@codav/slug-generator 1.0.4 → 1.0.6
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/index.js +42 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -108,11 +108,8 @@ function SlugGenerator({
|
|
|
108
108
|
onChange(createSlug(title, transliteratePersian));
|
|
109
109
|
};
|
|
110
110
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_clsx.default)("w-full space-y-1.5", className), children: [
|
|
111
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
112
|
-
|
|
113
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label })
|
|
114
|
-
] }),
|
|
115
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
|
|
111
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "flex items-center gap-2 text-sm font-medium text-(--color-text-primary)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label }) }),
|
|
112
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "group relative", children: [
|
|
116
113
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
117
114
|
"input",
|
|
118
115
|
{
|
|
@@ -128,15 +125,15 @@ function SlugGenerator({
|
|
|
128
125
|
}
|
|
129
126
|
},
|
|
130
127
|
className: (0, import_clsx.default)(
|
|
131
|
-
"w-full rounded-
|
|
128
|
+
"h-10 w-full rounded-xl border border-(--color-border)",
|
|
132
129
|
"bg-(--color-bg-main)",
|
|
133
|
-
"py-3 pe-4 ps-
|
|
130
|
+
"py-3 pe-4 ps-36",
|
|
134
131
|
"text-sm text-(--color-text-primary)",
|
|
135
|
-
"outline-none transition-all",
|
|
132
|
+
"outline-none transition-all duration-300",
|
|
136
133
|
"placeholder:text-(--color-text-secondary)/70",
|
|
137
|
-
"hover:border-[color-mix(in_oklab,var(--color-primary)
|
|
138
|
-
"focus:border-[color-mix(in_oklab,var(--color-primary)
|
|
139
|
-
"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)
|
|
134
|
+
"hover:border-[color-mix(in_oklab,var(--color-primary)_28%,var(--color-border))]",
|
|
135
|
+
"focus:border-[color-mix(in_oklab,var(--color-primary)_50%,var(--color-border))]",
|
|
136
|
+
"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)_10%,transparent)]",
|
|
140
137
|
"dark:bg-white/[0.03]",
|
|
141
138
|
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
142
139
|
)
|
|
@@ -148,21 +145,44 @@ function SlugGenerator({
|
|
|
148
145
|
type: "button",
|
|
149
146
|
onClick: handleGenerate,
|
|
150
147
|
disabled: disabled || !title.trim(),
|
|
148
|
+
"aria-label": buttonText,
|
|
151
149
|
className: (0, import_clsx.default)(
|
|
152
|
-
"absolute
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"text-xs font-
|
|
150
|
+
"absolute start-1.5 top-1/2 -translate-y-1/2",
|
|
151
|
+
"flex h-9 items-center gap-2 rounded-lg px-3.5",
|
|
152
|
+
"overflow-hidden",
|
|
153
|
+
"text-xs font-semibold text-white",
|
|
156
154
|
"bg-(--color-primary)",
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
155
|
+
"shadow-sm shadow-(--color-primary)/20",
|
|
156
|
+
"transition-all duration-300 ease-out",
|
|
157
|
+
"hover:-translate-y-1/2 hover:scale-[1.02]",
|
|
158
|
+
"hover:shadow-md hover:shadow-(--color-primary)/30",
|
|
159
|
+
"active:-translate-y-1/2 active:scale-[0.97]",
|
|
160
|
+
"focus:outline-none focus:ring-2 focus:ring-(--color-primary)/30",
|
|
161
|
+
"disabled:pointer-events-none disabled:opacity-40"
|
|
162
162
|
),
|
|
163
163
|
children: [
|
|
164
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
165
|
-
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
165
|
+
"span",
|
|
166
|
+
{
|
|
167
|
+
className: (0, import_clsx.default)(
|
|
168
|
+
"absolute inset-0 -translate-x-full",
|
|
169
|
+
"bg-gradient-to-r from-transparent via-white/20 to-transparent",
|
|
170
|
+
"transition-transform duration-700",
|
|
171
|
+
"group-hover:translate-x-full"
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
176
|
+
import_lucide_react.WandSparkles,
|
|
177
|
+
{
|
|
178
|
+
className: (0, import_clsx.default)(
|
|
179
|
+
"relative size-4 shrink-0",
|
|
180
|
+
"transition-transform duration-300",
|
|
181
|
+
"group-hover:rotate-12 group-hover:scale-110"
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative whitespace-nowrap", children: buttonText })
|
|
166
186
|
]
|
|
167
187
|
}
|
|
168
188
|
)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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 clsx from \"clsx\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nconst PERSIAN_MAP: Record<string, string> = {\r\n ا: \"a\",\r\n آ: \"a\",\r\n ب: \"b\",\r\n پ: \"p\",\r\n ت: \"t\",\r\n ث: \"s\",\r\n ج: \"j\",\r\n چ: \"ch\",\r\n ح: \"h\",\r\n خ: \"kh\",\r\n د: \"d\",\r\n ذ: \"z\",\r\n ر: \"r\",\r\n ز: \"z\",\r\n ژ: \"zh\",\r\n س: \"s\",\r\n ش: \"sh\",\r\n ص: \"s\",\r\n ض: \"z\",\r\n ط: \"t\",\r\n ظ: \"z\",\r\n ع: \"a\",\r\n غ: \"gh\",\r\n ف: \"f\",\r\n ق: \"gh\",\r\n ک: \"k\",\r\n گ: \"g\",\r\n ل: \"l\",\r\n م: \"m\",\r\n ن: \"n\",\r\n و: \"v\",\r\n ه: \"h\",\r\n ی: \"y\",\r\n ئ: \"y\",\r\n ء: \"a\",\r\n ۀ: \"h\",\r\n ة: \"h\",\r\n ي: \"y\",\r\n ك: \"k\",\r\n};\r\n\r\nconst ARABIC_DIACRITICS = /[\\u064B-\\u065F\\u0670]/g;\r\n\r\nfunction transliterate(text: string): string {\r\n return text\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\")\r\n .split(\"\")\r\n .map((char) => PERSIAN_MAP[char] ?? char)\r\n .join(\"\");\r\n}\r\n\r\nexport function createSlug(\r\n title: string,\r\n transliteratePersian = true,\r\n): string {\r\n let source = title\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\");\r\n\r\n if (transliteratePersian) {\r\n source = transliterate(source);\r\n }\r\n\r\n return source\r\n .toLowerCase()\r\n .trim()\r\n .replace(/['’`\"]/g, \"\")\r\n .replace(/[^a-z0-9\\s-]/g, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\");\r\n}\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 dir = \"ltr\",\r\n transliteratePersian = true,\r\n}: SlugGeneratorProps) {\r\n const handleGenerate = () => {\r\n if (!title.trim() || disabled) return;\r\n\r\n onChange(createSlug(title, transliteratePersian));\r\n };\r\n\r\n return (\r\n <div className={clsx(\"w-full space-y-1.5\", className)}>\r\n {label && (\r\n <label className=\"flex items-center gap-2 text-sm font-medium text-(--color-text-primary)\"
|
|
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 clsx from \"clsx\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nconst PERSIAN_MAP: Record<string, string> = {\r\n ا: \"a\",\r\n آ: \"a\",\r\n ب: \"b\",\r\n پ: \"p\",\r\n ت: \"t\",\r\n ث: \"s\",\r\n ج: \"j\",\r\n چ: \"ch\",\r\n ح: \"h\",\r\n خ: \"kh\",\r\n د: \"d\",\r\n ذ: \"z\",\r\n ر: \"r\",\r\n ز: \"z\",\r\n ژ: \"zh\",\r\n س: \"s\",\r\n ش: \"sh\",\r\n ص: \"s\",\r\n ض: \"z\",\r\n ط: \"t\",\r\n ظ: \"z\",\r\n ع: \"a\",\r\n غ: \"gh\",\r\n ف: \"f\",\r\n ق: \"gh\",\r\n ک: \"k\",\r\n گ: \"g\",\r\n ل: \"l\",\r\n م: \"m\",\r\n ن: \"n\",\r\n و: \"v\",\r\n ه: \"h\",\r\n ی: \"y\",\r\n ئ: \"y\",\r\n ء: \"a\",\r\n ۀ: \"h\",\r\n ة: \"h\",\r\n ي: \"y\",\r\n ك: \"k\",\r\n};\r\n\r\nconst ARABIC_DIACRITICS = /[\\u064B-\\u065F\\u0670]/g;\r\n\r\nfunction transliterate(text: string): string {\r\n return text\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\")\r\n .split(\"\")\r\n .map((char) => PERSIAN_MAP[char] ?? char)\r\n .join(\"\");\r\n}\r\n\r\nexport function createSlug(\r\n title: string,\r\n transliteratePersian = true,\r\n): string {\r\n let source = title\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\");\r\n\r\n if (transliteratePersian) {\r\n source = transliterate(source);\r\n }\r\n\r\n return source\r\n .toLowerCase()\r\n .trim()\r\n .replace(/['’`\"]/g, \"\")\r\n .replace(/[^a-z0-9\\s-]/g, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\");\r\n}\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 dir = \"ltr\",\r\n transliteratePersian = true,\r\n}: SlugGeneratorProps) {\r\n const handleGenerate = () => {\r\n if (!title.trim() || disabled) return;\r\n\r\n onChange(createSlug(title, transliteratePersian));\r\n };\r\n\r\n return (\r\n <div className={clsx(\"w-full space-y-1.5\", className)}>\r\n {label && (\r\n <label className=\"flex items-center gap-2 text-sm font-medium text-(--color-text-primary)\"> \r\n <span>{label}</span>\r\n </label>\r\n )}\r\n\r\n <div className=\"group relative\">\r\n <input\r\n dir={dir}\r\n value={value}\r\n onChange={(event) => onChange(event.target.value)}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n onKeyDown={(event) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n handleGenerate();\r\n }\r\n }}\r\n className={clsx(\r\n \"h-10 w-full rounded-xl border border-(--color-border)\",\r\n \"bg-(--color-bg-main)\",\r\n \"py-3 pe-4 ps-36\",\r\n \"text-sm text-(--color-text-primary)\",\r\n \"outline-none transition-all duration-300\",\r\n \"placeholder:text-(--color-text-secondary)/70\",\r\n \"hover:border-[color-mix(in_oklab,var(--color-primary)_28%,var(--color-border))]\",\r\n \"focus:border-[color-mix(in_oklab,var(--color-primary)_50%,var(--color-border))]\",\r\n \"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)_10%,transparent)]\",\r\n \"dark:bg-white/[0.03]\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50\",\r\n )}\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleGenerate}\r\n disabled={disabled || !title.trim()}\r\n aria-label={buttonText}\r\n className={clsx(\r\n \"absolute start-1.5 top-1/2 -translate-y-1/2\",\r\n \"flex h-9 items-center gap-2 rounded-lg px-3.5\",\r\n \"overflow-hidden\",\r\n \"text-xs font-semibold text-white\",\r\n \"bg-(--color-primary)\",\r\n \"shadow-sm shadow-(--color-primary)/20\",\r\n \"transition-all duration-300 ease-out\",\r\n \"hover:-translate-y-1/2 hover:scale-[1.02]\",\r\n \"hover:shadow-md hover:shadow-(--color-primary)/30\",\r\n \"active:-translate-y-1/2 active:scale-[0.97]\",\r\n \"focus:outline-none focus:ring-2 focus:ring-(--color-primary)/30\",\r\n \"disabled:pointer-events-none disabled:opacity-40\",\r\n )}\r\n >\r\n <span\r\n className={clsx(\r\n \"absolute inset-0 -translate-x-full\",\r\n \"bg-gradient-to-r from-transparent via-white/20 to-transparent\",\r\n \"transition-transform duration-700\",\r\n \"group-hover:translate-x-full\",\r\n )}\r\n />\r\n\r\n <WandSparkles\r\n className={clsx(\r\n \"relative size-4 shrink-0\",\r\n \"transition-transform duration-300\",\r\n \"group-hover:rotate-12 group-hover:scale-110\",\r\n )}\r\n />\r\n\r\n <span className=\"relative whitespace-nowrap\">\r\n {buttonText}\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}"],"mappings":"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","names":["clsx"]}
|
package/dist/index.mjs
CHANGED
|
@@ -72,11 +72,8 @@ function SlugGenerator({
|
|
|
72
72
|
onChange(createSlug(title, transliteratePersian));
|
|
73
73
|
};
|
|
74
74
|
return /* @__PURE__ */ jsxs("div", { className: clsx("w-full space-y-1.5", className), children: [
|
|
75
|
-
label && /* @__PURE__ */
|
|
76
|
-
|
|
77
|
-
/* @__PURE__ */ jsx("span", { children: label })
|
|
78
|
-
] }),
|
|
79
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
75
|
+
label && /* @__PURE__ */ jsx("label", { className: "flex items-center gap-2 text-sm font-medium text-(--color-text-primary)", children: /* @__PURE__ */ jsx("span", { children: label }) }),
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: "group relative", children: [
|
|
80
77
|
/* @__PURE__ */ jsx(
|
|
81
78
|
"input",
|
|
82
79
|
{
|
|
@@ -92,15 +89,15 @@ function SlugGenerator({
|
|
|
92
89
|
}
|
|
93
90
|
},
|
|
94
91
|
className: clsx(
|
|
95
|
-
"w-full rounded-
|
|
92
|
+
"h-10 w-full rounded-xl border border-(--color-border)",
|
|
96
93
|
"bg-(--color-bg-main)",
|
|
97
|
-
"py-3 pe-4 ps-
|
|
94
|
+
"py-3 pe-4 ps-36",
|
|
98
95
|
"text-sm text-(--color-text-primary)",
|
|
99
|
-
"outline-none transition-all",
|
|
96
|
+
"outline-none transition-all duration-300",
|
|
100
97
|
"placeholder:text-(--color-text-secondary)/70",
|
|
101
|
-
"hover:border-[color-mix(in_oklab,var(--color-primary)
|
|
102
|
-
"focus:border-[color-mix(in_oklab,var(--color-primary)
|
|
103
|
-
"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)
|
|
98
|
+
"hover:border-[color-mix(in_oklab,var(--color-primary)_28%,var(--color-border))]",
|
|
99
|
+
"focus:border-[color-mix(in_oklab,var(--color-primary)_50%,var(--color-border))]",
|
|
100
|
+
"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)_10%,transparent)]",
|
|
104
101
|
"dark:bg-white/[0.03]",
|
|
105
102
|
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
106
103
|
)
|
|
@@ -112,21 +109,44 @@ function SlugGenerator({
|
|
|
112
109
|
type: "button",
|
|
113
110
|
onClick: handleGenerate,
|
|
114
111
|
disabled: disabled || !title.trim(),
|
|
112
|
+
"aria-label": buttonText,
|
|
115
113
|
className: clsx(
|
|
116
|
-
"absolute
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"text-xs font-
|
|
114
|
+
"absolute start-1.5 top-1/2 -translate-y-1/2",
|
|
115
|
+
"flex h-9 items-center gap-2 rounded-lg px-3.5",
|
|
116
|
+
"overflow-hidden",
|
|
117
|
+
"text-xs font-semibold text-white",
|
|
120
118
|
"bg-(--color-primary)",
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
119
|
+
"shadow-sm shadow-(--color-primary)/20",
|
|
120
|
+
"transition-all duration-300 ease-out",
|
|
121
|
+
"hover:-translate-y-1/2 hover:scale-[1.02]",
|
|
122
|
+
"hover:shadow-md hover:shadow-(--color-primary)/30",
|
|
123
|
+
"active:-translate-y-1/2 active:scale-[0.97]",
|
|
124
|
+
"focus:outline-none focus:ring-2 focus:ring-(--color-primary)/30",
|
|
125
|
+
"disabled:pointer-events-none disabled:opacity-40"
|
|
126
126
|
),
|
|
127
127
|
children: [
|
|
128
|
-
/* @__PURE__ */ jsx(
|
|
129
|
-
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
"span",
|
|
130
|
+
{
|
|
131
|
+
className: clsx(
|
|
132
|
+
"absolute inset-0 -translate-x-full",
|
|
133
|
+
"bg-gradient-to-r from-transparent via-white/20 to-transparent",
|
|
134
|
+
"transition-transform duration-700",
|
|
135
|
+
"group-hover:translate-x-full"
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
),
|
|
139
|
+
/* @__PURE__ */ jsx(
|
|
140
|
+
WandSparkles,
|
|
141
|
+
{
|
|
142
|
+
className: clsx(
|
|
143
|
+
"relative size-4 shrink-0",
|
|
144
|
+
"transition-transform duration-300",
|
|
145
|
+
"group-hover:rotate-12 group-hover:scale-110"
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
),
|
|
149
|
+
/* @__PURE__ */ jsx("span", { className: "relative whitespace-nowrap", children: buttonText })
|
|
130
150
|
]
|
|
131
151
|
}
|
|
132
152
|
)
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/SlugGenerator.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { WandSparkles } from \"lucide-react\";\r\nimport clsx from \"clsx\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nconst PERSIAN_MAP: Record<string, string> = {\r\n ا: \"a\",\r\n آ: \"a\",\r\n ب: \"b\",\r\n پ: \"p\",\r\n ت: \"t\",\r\n ث: \"s\",\r\n ج: \"j\",\r\n چ: \"ch\",\r\n ح: \"h\",\r\n خ: \"kh\",\r\n د: \"d\",\r\n ذ: \"z\",\r\n ر: \"r\",\r\n ز: \"z\",\r\n ژ: \"zh\",\r\n س: \"s\",\r\n ش: \"sh\",\r\n ص: \"s\",\r\n ض: \"z\",\r\n ط: \"t\",\r\n ظ: \"z\",\r\n ع: \"a\",\r\n غ: \"gh\",\r\n ف: \"f\",\r\n ق: \"gh\",\r\n ک: \"k\",\r\n گ: \"g\",\r\n ل: \"l\",\r\n م: \"m\",\r\n ن: \"n\",\r\n و: \"v\",\r\n ه: \"h\",\r\n ی: \"y\",\r\n ئ: \"y\",\r\n ء: \"a\",\r\n ۀ: \"h\",\r\n ة: \"h\",\r\n ي: \"y\",\r\n ك: \"k\",\r\n};\r\n\r\nconst ARABIC_DIACRITICS = /[\\u064B-\\u065F\\u0670]/g;\r\n\r\nfunction transliterate(text: string): string {\r\n return text\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\")\r\n .split(\"\")\r\n .map((char) => PERSIAN_MAP[char] ?? char)\r\n .join(\"\");\r\n}\r\n\r\nexport function createSlug(\r\n title: string,\r\n transliteratePersian = true,\r\n): string {\r\n let source = title\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\");\r\n\r\n if (transliteratePersian) {\r\n source = transliterate(source);\r\n }\r\n\r\n return source\r\n .toLowerCase()\r\n .trim()\r\n .replace(/['’`\"]/g, \"\")\r\n .replace(/[^a-z0-9\\s-]/g, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\");\r\n}\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 dir = \"ltr\",\r\n transliteratePersian = true,\r\n}: SlugGeneratorProps) {\r\n const handleGenerate = () => {\r\n if (!title.trim() || disabled) return;\r\n\r\n onChange(createSlug(title, transliteratePersian));\r\n };\r\n\r\n return (\r\n <div className={clsx(\"w-full space-y-1.5\", className)}>\r\n {label && (\r\n <label className=\"flex items-center gap-2 text-sm font-medium text-(--color-text-primary)\"
|
|
1
|
+
{"version":3,"sources":["../src/SlugGenerator.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { WandSparkles } from \"lucide-react\";\r\nimport clsx from \"clsx\";\r\nimport type { SlugGeneratorProps } from \"./types\";\r\n\r\nconst PERSIAN_MAP: Record<string, string> = {\r\n ا: \"a\",\r\n آ: \"a\",\r\n ب: \"b\",\r\n پ: \"p\",\r\n ت: \"t\",\r\n ث: \"s\",\r\n ج: \"j\",\r\n چ: \"ch\",\r\n ح: \"h\",\r\n خ: \"kh\",\r\n د: \"d\",\r\n ذ: \"z\",\r\n ر: \"r\",\r\n ز: \"z\",\r\n ژ: \"zh\",\r\n س: \"s\",\r\n ش: \"sh\",\r\n ص: \"s\",\r\n ض: \"z\",\r\n ط: \"t\",\r\n ظ: \"z\",\r\n ع: \"a\",\r\n غ: \"gh\",\r\n ف: \"f\",\r\n ق: \"gh\",\r\n ک: \"k\",\r\n گ: \"g\",\r\n ل: \"l\",\r\n م: \"m\",\r\n ن: \"n\",\r\n و: \"v\",\r\n ه: \"h\",\r\n ی: \"y\",\r\n ئ: \"y\",\r\n ء: \"a\",\r\n ۀ: \"h\",\r\n ة: \"h\",\r\n ي: \"y\",\r\n ك: \"k\",\r\n};\r\n\r\nconst ARABIC_DIACRITICS = /[\\u064B-\\u065F\\u0670]/g;\r\n\r\nfunction transliterate(text: string): string {\r\n return text\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\")\r\n .split(\"\")\r\n .map((char) => PERSIAN_MAP[char] ?? char)\r\n .join(\"\");\r\n}\r\n\r\nexport function createSlug(\r\n title: string,\r\n transliteratePersian = true,\r\n): string {\r\n let source = title\r\n .normalize(\"NFKC\")\r\n .replace(ARABIC_DIACRITICS, \"\");\r\n\r\n if (transliteratePersian) {\r\n source = transliterate(source);\r\n }\r\n\r\n return source\r\n .toLowerCase()\r\n .trim()\r\n .replace(/['’`\"]/g, \"\")\r\n .replace(/[^a-z0-9\\s-]/g, \"\")\r\n .replace(/\\s+/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\");\r\n}\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 dir = \"ltr\",\r\n transliteratePersian = true,\r\n}: SlugGeneratorProps) {\r\n const handleGenerate = () => {\r\n if (!title.trim() || disabled) return;\r\n\r\n onChange(createSlug(title, transliteratePersian));\r\n };\r\n\r\n return (\r\n <div className={clsx(\"w-full space-y-1.5\", className)}>\r\n {label && (\r\n <label className=\"flex items-center gap-2 text-sm font-medium text-(--color-text-primary)\"> \r\n <span>{label}</span>\r\n </label>\r\n )}\r\n\r\n <div className=\"group relative\">\r\n <input\r\n dir={dir}\r\n value={value}\r\n onChange={(event) => onChange(event.target.value)}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n onKeyDown={(event) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n handleGenerate();\r\n }\r\n }}\r\n className={clsx(\r\n \"h-10 w-full rounded-xl border border-(--color-border)\",\r\n \"bg-(--color-bg-main)\",\r\n \"py-3 pe-4 ps-36\",\r\n \"text-sm text-(--color-text-primary)\",\r\n \"outline-none transition-all duration-300\",\r\n \"placeholder:text-(--color-text-secondary)/70\",\r\n \"hover:border-[color-mix(in_oklab,var(--color-primary)_28%,var(--color-border))]\",\r\n \"focus:border-[color-mix(in_oklab,var(--color-primary)_50%,var(--color-border))]\",\r\n \"focus:ring-4 focus:ring-[color-mix(in_oklab,var(--color-primary)_10%,transparent)]\",\r\n \"dark:bg-white/[0.03]\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50\",\r\n )}\r\n />\r\n\r\n <button\r\n type=\"button\"\r\n onClick={handleGenerate}\r\n disabled={disabled || !title.trim()}\r\n aria-label={buttonText}\r\n className={clsx(\r\n \"absolute start-1.5 top-1/2 -translate-y-1/2\",\r\n \"flex h-9 items-center gap-2 rounded-lg px-3.5\",\r\n \"overflow-hidden\",\r\n \"text-xs font-semibold text-white\",\r\n \"bg-(--color-primary)\",\r\n \"shadow-sm shadow-(--color-primary)/20\",\r\n \"transition-all duration-300 ease-out\",\r\n \"hover:-translate-y-1/2 hover:scale-[1.02]\",\r\n \"hover:shadow-md hover:shadow-(--color-primary)/30\",\r\n \"active:-translate-y-1/2 active:scale-[0.97]\",\r\n \"focus:outline-none focus:ring-2 focus:ring-(--color-primary)/30\",\r\n \"disabled:pointer-events-none disabled:opacity-40\",\r\n )}\r\n >\r\n <span\r\n className={clsx(\r\n \"absolute inset-0 -translate-x-full\",\r\n \"bg-gradient-to-r from-transparent via-white/20 to-transparent\",\r\n \"transition-transform duration-700\",\r\n \"group-hover:translate-x-full\",\r\n )}\r\n />\r\n\r\n <WandSparkles\r\n className={clsx(\r\n \"relative size-4 shrink-0\",\r\n \"transition-transform duration-300\",\r\n \"group-hover:rotate-12 group-hover:scale-110\",\r\n )}\r\n />\r\n\r\n <span className=\"relative whitespace-nowrap\">\r\n {buttonText}\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codav/slug-generator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "A lightweight, reusable TypeScript-first React slug generator component",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -25,5 +25,8 @@
|
|
|
25
25
|
"tsup": "^8.0.0",
|
|
26
26
|
"typescript": "^5.0.0"
|
|
27
27
|
},
|
|
28
|
-
"license": "MIT"
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@codav/slug-generator": "file:codav-slug-generator-1.0.4.tgz"
|
|
31
|
+
}
|
|
29
32
|
}
|