@codav/slug-generator 1.0.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/README.md +217 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +55 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# @codav/slug-generator
|
|
2
|
+
|
|
3
|
+
A lightweight, reusable and TypeScript-first React component for generating clean, URL-friendly slugs directly from titles.
|
|
4
|
+
|
|
5
|
+
Built for modern React and Next.js applications with a simple API, zero unnecessary complexity, and easy integration.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
- Generate slugs directly from titles
|
|
10
|
+
- Supports Persian, English, numbers and Unicode characters
|
|
11
|
+
- Automatically removes unnecessary characters
|
|
12
|
+
- Converts spaces into `-`
|
|
13
|
+
- Prevents duplicate hyphens
|
|
14
|
+
- Removes leading and trailing hyphens
|
|
15
|
+
- Fully controlled React component
|
|
16
|
+
- Written in TypeScript
|
|
17
|
+
- React 18 and React 19 compatible
|
|
18
|
+
- Next.js compatible
|
|
19
|
+
- Customizable labels and button text
|
|
20
|
+
- Supports custom classes
|
|
21
|
+
- Lightweight package architecture
|
|
22
|
+
- ESM and CommonJS builds
|
|
23
|
+
- Built-in TypeScript declarations
|
|
24
|
+
|
|
25
|
+
## 📦 Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @codav/slug-generator
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
yarn add @codav/slug-generator
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm add @codav/slug-generator
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 🚀 Basic Usage
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
"use client";
|
|
45
|
+
|
|
46
|
+
import { useState } from "react";
|
|
47
|
+
import { SlugGenerator } from "@codav/slug-generator";
|
|
48
|
+
|
|
49
|
+
export default function Example() {
|
|
50
|
+
const [title, setTitle] = useState("");
|
|
51
|
+
const [slug, setSlug] = useState("");
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<SlugGenerator
|
|
55
|
+
title={title}
|
|
56
|
+
value={slug}
|
|
57
|
+
onChange={setSlug}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🧩 With a Title Input
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
"use client";
|
|
67
|
+
|
|
68
|
+
import { useState } from "react";
|
|
69
|
+
import { SlugGenerator } from "@codav/slug-generator";
|
|
70
|
+
|
|
71
|
+
export default function BlogForm() {
|
|
72
|
+
const [title, setTitle] = useState("");
|
|
73
|
+
const [slug, setSlug] = useState("");
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div>
|
|
77
|
+
<input
|
|
78
|
+
value={title}
|
|
79
|
+
onChange={(event) => setTitle(event.target.value)}
|
|
80
|
+
placeholder="Article title"
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
<SlugGenerator
|
|
84
|
+
title={title}
|
|
85
|
+
value={slug}
|
|
86
|
+
onChange={setSlug}
|
|
87
|
+
label="Slug"
|
|
88
|
+
buttonText="Generate Slug"
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 🌍 Persian Support
|
|
96
|
+
|
|
97
|
+
The component is designed to work with Unicode text, making it suitable for Persian and other non-Latin languages.
|
|
98
|
+
|
|
99
|
+
For example:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
آموزش لاراول برای مبتدیان
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
can become:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
آموزش-لاراول-برای-مبتدیان
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
English titles are supported as well:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
Learn Laravel From Scratch
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
becomes:
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
learn-laravel-from-scratch
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## ⚙️ API
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Default | Description |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| `title` | `string` | — | Source title used to generate the slug |
|
|
128
|
+
| `value` | `string` | — | Current slug value |
|
|
129
|
+
| `onChange` | `(slug: string) => void` | — | Called when the slug changes |
|
|
130
|
+
| `label` | `string` | `"Slug"` | Input label |
|
|
131
|
+
| `placeholder` | `string` | `"your-slug"` | Input placeholder |
|
|
132
|
+
| `buttonText` | `string` | `"Generate"` | Generate button text |
|
|
133
|
+
| `disabled` | `boolean` | `false` | Disables the component |
|
|
134
|
+
| `className` | `string` | `""` | Custom CSS class |
|
|
135
|
+
| `icon` | `ReactNode` | — | Optional label icon |
|
|
136
|
+
|
|
137
|
+
## 🏗️ Build From Source
|
|
138
|
+
|
|
139
|
+
Clone the repository:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git clone https://github.com/YOUR_USERNAME/slug-generator.git
|
|
143
|
+
cd slug-generator
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Install dependencies:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npm install
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Build the package:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm run build
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Development mode:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm run dev
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 📁 Package Architecture
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
slug-generator/
|
|
168
|
+
├── src/
|
|
169
|
+
│ ├── SlugGenerator.tsx
|
|
170
|
+
│ ├── index.ts
|
|
171
|
+
│ └── types.ts
|
|
172
|
+
├── package.json
|
|
173
|
+
├── tsconfig.json
|
|
174
|
+
├── tsup.config.ts
|
|
175
|
+
└── README.md
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 🎯 Design Philosophy
|
|
179
|
+
|
|
180
|
+
`@codav/slug-generator` is intentionally focused on one responsibility:
|
|
181
|
+
|
|
182
|
+
> Convert user-provided titles into clean, URL-friendly slugs through a reusable React component.
|
|
183
|
+
|
|
184
|
+
The package is designed to remain independent from any specific CMS, blog system, backend framework, database or application architecture.
|
|
185
|
+
|
|
186
|
+
This makes it suitable for:
|
|
187
|
+
|
|
188
|
+
- Blogs
|
|
189
|
+
- Products
|
|
190
|
+
- Categories
|
|
191
|
+
- Pages
|
|
192
|
+
- Courses
|
|
193
|
+
- Documentation
|
|
194
|
+
- News systems
|
|
195
|
+
- E-commerce platforms
|
|
196
|
+
- Admin dashboards
|
|
197
|
+
- Content management systems
|
|
198
|
+
|
|
199
|
+
## 🛠️ Tech Stack
|
|
200
|
+
|
|
201
|
+
- React
|
|
202
|
+
- TypeScript
|
|
203
|
+
- tsup
|
|
204
|
+
- ESM
|
|
205
|
+
- CommonJS
|
|
206
|
+
|
|
207
|
+
## 📄 License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
210
|
+
|
|
211
|
+
## 👨💻 Author
|
|
212
|
+
|
|
213
|
+
Developed and maintained by **CODAV**.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
If you find this package useful, consider giving the repository a ⭐ on GitHub.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type SlugGeneratorProps = {
|
|
5
|
+
title: string;
|
|
6
|
+
value: string;
|
|
7
|
+
onChange: (slug: string) => void;
|
|
8
|
+
label?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
buttonText?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
declare function SlugGenerator({ title, value, onChange, label, placeholder, buttonText, disabled, className, icon, }: SlugGeneratorProps): react.JSX.Element;
|
|
17
|
+
|
|
18
|
+
export { SlugGenerator, type SlugGeneratorProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type SlugGeneratorProps = {
|
|
5
|
+
title: string;
|
|
6
|
+
value: string;
|
|
7
|
+
onChange: (slug: string) => void;
|
|
8
|
+
label?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
buttonText?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
declare function SlugGenerator({ title, value, onChange, label, placeholder, buttonText, disabled, className, icon, }: SlugGeneratorProps): react.JSX.Element;
|
|
17
|
+
|
|
18
|
+
export { SlugGenerator, type SlugGeneratorProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SlugGenerator: () => SlugGenerator
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/SlugGenerator.tsx
|
|
28
|
+
var import_lucide_react = require("lucide-react");
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
function SlugGenerator({
|
|
31
|
+
title,
|
|
32
|
+
value,
|
|
33
|
+
onChange,
|
|
34
|
+
label = "Slug",
|
|
35
|
+
placeholder = "your-slug",
|
|
36
|
+
buttonText = "Generate",
|
|
37
|
+
disabled = false,
|
|
38
|
+
className = "",
|
|
39
|
+
icon
|
|
40
|
+
}) {
|
|
41
|
+
const generateSlug = () => {
|
|
42
|
+
const slug = title.toLowerCase().trim().replace(/[^\p{L}\p{N}\s-]/gu, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
43
|
+
onChange(slug);
|
|
44
|
+
};
|
|
45
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, children: [
|
|
46
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
47
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "text-sm font-medium", children: [
|
|
48
|
+
icon,
|
|
49
|
+
label
|
|
50
|
+
] }),
|
|
51
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
52
|
+
"button",
|
|
53
|
+
{
|
|
54
|
+
type: "button",
|
|
55
|
+
onClick: generateSlug,
|
|
56
|
+
disabled: disabled || !title.trim(),
|
|
57
|
+
className: "inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-medium transition disabled:cursor-not-allowed disabled:opacity-50",
|
|
58
|
+
children: [
|
|
59
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.WandSparkles, { className: "size-4" }),
|
|
60
|
+
buttonText
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
66
|
+
"input",
|
|
67
|
+
{
|
|
68
|
+
dir: "ltr",
|
|
69
|
+
value,
|
|
70
|
+
onChange: (event) => onChange(event.target.value),
|
|
71
|
+
placeholder,
|
|
72
|
+
disabled,
|
|
73
|
+
className: "w-full rounded-lg border px-3 py-3 text-sm outline-none"
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
79
|
+
0 && (module.exports = {
|
|
80
|
+
SlugGenerator
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/SlugGenerator.tsx"],"sourcesContent":["export { default as SlugGenerator } from \"./SlugGenerator\";\r\nexport type { SlugGeneratorProps } from \"./types\";","\"use client\";\r\n\r\nimport { WandSparkles } from \"lucide-react\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nexport default function SlugGenerator({\r\n title,\r\n value,\r\n onChange,\r\n label = \"Slug\",\r\n placeholder = \"your-slug\",\r\n buttonText = \"Generate\",\r\n disabled = false,\r\n className = \"\",\r\n icon,\r\n}: SlugGeneratorProps) {\r\n const generateSlug = () => {\r\n const slug = title\r\n .toLowerCase()\r\n .trim()\r\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-|-$/g, \"\");\r\n\r\n onChange(slug);\r\n };\r\n\r\n return (\r\n <div className={className}>\r\n <div className=\"mb-2 flex items-center justify-between gap-3\">\r\n <label className=\"text-sm font-medium\">\r\n {icon}\r\n {label}\r\n </label>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={generateSlug}\r\n disabled={disabled || !title.trim()}\r\n className=\"inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-medium transition disabled:cursor-not-allowed disabled:opacity-50\"\r\n >\r\n <WandSparkles className=\"size-4\" />\r\n {buttonText}\r\n </button>\r\n </div>\r\n\r\n <input\r\n dir=\"ltr\"\r\n value={value}\r\n onChange={(event) => onChange(event.target.value)}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n className=\"w-full rounded-lg border px-3 py-3 text-sm outline-none\"\r\n />\r\n </div>\r\n );\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,0BAA6B;AA6BrB;AA1BO,SAAR,cAA+B;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AACF,GAAuB;AACrB,QAAM,eAAe,MAAM;AACzB,UAAM,OAAO,MACV,YAAY,EACZ,KAAK,EACL,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,QAAQ,GAAG,EACnB,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AAEvB,aAAS,IAAI;AAAA,EACf;AAEA,SACE,6CAAC,SAAI,WACH;AAAA,iDAAC,SAAI,WAAU,gDACb;AAAA,mDAAC,WAAM,WAAU,uBACd;AAAA;AAAA,QACA;AAAA,SACH;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU,YAAY,CAAC,MAAM,KAAK;AAAA,UAClC,WAAU;AAAA,UAEV;AAAA,wDAAC,oCAAa,WAAU,UAAS;AAAA,YAChC;AAAA;AAAA;AAAA,MACH;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ;AAAA,QACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAChD;AAAA,QACA;AAAA,QACA,WAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/SlugGenerator.tsx
|
|
2
|
+
import { WandSparkles } from "lucide-react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
function SlugGenerator({
|
|
5
|
+
title,
|
|
6
|
+
value,
|
|
7
|
+
onChange,
|
|
8
|
+
label = "Slug",
|
|
9
|
+
placeholder = "your-slug",
|
|
10
|
+
buttonText = "Generate",
|
|
11
|
+
disabled = false,
|
|
12
|
+
className = "",
|
|
13
|
+
icon
|
|
14
|
+
}) {
|
|
15
|
+
const generateSlug = () => {
|
|
16
|
+
const slug = title.toLowerCase().trim().replace(/[^\p{L}\p{N}\s-]/gu, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
17
|
+
onChange(slug);
|
|
18
|
+
};
|
|
19
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
20
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
21
|
+
/* @__PURE__ */ jsxs("label", { className: "text-sm font-medium", children: [
|
|
22
|
+
icon,
|
|
23
|
+
label
|
|
24
|
+
] }),
|
|
25
|
+
/* @__PURE__ */ jsxs(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
onClick: generateSlug,
|
|
30
|
+
disabled: disabled || !title.trim(),
|
|
31
|
+
className: "inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-medium transition disabled:cursor-not-allowed disabled:opacity-50",
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx(WandSparkles, { className: "size-4" }),
|
|
34
|
+
buttonText
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
] }),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"input",
|
|
41
|
+
{
|
|
42
|
+
dir: "ltr",
|
|
43
|
+
value,
|
|
44
|
+
onChange: (event) => onChange(event.target.value),
|
|
45
|
+
placeholder,
|
|
46
|
+
disabled,
|
|
47
|
+
className: "w-full rounded-lg border px-3 py-3 text-sm outline-none"
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
SlugGenerator
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SlugGenerator.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { WandSparkles } from \"lucide-react\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nexport default function SlugGenerator({\r\n title,\r\n value,\r\n onChange,\r\n label = \"Slug\",\r\n placeholder = \"your-slug\",\r\n buttonText = \"Generate\",\r\n disabled = false,\r\n className = \"\",\r\n icon,\r\n}: SlugGeneratorProps) {\r\n const generateSlug = () => {\r\n const slug = title\r\n .toLowerCase()\r\n .trim()\r\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-|-$/g, \"\");\r\n\r\n onChange(slug);\r\n };\r\n\r\n return (\r\n <div className={className}>\r\n <div className=\"mb-2 flex items-center justify-between gap-3\">\r\n <label className=\"text-sm font-medium\">\r\n {icon}\r\n {label}\r\n </label>\r\n\r\n <button\r\n type=\"button\"\r\n onClick={generateSlug}\r\n disabled={disabled || !title.trim()}\r\n className=\"inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-medium transition disabled:cursor-not-allowed disabled:opacity-50\"\r\n >\r\n <WandSparkles className=\"size-4\" />\r\n {buttonText}\r\n </button>\r\n </div>\r\n\r\n <input\r\n dir=\"ltr\"\r\n value={value}\r\n onChange={(event) => onChange(event.target.value)}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n className=\"w-full rounded-lg border px-3 py-3 text-sm outline-none\"\r\n />\r\n </div>\r\n );\r\n}"],"mappings":";AAEA,SAAS,oBAAoB;AA6BrB,SAWE,KAXF;AA1BO,SAAR,cAA+B;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AACF,GAAuB;AACrB,QAAM,eAAe,MAAM;AACzB,UAAM,OAAO,MACV,YAAY,EACZ,KAAK,EACL,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,QAAQ,GAAG,EACnB,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AAEvB,aAAS,IAAI;AAAA,EACf;AAEA,SACE,qBAAC,SAAI,WACH;AAAA,yBAAC,SAAI,WAAU,gDACb;AAAA,2BAAC,WAAM,WAAU,uBACd;AAAA;AAAA,QACA;AAAA,SACH;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU,YAAY,CAAC,MAAM,KAAK;AAAA,UAClC,WAAU;AAAA,UAEV;AAAA,gCAAC,gBAAa,WAAU,UAAS;AAAA,YAChC;AAAA;AAAA;AAAA,MACH;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ;AAAA,QACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAChD;AAAA,QACA;AAAA,QACA,WAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codav/slug-generator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight, reusable TypeScript-first React slug generator component",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"dev": "tsup --watch"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
17
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
18
|
+
"lucide-react": "^0.400.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/react": "^19.0.0",
|
|
22
|
+
"@types/react-dom": "^19.0.0",
|
|
23
|
+
"lucide-react": "^0.400.0",
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.0.0"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT"
|
|
28
|
+
}
|