tr-identity 0.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/index.d.mts +43 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +186 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +182 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +30 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
type TRIdType = 'TCKN' | 'VERGI_NO';
|
|
2
|
+
declare const TRIdError: {
|
|
3
|
+
readonly INVALID_FORMAT: "INVALID_FORMAT";
|
|
4
|
+
readonly INVALID_CHECKSUM: "INVALID_CHECKSUM";
|
|
5
|
+
readonly TOO_SHORT: "TOO_SHORT";
|
|
6
|
+
readonly TOO_LONG: "TOO_LONG";
|
|
7
|
+
readonly INCOMPLETE: "INCOMPLETE";
|
|
8
|
+
};
|
|
9
|
+
type TRIdError = (typeof TRIdError)[keyof typeof TRIdError];
|
|
10
|
+
interface TRIdResult {
|
|
11
|
+
type: TRIdType | null;
|
|
12
|
+
valid: boolean;
|
|
13
|
+
completed: string | null;
|
|
14
|
+
suggestion: string | null;
|
|
15
|
+
original: string;
|
|
16
|
+
error?: TRIdError;
|
|
17
|
+
}
|
|
18
|
+
declare function processTRId(input: string | number | null | undefined, hint?: TRIdType): TRIdResult;
|
|
19
|
+
|
|
20
|
+
type IdentityStatus = 'idle' | 'typing' | 'valid' | 'autocompleted' | 'invalid';
|
|
21
|
+
interface IdentityState {
|
|
22
|
+
status: IdentityStatus;
|
|
23
|
+
type: TRIdType | null;
|
|
24
|
+
completed: string | null;
|
|
25
|
+
suggestion: string | null;
|
|
26
|
+
error: TRIdError | null;
|
|
27
|
+
}
|
|
28
|
+
interface UseIdentityOptions {
|
|
29
|
+
debounceMs?: number;
|
|
30
|
+
onCommit?: (value: string) => void;
|
|
31
|
+
}
|
|
32
|
+
interface UseIdentityReturn {
|
|
33
|
+
raw: string;
|
|
34
|
+
state: IdentityState;
|
|
35
|
+
detectedLabel: string | null;
|
|
36
|
+
errorMessage: string | null;
|
|
37
|
+
handleChange: (value: string) => void;
|
|
38
|
+
applySuggestion: () => void;
|
|
39
|
+
reset: () => void;
|
|
40
|
+
}
|
|
41
|
+
declare function useIdentity({ debounceMs, onCommit, }?: UseIdentityOptions): UseIdentityReturn;
|
|
42
|
+
|
|
43
|
+
export { type IdentityState, TRIdError, type TRIdResult, type TRIdType, type UseIdentityOptions, type UseIdentityReturn, processTRId, useIdentity };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
type TRIdType = 'TCKN' | 'VERGI_NO';
|
|
2
|
+
declare const TRIdError: {
|
|
3
|
+
readonly INVALID_FORMAT: "INVALID_FORMAT";
|
|
4
|
+
readonly INVALID_CHECKSUM: "INVALID_CHECKSUM";
|
|
5
|
+
readonly TOO_SHORT: "TOO_SHORT";
|
|
6
|
+
readonly TOO_LONG: "TOO_LONG";
|
|
7
|
+
readonly INCOMPLETE: "INCOMPLETE";
|
|
8
|
+
};
|
|
9
|
+
type TRIdError = (typeof TRIdError)[keyof typeof TRIdError];
|
|
10
|
+
interface TRIdResult {
|
|
11
|
+
type: TRIdType | null;
|
|
12
|
+
valid: boolean;
|
|
13
|
+
completed: string | null;
|
|
14
|
+
suggestion: string | null;
|
|
15
|
+
original: string;
|
|
16
|
+
error?: TRIdError;
|
|
17
|
+
}
|
|
18
|
+
declare function processTRId(input: string | number | null | undefined, hint?: TRIdType): TRIdResult;
|
|
19
|
+
|
|
20
|
+
type IdentityStatus = 'idle' | 'typing' | 'valid' | 'autocompleted' | 'invalid';
|
|
21
|
+
interface IdentityState {
|
|
22
|
+
status: IdentityStatus;
|
|
23
|
+
type: TRIdType | null;
|
|
24
|
+
completed: string | null;
|
|
25
|
+
suggestion: string | null;
|
|
26
|
+
error: TRIdError | null;
|
|
27
|
+
}
|
|
28
|
+
interface UseIdentityOptions {
|
|
29
|
+
debounceMs?: number;
|
|
30
|
+
onCommit?: (value: string) => void;
|
|
31
|
+
}
|
|
32
|
+
interface UseIdentityReturn {
|
|
33
|
+
raw: string;
|
|
34
|
+
state: IdentityState;
|
|
35
|
+
detectedLabel: string | null;
|
|
36
|
+
errorMessage: string | null;
|
|
37
|
+
handleChange: (value: string) => void;
|
|
38
|
+
applySuggestion: () => void;
|
|
39
|
+
reset: () => void;
|
|
40
|
+
}
|
|
41
|
+
declare function useIdentity({ debounceMs, onCommit, }?: UseIdentityOptions): UseIdentityReturn;
|
|
42
|
+
|
|
43
|
+
export { type IdentityState, TRIdError, type TRIdResult, type TRIdType, type UseIdentityOptions, type UseIdentityReturn, processTRId, useIdentity };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/core.ts
|
|
6
|
+
var TRIdError = {
|
|
7
|
+
INVALID_FORMAT: "INVALID_FORMAT",
|
|
8
|
+
INVALID_CHECKSUM: "INVALID_CHECKSUM",
|
|
9
|
+
TOO_SHORT: "TOO_SHORT",
|
|
10
|
+
TOO_LONG: "TOO_LONG",
|
|
11
|
+
INCOMPLETE: "INCOMPLETE"
|
|
12
|
+
};
|
|
13
|
+
var LENGTH = {
|
|
14
|
+
TCKN: { min: 9, max: 11 },
|
|
15
|
+
VERGI_NO: { min: 10, max: 10 }
|
|
16
|
+
};
|
|
17
|
+
function computeTCKNChecksum(nine) {
|
|
18
|
+
const d = [...nine].map(Number);
|
|
19
|
+
const odd = d[0] + d[2] + d[4] + d[6] + d[8];
|
|
20
|
+
const even = d[1] + d[3] + d[5] + d[7];
|
|
21
|
+
const d10 = ((odd * 7 - even) % 10 + 10) % 10;
|
|
22
|
+
const d11 = (odd + even + d10) % 10;
|
|
23
|
+
return [d10, d11];
|
|
24
|
+
}
|
|
25
|
+
function computeVergiNoChecksum(digits) {
|
|
26
|
+
const partial = digits.slice(0, 9).reduce((acc, d, i) => {
|
|
27
|
+
const v = (d + 10 - (i + 1)) % 10;
|
|
28
|
+
return acc + (v === 9 ? 9 : v * 2 ** (9 - i) % 9);
|
|
29
|
+
}, 0);
|
|
30
|
+
return (10 - partial % 10) % 10;
|
|
31
|
+
}
|
|
32
|
+
function completeTCKN(raw) {
|
|
33
|
+
const [d10, d11] = computeTCKNChecksum(raw.slice(0, 9));
|
|
34
|
+
return `${raw.slice(0, 9)}${d10}${d11}`;
|
|
35
|
+
}
|
|
36
|
+
function completeVergiNo(raw) {
|
|
37
|
+
const d10 = computeVergiNoChecksum([...raw].map(Number));
|
|
38
|
+
return `${raw.slice(0, 9)}${d10}`;
|
|
39
|
+
}
|
|
40
|
+
var complete = {
|
|
41
|
+
TCKN: completeTCKN,
|
|
42
|
+
VERGI_NO: completeVergiNo
|
|
43
|
+
};
|
|
44
|
+
function isValidChecksum(type, digits) {
|
|
45
|
+
if (type === "TCKN") {
|
|
46
|
+
const [d10, d11] = computeTCKNChecksum(digits.slice(0, 9));
|
|
47
|
+
return +digits[9] === d10 && +digits[10] === d11;
|
|
48
|
+
}
|
|
49
|
+
const d = [...digits].map(Number);
|
|
50
|
+
return d[9] === computeVergiNoChecksum(d);
|
|
51
|
+
}
|
|
52
|
+
function inferType(digits) {
|
|
53
|
+
if (digits.length === 10 && isValidChecksum("VERGI_NO", digits)) return "VERGI_NO";
|
|
54
|
+
return "TCKN";
|
|
55
|
+
}
|
|
56
|
+
function ok(type, completed, original) {
|
|
57
|
+
return { type, valid: true, completed, suggestion: null, original };
|
|
58
|
+
}
|
|
59
|
+
function fail(type, error, original, suggestion = null) {
|
|
60
|
+
return { type, valid: false, completed: null, suggestion, original, error };
|
|
61
|
+
}
|
|
62
|
+
function validate(type, digits, original) {
|
|
63
|
+
const { min, max } = LENGTH[type];
|
|
64
|
+
if (digits.length < min) return fail(type, TRIdError.TOO_SHORT, original);
|
|
65
|
+
if (digits.length > max) return fail(type, TRIdError.TOO_LONG, original);
|
|
66
|
+
if (type === "TCKN" && digits[0] === "0") {
|
|
67
|
+
return fail(type, TRIdError.INVALID_FORMAT, original);
|
|
68
|
+
}
|
|
69
|
+
if (type === "TCKN" && digits.length === 9) {
|
|
70
|
+
return fail(type, TRIdError.INCOMPLETE, original, completeTCKN(digits));
|
|
71
|
+
}
|
|
72
|
+
if (type === "TCKN" && digits.length === 10) {
|
|
73
|
+
return fail(type, TRIdError.INCOMPLETE, original, null);
|
|
74
|
+
}
|
|
75
|
+
const suggestion = complete[type](digits);
|
|
76
|
+
return isValidChecksum(type, digits) ? ok(type, suggestion, original) : fail(type, TRIdError.INVALID_CHECKSUM, original, suggestion);
|
|
77
|
+
}
|
|
78
|
+
function processTRId(input, hint) {
|
|
79
|
+
const original = String(input != null ? input : "").trim();
|
|
80
|
+
if (!/^\d+$/.test(original)) {
|
|
81
|
+
return fail(null, TRIdError.INVALID_FORMAT, original);
|
|
82
|
+
}
|
|
83
|
+
const type = hint != null ? hint : inferType(original);
|
|
84
|
+
return validate(type, original, original);
|
|
85
|
+
}
|
|
86
|
+
var DEFAULT_DEBOUNCE_MS = 600;
|
|
87
|
+
var INITIAL_STATE = {
|
|
88
|
+
status: "idle",
|
|
89
|
+
type: null,
|
|
90
|
+
completed: null,
|
|
91
|
+
suggestion: null,
|
|
92
|
+
error: null
|
|
93
|
+
};
|
|
94
|
+
var TYPE_LABELS = {
|
|
95
|
+
TCKN: "T.C. Kimlik No",
|
|
96
|
+
VERGI_NO: "Vergi No"
|
|
97
|
+
};
|
|
98
|
+
var ERROR_MESSAGES = {
|
|
99
|
+
[TRIdError.INVALID_FORMAT]: "Ge\xE7ersiz format",
|
|
100
|
+
[TRIdError.INVALID_CHECKSUM]: "Hatal\u0131 numara",
|
|
101
|
+
[TRIdError.TOO_SHORT]: "\xC7ok k\u0131sa",
|
|
102
|
+
[TRIdError.TOO_LONG]: "\xC7ok uzun",
|
|
103
|
+
[TRIdError.INCOMPLETE]: "Tamamlan\u0131yor\u2026"
|
|
104
|
+
};
|
|
105
|
+
function useIdentity({
|
|
106
|
+
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
107
|
+
onCommit
|
|
108
|
+
} = {}) {
|
|
109
|
+
const [raw, setRaw] = react.useState("");
|
|
110
|
+
const [state, setState] = react.useState(INITIAL_STATE);
|
|
111
|
+
const onCommitRef = react.useRef(onCommit);
|
|
112
|
+
react.useEffect(() => {
|
|
113
|
+
onCommitRef.current = onCommit;
|
|
114
|
+
}, [onCommit]);
|
|
115
|
+
const commit = react.useCallback((value) => {
|
|
116
|
+
var _a;
|
|
117
|
+
(_a = onCommitRef.current) == null ? void 0 : _a.call(onCommitRef, value);
|
|
118
|
+
}, []);
|
|
119
|
+
react.useEffect(() => {
|
|
120
|
+
if (!raw) {
|
|
121
|
+
setState(INITIAL_STATE);
|
|
122
|
+
commit("");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
setState((prev) => ({ ...prev, status: "typing" }));
|
|
126
|
+
const timer = setTimeout(() => {
|
|
127
|
+
var _a, _b;
|
|
128
|
+
const result = processTRId(raw);
|
|
129
|
+
if (result.valid && result.completed) {
|
|
130
|
+
setState({
|
|
131
|
+
status: "valid",
|
|
132
|
+
type: result.type,
|
|
133
|
+
completed: result.completed,
|
|
134
|
+
suggestion: null,
|
|
135
|
+
error: null
|
|
136
|
+
});
|
|
137
|
+
commit(result.completed);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (result.error === TRIdError.INCOMPLETE && result.suggestion) {
|
|
141
|
+
setState({
|
|
142
|
+
status: "autocompleted",
|
|
143
|
+
type: result.type,
|
|
144
|
+
completed: result.suggestion,
|
|
145
|
+
suggestion: null,
|
|
146
|
+
error: null
|
|
147
|
+
});
|
|
148
|
+
setRaw(result.suggestion);
|
|
149
|
+
commit(result.suggestion);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
setState({
|
|
153
|
+
status: "invalid",
|
|
154
|
+
type: result.type,
|
|
155
|
+
completed: null,
|
|
156
|
+
suggestion: (_a = result.suggestion) != null ? _a : null,
|
|
157
|
+
error: (_b = result.error) != null ? _b : null
|
|
158
|
+
});
|
|
159
|
+
commit(raw);
|
|
160
|
+
}, debounceMs);
|
|
161
|
+
return () => clearTimeout(timer);
|
|
162
|
+
}, [raw, debounceMs, commit]);
|
|
163
|
+
const handleChange = react.useCallback((value) => {
|
|
164
|
+
setRaw(value.replace(/\D/g, ""));
|
|
165
|
+
}, []);
|
|
166
|
+
const applySuggestion = react.useCallback(() => {
|
|
167
|
+
if (state.status !== "invalid" || !state.suggestion) return;
|
|
168
|
+
setRaw(state.suggestion);
|
|
169
|
+
commit(state.suggestion);
|
|
170
|
+
}, [state.status, state.suggestion, commit]);
|
|
171
|
+
const reset = react.useCallback(() => {
|
|
172
|
+
setRaw("");
|
|
173
|
+
setState(INITIAL_STATE);
|
|
174
|
+
commit("");
|
|
175
|
+
}, [commit]);
|
|
176
|
+
const isResolved = state.status === "valid" || state.status === "autocompleted" || state.status === "invalid";
|
|
177
|
+
const detectedLabel = isResolved && state.type ? TYPE_LABELS[state.type] : null;
|
|
178
|
+
const errorMessage = state.status === "invalid" && state.error ? ERROR_MESSAGES[state.error] : null;
|
|
179
|
+
return { raw, state, detectedLabel, errorMessage, handleChange, applySuggestion, reset };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
exports.TRIdError = TRIdError;
|
|
183
|
+
exports.processTRId = processTRId;
|
|
184
|
+
exports.useIdentity = useIdentity;
|
|
185
|
+
//# sourceMappingURL=index.js.map
|
|
186
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/use-identity.ts"],"names":["useState","useRef","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type TRIdType = 'TCKN' | 'VERGI_NO'\n\nexport const TRIdError = {\n INVALID_FORMAT: 'INVALID_FORMAT',\n INVALID_CHECKSUM: 'INVALID_CHECKSUM',\n TOO_SHORT: 'TOO_SHORT',\n TOO_LONG: 'TOO_LONG',\n INCOMPLETE: 'INCOMPLETE',\n} as const\n\nexport type TRIdError = (typeof TRIdError)[keyof typeof TRIdError]\n\nexport interface TRIdResult {\n type: TRIdType | null\n valid: boolean\n completed: string | null\n suggestion: string | null\n original: string\n error?: TRIdError\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst LENGTH: Record<TRIdType, { min: number; max: number }> = {\n TCKN: { min: 9, max: 11 },\n VERGI_NO: { min: 10, max: 10 },\n}\n\n// ─── Checksum ────────────────────────────────────────────────────────────────\n\nfunction computeTCKNChecksum(nine: string): [d10: number, d11: number] {\n const d = [...nine].map(Number)\n const odd = d[0] + d[2] + d[4] + d[6] + d[8]\n const even = d[1] + d[3] + d[5] + d[7]\n const d10 = (((odd * 7 - even) % 10) + 10) % 10\n const d11 = (odd + even + d10) % 10\n return [d10, d11]\n}\n\nfunction computeVergiNoChecksum(digits: readonly number[]): number {\n const partial = digits.slice(0, 9).reduce((acc, d, i) => {\n const v = (d + 10 - (i + 1)) % 10\n return acc + (v === 9 ? 9 : (v * 2 ** (9 - i)) % 9)\n }, 0)\n return (10 - (partial % 10)) % 10\n}\n\n// ─── Completion ──────────────────────────────────────────────────────────────\n\nfunction completeTCKN(raw: string): string {\n const [d10, d11] = computeTCKNChecksum(raw.slice(0, 9))\n return `${raw.slice(0, 9)}${d10}${d11}`\n}\n\nfunction completeVergiNo(raw: string): string {\n const d10 = computeVergiNoChecksum([...raw].map(Number))\n return `${raw.slice(0, 9)}${d10}`\n}\n\nconst complete: Record<TRIdType, (raw: string) => string> = {\n TCKN: completeTCKN,\n VERGI_NO: completeVergiNo,\n}\n\n// ─── Validation ──────────────────────────────────────────────────────────────\nfunction isValidChecksum(type: TRIdType, digits: string): boolean {\n if (type === 'TCKN') {\n const [d10, d11] = computeTCKNChecksum(digits.slice(0, 9))\n return +digits[9] === d10 && +digits[10] === d11\n }\n\n const d = [...digits].map(Number)\n return d[9] === computeVergiNoChecksum(d)\n}\n\n/**\n * 10 hane geldiğinde: Vergi No checksum geçerliyse VERGI_NO, değilse TCKN\n */\nfunction inferType(digits: string): TRIdType {\n if (digits.length === 10 && isValidChecksum('VERGI_NO', digits)) return 'VERGI_NO'\n return 'TCKN'\n}\n\n// ─── Result builders ─────────────────────────────────────────────────────────\n\nfunction ok(type: TRIdType, completed: string, original: string): TRIdResult {\n return { type, valid: true, completed, suggestion: null, original }\n}\n\nfunction fail(\n type: TRIdType | null,\n error: TRIdError,\n original: string,\n suggestion: string | null = null\n): TRIdResult {\n return { type, valid: false, completed: null, suggestion, original, error }\n}\n\n// ─── Core logic ──────────────────────────────────────────────────────────────\n\nfunction validate(type: TRIdType, digits: string, original: string): TRIdResult {\n const { min, max } = LENGTH[type]\n\n if (digits.length < min) return fail(type, TRIdError.TOO_SHORT, original)\n if (digits.length > max) return fail(type, TRIdError.TOO_LONG, original)\n\n // TCKN'de ilk hane 0 olamaz\n if (type === 'TCKN' && digits[0] === '0') {\n return fail(type, TRIdError.INVALID_FORMAT, original)\n }\n\n // 9 hane → TCKN, tamamlanabilir\n if (type === 'TCKN' && digits.length === 9) {\n return fail(type, TRIdError.INCOMPLETE, original, completeTCKN(digits))\n }\n\n // 10 hane → TCKN için hâlâ eksik (11 gerekli)\n if (type === 'TCKN' && digits.length === 10) {\n return fail(type, TRIdError.INCOMPLETE, original, null)\n }\n\n const suggestion = complete[type](digits)\n\n return isValidChecksum(type, digits)\n ? ok(type, suggestion, original)\n : fail(type, TRIdError.INVALID_CHECKSUM, original, suggestion)\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\nexport function processTRId(\n input: string | number | null | undefined,\n hint?: TRIdType\n): TRIdResult {\n const original = String(input ?? '').trim()\n\n // Sadece rakam içermeli; boş string veya tamamen boşluk → format hatası\n if (!/^\\d+$/.test(original)) {\n return fail(null, TRIdError.INVALID_FORMAT, original)\n }\n\n const type = hint ?? inferType(original)\n return validate(type, original, original)\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport { processTRId, TRIdError, type TRIdType } from './core'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ntype IdentityStatus = 'idle' | 'typing' | 'valid' | 'autocompleted' | 'invalid'\n\nexport interface IdentityState {\n status: IdentityStatus\n type: TRIdType | null\n completed: string | null\n suggestion: string | null\n error: TRIdError | null\n}\n\nexport interface UseIdentityOptions {\n debounceMs?: number\n onCommit?: (value: string) => void\n}\n\nexport interface UseIdentityReturn {\n raw: string\n state: IdentityState\n detectedLabel: string | null\n errorMessage: string | null\n handleChange: (value: string) => void\n applySuggestion: () => void\n reset: () => void\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_DEBOUNCE_MS = 600\n\nconst INITIAL_STATE: IdentityState = {\n status: 'idle',\n type: null,\n completed: null,\n suggestion: null,\n error: null,\n}\n\nconst TYPE_LABELS: Record<TRIdType, string> = {\n TCKN: 'T.C. Kimlik No',\n VERGI_NO: 'Vergi No',\n}\n\nconst ERROR_MESSAGES: Record<TRIdError, string> = {\n [TRIdError.INVALID_FORMAT]: 'Geçersiz format',\n [TRIdError.INVALID_CHECKSUM]: 'Hatalı numara',\n [TRIdError.TOO_SHORT]: 'Çok kısa',\n [TRIdError.TOO_LONG]: 'Çok uzun',\n [TRIdError.INCOMPLETE]: 'Tamamlanıyor…',\n}\n\n// ─── Hook ────────────────────────────────────────────────────────────────────\n\nexport function useIdentity({\n debounceMs = DEFAULT_DEBOUNCE_MS,\n onCommit,\n}: UseIdentityOptions = {}): UseIdentityReturn {\n const [raw, setRaw] = useState('')\n const [state, setState] = useState<IdentityState>(INITIAL_STATE)\n\n const onCommitRef = useRef(onCommit)\n useEffect(() => {\n onCommitRef.current = onCommit\n }, [onCommit])\n\n const commit = useCallback((value: string) => {\n onCommitRef.current?.(value)\n }, [])\n\n useEffect(() => {\n if (!raw) {\n setState(INITIAL_STATE)\n commit('')\n return\n }\n\n setState(prev => ({ ...prev, status: 'typing' }))\n\n const timer = setTimeout(() => {\n const result = processTRId(raw)\n\n // Geçerli kimlik numarası\n if (result.valid && result.completed) {\n setState({\n status: 'valid',\n type: result.type,\n completed: result.completed,\n suggestion: null,\n error: null,\n })\n commit(result.completed)\n return\n }\n\n // Eksik girişi otomatik tamamla (TCKN 9 hane)\n if (result.error === TRIdError.INCOMPLETE && result.suggestion) {\n setState({\n status: 'autocompleted',\n type: result.type,\n completed: result.suggestion,\n suggestion: null,\n error: null,\n })\n\n setRaw(result.suggestion)\n commit(result.suggestion)\n return\n }\n\n setState({\n status: 'invalid',\n type: result.type,\n completed: null,\n suggestion: result.suggestion ?? null,\n error: result.error ?? null,\n })\n commit(raw)\n }, debounceMs)\n\n return () => clearTimeout(timer)\n }, [raw, debounceMs, commit])\n\n // ─── Handlers ────────────────────────────────────────────────────────────\n\n const handleChange = useCallback((value: string) => {\n setRaw(value.replace(/\\D/g, ''))\n }, [])\n\n const applySuggestion = useCallback(() => {\n if (state.status !== 'invalid' || !state.suggestion) return\n setRaw(state.suggestion)\n commit(state.suggestion)\n }, [state.status, state.suggestion, commit])\n\n const reset = useCallback(() => {\n setRaw('')\n setState(INITIAL_STATE)\n commit('')\n }, [commit])\n\n // ─── Derived ─────────────────────────────────────────────────────────────\n\n const isResolved =\n state.status === 'valid' || state.status === 'autocompleted' || state.status === 'invalid'\n\n const detectedLabel = isResolved && state.type ? TYPE_LABELS[state.type] : null\n const errorMessage =\n state.status === 'invalid' && state.error ? ERROR_MESSAGES[state.error] : null\n\n return { raw, state, detectedLabel, errorMessage, handleChange, applySuggestion, reset }\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/core.ts
|
|
4
|
+
var TRIdError = {
|
|
5
|
+
INVALID_FORMAT: "INVALID_FORMAT",
|
|
6
|
+
INVALID_CHECKSUM: "INVALID_CHECKSUM",
|
|
7
|
+
TOO_SHORT: "TOO_SHORT",
|
|
8
|
+
TOO_LONG: "TOO_LONG",
|
|
9
|
+
INCOMPLETE: "INCOMPLETE"
|
|
10
|
+
};
|
|
11
|
+
var LENGTH = {
|
|
12
|
+
TCKN: { min: 9, max: 11 },
|
|
13
|
+
VERGI_NO: { min: 10, max: 10 }
|
|
14
|
+
};
|
|
15
|
+
function computeTCKNChecksum(nine) {
|
|
16
|
+
const d = [...nine].map(Number);
|
|
17
|
+
const odd = d[0] + d[2] + d[4] + d[6] + d[8];
|
|
18
|
+
const even = d[1] + d[3] + d[5] + d[7];
|
|
19
|
+
const d10 = ((odd * 7 - even) % 10 + 10) % 10;
|
|
20
|
+
const d11 = (odd + even + d10) % 10;
|
|
21
|
+
return [d10, d11];
|
|
22
|
+
}
|
|
23
|
+
function computeVergiNoChecksum(digits) {
|
|
24
|
+
const partial = digits.slice(0, 9).reduce((acc, d, i) => {
|
|
25
|
+
const v = (d + 10 - (i + 1)) % 10;
|
|
26
|
+
return acc + (v === 9 ? 9 : v * 2 ** (9 - i) % 9);
|
|
27
|
+
}, 0);
|
|
28
|
+
return (10 - partial % 10) % 10;
|
|
29
|
+
}
|
|
30
|
+
function completeTCKN(raw) {
|
|
31
|
+
const [d10, d11] = computeTCKNChecksum(raw.slice(0, 9));
|
|
32
|
+
return `${raw.slice(0, 9)}${d10}${d11}`;
|
|
33
|
+
}
|
|
34
|
+
function completeVergiNo(raw) {
|
|
35
|
+
const d10 = computeVergiNoChecksum([...raw].map(Number));
|
|
36
|
+
return `${raw.slice(0, 9)}${d10}`;
|
|
37
|
+
}
|
|
38
|
+
var complete = {
|
|
39
|
+
TCKN: completeTCKN,
|
|
40
|
+
VERGI_NO: completeVergiNo
|
|
41
|
+
};
|
|
42
|
+
function isValidChecksum(type, digits) {
|
|
43
|
+
if (type === "TCKN") {
|
|
44
|
+
const [d10, d11] = computeTCKNChecksum(digits.slice(0, 9));
|
|
45
|
+
return +digits[9] === d10 && +digits[10] === d11;
|
|
46
|
+
}
|
|
47
|
+
const d = [...digits].map(Number);
|
|
48
|
+
return d[9] === computeVergiNoChecksum(d);
|
|
49
|
+
}
|
|
50
|
+
function inferType(digits) {
|
|
51
|
+
if (digits.length === 10 && isValidChecksum("VERGI_NO", digits)) return "VERGI_NO";
|
|
52
|
+
return "TCKN";
|
|
53
|
+
}
|
|
54
|
+
function ok(type, completed, original) {
|
|
55
|
+
return { type, valid: true, completed, suggestion: null, original };
|
|
56
|
+
}
|
|
57
|
+
function fail(type, error, original, suggestion = null) {
|
|
58
|
+
return { type, valid: false, completed: null, suggestion, original, error };
|
|
59
|
+
}
|
|
60
|
+
function validate(type, digits, original) {
|
|
61
|
+
const { min, max } = LENGTH[type];
|
|
62
|
+
if (digits.length < min) return fail(type, TRIdError.TOO_SHORT, original);
|
|
63
|
+
if (digits.length > max) return fail(type, TRIdError.TOO_LONG, original);
|
|
64
|
+
if (type === "TCKN" && digits[0] === "0") {
|
|
65
|
+
return fail(type, TRIdError.INVALID_FORMAT, original);
|
|
66
|
+
}
|
|
67
|
+
if (type === "TCKN" && digits.length === 9) {
|
|
68
|
+
return fail(type, TRIdError.INCOMPLETE, original, completeTCKN(digits));
|
|
69
|
+
}
|
|
70
|
+
if (type === "TCKN" && digits.length === 10) {
|
|
71
|
+
return fail(type, TRIdError.INCOMPLETE, original, null);
|
|
72
|
+
}
|
|
73
|
+
const suggestion = complete[type](digits);
|
|
74
|
+
return isValidChecksum(type, digits) ? ok(type, suggestion, original) : fail(type, TRIdError.INVALID_CHECKSUM, original, suggestion);
|
|
75
|
+
}
|
|
76
|
+
function processTRId(input, hint) {
|
|
77
|
+
const original = String(input != null ? input : "").trim();
|
|
78
|
+
if (!/^\d+$/.test(original)) {
|
|
79
|
+
return fail(null, TRIdError.INVALID_FORMAT, original);
|
|
80
|
+
}
|
|
81
|
+
const type = hint != null ? hint : inferType(original);
|
|
82
|
+
return validate(type, original, original);
|
|
83
|
+
}
|
|
84
|
+
var DEFAULT_DEBOUNCE_MS = 600;
|
|
85
|
+
var INITIAL_STATE = {
|
|
86
|
+
status: "idle",
|
|
87
|
+
type: null,
|
|
88
|
+
completed: null,
|
|
89
|
+
suggestion: null,
|
|
90
|
+
error: null
|
|
91
|
+
};
|
|
92
|
+
var TYPE_LABELS = {
|
|
93
|
+
TCKN: "T.C. Kimlik No",
|
|
94
|
+
VERGI_NO: "Vergi No"
|
|
95
|
+
};
|
|
96
|
+
var ERROR_MESSAGES = {
|
|
97
|
+
[TRIdError.INVALID_FORMAT]: "Ge\xE7ersiz format",
|
|
98
|
+
[TRIdError.INVALID_CHECKSUM]: "Hatal\u0131 numara",
|
|
99
|
+
[TRIdError.TOO_SHORT]: "\xC7ok k\u0131sa",
|
|
100
|
+
[TRIdError.TOO_LONG]: "\xC7ok uzun",
|
|
101
|
+
[TRIdError.INCOMPLETE]: "Tamamlan\u0131yor\u2026"
|
|
102
|
+
};
|
|
103
|
+
function useIdentity({
|
|
104
|
+
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
105
|
+
onCommit
|
|
106
|
+
} = {}) {
|
|
107
|
+
const [raw, setRaw] = useState("");
|
|
108
|
+
const [state, setState] = useState(INITIAL_STATE);
|
|
109
|
+
const onCommitRef = useRef(onCommit);
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
onCommitRef.current = onCommit;
|
|
112
|
+
}, [onCommit]);
|
|
113
|
+
const commit = useCallback((value) => {
|
|
114
|
+
var _a;
|
|
115
|
+
(_a = onCommitRef.current) == null ? void 0 : _a.call(onCommitRef, value);
|
|
116
|
+
}, []);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (!raw) {
|
|
119
|
+
setState(INITIAL_STATE);
|
|
120
|
+
commit("");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
setState((prev) => ({ ...prev, status: "typing" }));
|
|
124
|
+
const timer = setTimeout(() => {
|
|
125
|
+
var _a, _b;
|
|
126
|
+
const result = processTRId(raw);
|
|
127
|
+
if (result.valid && result.completed) {
|
|
128
|
+
setState({
|
|
129
|
+
status: "valid",
|
|
130
|
+
type: result.type,
|
|
131
|
+
completed: result.completed,
|
|
132
|
+
suggestion: null,
|
|
133
|
+
error: null
|
|
134
|
+
});
|
|
135
|
+
commit(result.completed);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (result.error === TRIdError.INCOMPLETE && result.suggestion) {
|
|
139
|
+
setState({
|
|
140
|
+
status: "autocompleted",
|
|
141
|
+
type: result.type,
|
|
142
|
+
completed: result.suggestion,
|
|
143
|
+
suggestion: null,
|
|
144
|
+
error: null
|
|
145
|
+
});
|
|
146
|
+
setRaw(result.suggestion);
|
|
147
|
+
commit(result.suggestion);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
setState({
|
|
151
|
+
status: "invalid",
|
|
152
|
+
type: result.type,
|
|
153
|
+
completed: null,
|
|
154
|
+
suggestion: (_a = result.suggestion) != null ? _a : null,
|
|
155
|
+
error: (_b = result.error) != null ? _b : null
|
|
156
|
+
});
|
|
157
|
+
commit(raw);
|
|
158
|
+
}, debounceMs);
|
|
159
|
+
return () => clearTimeout(timer);
|
|
160
|
+
}, [raw, debounceMs, commit]);
|
|
161
|
+
const handleChange = useCallback((value) => {
|
|
162
|
+
setRaw(value.replace(/\D/g, ""));
|
|
163
|
+
}, []);
|
|
164
|
+
const applySuggestion = useCallback(() => {
|
|
165
|
+
if (state.status !== "invalid" || !state.suggestion) return;
|
|
166
|
+
setRaw(state.suggestion);
|
|
167
|
+
commit(state.suggestion);
|
|
168
|
+
}, [state.status, state.suggestion, commit]);
|
|
169
|
+
const reset = useCallback(() => {
|
|
170
|
+
setRaw("");
|
|
171
|
+
setState(INITIAL_STATE);
|
|
172
|
+
commit("");
|
|
173
|
+
}, [commit]);
|
|
174
|
+
const isResolved = state.status === "valid" || state.status === "autocompleted" || state.status === "invalid";
|
|
175
|
+
const detectedLabel = isResolved && state.type ? TYPE_LABELS[state.type] : null;
|
|
176
|
+
const errorMessage = state.status === "invalid" && state.error ? ERROR_MESSAGES[state.error] : null;
|
|
177
|
+
return { raw, state, detectedLabel, errorMessage, handleChange, applySuggestion, reset };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { TRIdError, processTRId, useIdentity };
|
|
181
|
+
//# sourceMappingURL=index.mjs.map
|
|
182
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/use-identity.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type TRIdType = 'TCKN' | 'VERGI_NO'\n\nexport const TRIdError = {\n INVALID_FORMAT: 'INVALID_FORMAT',\n INVALID_CHECKSUM: 'INVALID_CHECKSUM',\n TOO_SHORT: 'TOO_SHORT',\n TOO_LONG: 'TOO_LONG',\n INCOMPLETE: 'INCOMPLETE',\n} as const\n\nexport type TRIdError = (typeof TRIdError)[keyof typeof TRIdError]\n\nexport interface TRIdResult {\n type: TRIdType | null\n valid: boolean\n completed: string | null\n suggestion: string | null\n original: string\n error?: TRIdError\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst LENGTH: Record<TRIdType, { min: number; max: number }> = {\n TCKN: { min: 9, max: 11 },\n VERGI_NO: { min: 10, max: 10 },\n}\n\n// ─── Checksum ────────────────────────────────────────────────────────────────\n\nfunction computeTCKNChecksum(nine: string): [d10: number, d11: number] {\n const d = [...nine].map(Number)\n const odd = d[0] + d[2] + d[4] + d[6] + d[8]\n const even = d[1] + d[3] + d[5] + d[7]\n const d10 = (((odd * 7 - even) % 10) + 10) % 10\n const d11 = (odd + even + d10) % 10\n return [d10, d11]\n}\n\nfunction computeVergiNoChecksum(digits: readonly number[]): number {\n const partial = digits.slice(0, 9).reduce((acc, d, i) => {\n const v = (d + 10 - (i + 1)) % 10\n return acc + (v === 9 ? 9 : (v * 2 ** (9 - i)) % 9)\n }, 0)\n return (10 - (partial % 10)) % 10\n}\n\n// ─── Completion ──────────────────────────────────────────────────────────────\n\nfunction completeTCKN(raw: string): string {\n const [d10, d11] = computeTCKNChecksum(raw.slice(0, 9))\n return `${raw.slice(0, 9)}${d10}${d11}`\n}\n\nfunction completeVergiNo(raw: string): string {\n const d10 = computeVergiNoChecksum([...raw].map(Number))\n return `${raw.slice(0, 9)}${d10}`\n}\n\nconst complete: Record<TRIdType, (raw: string) => string> = {\n TCKN: completeTCKN,\n VERGI_NO: completeVergiNo,\n}\n\n// ─── Validation ──────────────────────────────────────────────────────────────\nfunction isValidChecksum(type: TRIdType, digits: string): boolean {\n if (type === 'TCKN') {\n const [d10, d11] = computeTCKNChecksum(digits.slice(0, 9))\n return +digits[9] === d10 && +digits[10] === d11\n }\n\n const d = [...digits].map(Number)\n return d[9] === computeVergiNoChecksum(d)\n}\n\n/**\n * 10 hane geldiğinde: Vergi No checksum geçerliyse VERGI_NO, değilse TCKN\n */\nfunction inferType(digits: string): TRIdType {\n if (digits.length === 10 && isValidChecksum('VERGI_NO', digits)) return 'VERGI_NO'\n return 'TCKN'\n}\n\n// ─── Result builders ─────────────────────────────────────────────────────────\n\nfunction ok(type: TRIdType, completed: string, original: string): TRIdResult {\n return { type, valid: true, completed, suggestion: null, original }\n}\n\nfunction fail(\n type: TRIdType | null,\n error: TRIdError,\n original: string,\n suggestion: string | null = null\n): TRIdResult {\n return { type, valid: false, completed: null, suggestion, original, error }\n}\n\n// ─── Core logic ──────────────────────────────────────────────────────────────\n\nfunction validate(type: TRIdType, digits: string, original: string): TRIdResult {\n const { min, max } = LENGTH[type]\n\n if (digits.length < min) return fail(type, TRIdError.TOO_SHORT, original)\n if (digits.length > max) return fail(type, TRIdError.TOO_LONG, original)\n\n // TCKN'de ilk hane 0 olamaz\n if (type === 'TCKN' && digits[0] === '0') {\n return fail(type, TRIdError.INVALID_FORMAT, original)\n }\n\n // 9 hane → TCKN, tamamlanabilir\n if (type === 'TCKN' && digits.length === 9) {\n return fail(type, TRIdError.INCOMPLETE, original, completeTCKN(digits))\n }\n\n // 10 hane → TCKN için hâlâ eksik (11 gerekli)\n if (type === 'TCKN' && digits.length === 10) {\n return fail(type, TRIdError.INCOMPLETE, original, null)\n }\n\n const suggestion = complete[type](digits)\n\n return isValidChecksum(type, digits)\n ? ok(type, suggestion, original)\n : fail(type, TRIdError.INVALID_CHECKSUM, original, suggestion)\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\nexport function processTRId(\n input: string | number | null | undefined,\n hint?: TRIdType\n): TRIdResult {\n const original = String(input ?? '').trim()\n\n // Sadece rakam içermeli; boş string veya tamamen boşluk → format hatası\n if (!/^\\d+$/.test(original)) {\n return fail(null, TRIdError.INVALID_FORMAT, original)\n }\n\n const type = hint ?? inferType(original)\n return validate(type, original, original)\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport { processTRId, TRIdError, type TRIdType } from './core'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ntype IdentityStatus = 'idle' | 'typing' | 'valid' | 'autocompleted' | 'invalid'\n\nexport interface IdentityState {\n status: IdentityStatus\n type: TRIdType | null\n completed: string | null\n suggestion: string | null\n error: TRIdError | null\n}\n\nexport interface UseIdentityOptions {\n debounceMs?: number\n onCommit?: (value: string) => void\n}\n\nexport interface UseIdentityReturn {\n raw: string\n state: IdentityState\n detectedLabel: string | null\n errorMessage: string | null\n handleChange: (value: string) => void\n applySuggestion: () => void\n reset: () => void\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_DEBOUNCE_MS = 600\n\nconst INITIAL_STATE: IdentityState = {\n status: 'idle',\n type: null,\n completed: null,\n suggestion: null,\n error: null,\n}\n\nconst TYPE_LABELS: Record<TRIdType, string> = {\n TCKN: 'T.C. Kimlik No',\n VERGI_NO: 'Vergi No',\n}\n\nconst ERROR_MESSAGES: Record<TRIdError, string> = {\n [TRIdError.INVALID_FORMAT]: 'Geçersiz format',\n [TRIdError.INVALID_CHECKSUM]: 'Hatalı numara',\n [TRIdError.TOO_SHORT]: 'Çok kısa',\n [TRIdError.TOO_LONG]: 'Çok uzun',\n [TRIdError.INCOMPLETE]: 'Tamamlanıyor…',\n}\n\n// ─── Hook ────────────────────────────────────────────────────────────────────\n\nexport function useIdentity({\n debounceMs = DEFAULT_DEBOUNCE_MS,\n onCommit,\n}: UseIdentityOptions = {}): UseIdentityReturn {\n const [raw, setRaw] = useState('')\n const [state, setState] = useState<IdentityState>(INITIAL_STATE)\n\n const onCommitRef = useRef(onCommit)\n useEffect(() => {\n onCommitRef.current = onCommit\n }, [onCommit])\n\n const commit = useCallback((value: string) => {\n onCommitRef.current?.(value)\n }, [])\n\n useEffect(() => {\n if (!raw) {\n setState(INITIAL_STATE)\n commit('')\n return\n }\n\n setState(prev => ({ ...prev, status: 'typing' }))\n\n const timer = setTimeout(() => {\n const result = processTRId(raw)\n\n // Geçerli kimlik numarası\n if (result.valid && result.completed) {\n setState({\n status: 'valid',\n type: result.type,\n completed: result.completed,\n suggestion: null,\n error: null,\n })\n commit(result.completed)\n return\n }\n\n // Eksik girişi otomatik tamamla (TCKN 9 hane)\n if (result.error === TRIdError.INCOMPLETE && result.suggestion) {\n setState({\n status: 'autocompleted',\n type: result.type,\n completed: result.suggestion,\n suggestion: null,\n error: null,\n })\n\n setRaw(result.suggestion)\n commit(result.suggestion)\n return\n }\n\n setState({\n status: 'invalid',\n type: result.type,\n completed: null,\n suggestion: result.suggestion ?? null,\n error: result.error ?? null,\n })\n commit(raw)\n }, debounceMs)\n\n return () => clearTimeout(timer)\n }, [raw, debounceMs, commit])\n\n // ─── Handlers ────────────────────────────────────────────────────────────\n\n const handleChange = useCallback((value: string) => {\n setRaw(value.replace(/\\D/g, ''))\n }, [])\n\n const applySuggestion = useCallback(() => {\n if (state.status !== 'invalid' || !state.suggestion) return\n setRaw(state.suggestion)\n commit(state.suggestion)\n }, [state.status, state.suggestion, commit])\n\n const reset = useCallback(() => {\n setRaw('')\n setState(INITIAL_STATE)\n commit('')\n }, [commit])\n\n // ─── Derived ─────────────────────────────────────────────────────────────\n\n const isResolved =\n state.status === 'valid' || state.status === 'autocompleted' || state.status === 'invalid'\n\n const detectedLabel = isResolved && state.type ? TYPE_LABELS[state.type] : null\n const errorMessage =\n state.status === 'invalid' && state.error ? ERROR_MESSAGES[state.error] : null\n\n return { raw, state, detectedLabel, errorMessage, handleChange, applySuggestion, reset }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tr-identity",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Turkish TCKN & Vergi No validation with React hook",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" },
|
|
11
|
+
"require": { "types": "./dist/index.d.ts", "default": "./dist/index.js" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": ">=17.0.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"react": "^18.0.0",
|
|
21
|
+
"@types/react": "^18.0.0",
|
|
22
|
+
"tsup": "^8.0.0",
|
|
23
|
+
"typescript": "^5.0.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
}
|
|
30
|
+
}
|