nihonput 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.js ADDED
@@ -0,0 +1,948 @@
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
+ PREFECTURES: () => PREFECTURES,
24
+ PREFECTURE_SHORT_NAMES: () => PREFECTURE_SHORT_NAMES,
25
+ addPhoneNumberHyphen: () => addPhoneNumberHyphen,
26
+ addPostalCodeHyphen: () => addPostalCodeHyphen,
27
+ containsFullWidthPhoneNumber: () => containsFullWidthPhoneNumber,
28
+ containsHiragana: () => containsHiragana,
29
+ containsKatakana: () => containsKatakana,
30
+ defaultErrorMessages: () => defaultErrorMessages,
31
+ isFullWidthPostalCode: () => isFullWidthPostalCode,
32
+ isHalfWidthPhoneNumber: () => isHalfWidthPhoneNumber,
33
+ isHalfWidthPostalCode: () => isHalfWidthPostalCode,
34
+ normalizePrefecture: () => normalizePrefecture,
35
+ toFullWidth: () => toFullWidth,
36
+ toFullWidthHyphen: () => toFullWidthHyphen,
37
+ toFullWidthNumbers: () => toFullWidthNumbers,
38
+ toHalfWidth: () => toHalfWidth,
39
+ toHalfWidthHyphen: () => toHalfWidthHyphen,
40
+ toHalfWidthNumbers: () => toHalfWidthNumbers,
41
+ toHiragana: () => toHiragana,
42
+ toKatakana: () => toKatakana,
43
+ useAddressField: () => useAddressField,
44
+ useNameField: () => useNameField,
45
+ usePhoneNumberField: () => usePhoneNumberField,
46
+ usePostalCodeField: () => usePostalCodeField,
47
+ usePrefectureField: () => usePrefectureField,
48
+ validateHiragana: () => validateHiragana,
49
+ validateKatakana: () => validateKatakana,
50
+ validatePhoneNumber: () => validatePhoneNumber,
51
+ validatePostalCode: () => validatePostalCode,
52
+ validatePrefecture: () => validatePrefecture
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+
56
+ // src/hooks/useNameField.ts
57
+ var import_react = require("react");
58
+
59
+ // src/types/index.ts
60
+ var defaultErrorMessages = {
61
+ katakanaOnly: "\u30AB\u30BF\u30AB\u30CA\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
62
+ hiraganaOnly: "\u3072\u3089\u304C\u306A\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
63
+ invalidPostalCode: "\u6B63\u3057\u3044\u90F5\u4FBF\u756A\u53F7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: 123-4567\uFF09",
64
+ invalidPrefecture: "\u6B63\u3057\u3044\u90FD\u9053\u5E9C\u770C\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
65
+ invalidPhoneNumber: "\u6B63\u3057\u3044\u96FB\u8A71\u756A\u53F7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
66
+ invalidWidth: "\u6B63\u3057\u3044\u6587\u5B57\u5E45\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
67
+ invalidFormat: "\u6B63\u3057\u3044\u5F62\u5F0F\u3067\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044"
68
+ };
69
+
70
+ // src/validators/katakana.ts
71
+ function validateKatakana(value) {
72
+ if (!value) return true;
73
+ const katakanaRegex = /^[\u30A0-\u30FF\u3000\s]+$/;
74
+ return katakanaRegex.test(value);
75
+ }
76
+ function containsHiragana(value) {
77
+ if (!value) return false;
78
+ const hiraganaRegex = /[\u3040-\u309F]/;
79
+ return hiraganaRegex.test(value);
80
+ }
81
+
82
+ // src/normalizers/toKatakana.ts
83
+ function toKatakana(value) {
84
+ if (!value) return value;
85
+ return value.replace(/[\u3040-\u309F]/g, (char) => {
86
+ return String.fromCharCode(char.charCodeAt(0) + 96);
87
+ });
88
+ }
89
+
90
+ // src/hooks/useNameField.ts
91
+ function useNameField(options) {
92
+ const {
93
+ kanaMode,
94
+ normalizeOn = "blur",
95
+ validateOn = "blur",
96
+ errorMessages = {}
97
+ } = options;
98
+ const [value, setValue] = (0, import_react.useState)("");
99
+ const [error, setError] = (0, import_react.useState)(null);
100
+ const [isValidating, setIsValidating] = (0, import_react.useState)(false);
101
+ const isComposingRef = (0, import_react.useRef)(false);
102
+ const messages = {
103
+ katakanaOnly: errorMessages.katakanaOnly ?? defaultErrorMessages.katakanaOnly,
104
+ invalidFormat: errorMessages.invalidFormat ?? defaultErrorMessages.invalidFormat
105
+ };
106
+ const normalize = (0, import_react.useCallback)(
107
+ (val) => {
108
+ if (kanaMode === "auto-convert") {
109
+ return toKatakana(val);
110
+ }
111
+ return val;
112
+ },
113
+ [kanaMode]
114
+ );
115
+ const validate = (0, import_react.useCallback)(
116
+ (val) => {
117
+ if (!val) return null;
118
+ if (kanaMode === "error-on-hiragana") {
119
+ if (containsHiragana(val)) {
120
+ return messages.katakanaOnly;
121
+ }
122
+ }
123
+ if (!validateKatakana(val)) {
124
+ return messages.katakanaOnly;
125
+ }
126
+ return null;
127
+ },
128
+ [kanaMode, messages.katakanaOnly]
129
+ );
130
+ const handleChange = (0, import_react.useCallback)(
131
+ (e) => {
132
+ const newValue = e.target.value;
133
+ setValue(newValue);
134
+ if (isComposingRef.current) return;
135
+ if (normalizeOn === "change") {
136
+ setValue(normalize(newValue));
137
+ }
138
+ if (validateOn === "change") {
139
+ setIsValidating(true);
140
+ const validationError = validate(
141
+ normalizeOn === "change" ? normalize(newValue) : newValue
142
+ );
143
+ setError(validationError);
144
+ setIsValidating(false);
145
+ }
146
+ },
147
+ [normalize, validate, normalizeOn, validateOn]
148
+ );
149
+ const handleBlur = (0, import_react.useCallback)(
150
+ (e) => {
151
+ const currentValue = e.target.value;
152
+ if (normalizeOn === "blur") {
153
+ const normalized = normalize(currentValue);
154
+ setValue(normalized);
155
+ if (validateOn === "blur") {
156
+ setIsValidating(true);
157
+ setError(validate(normalized));
158
+ setIsValidating(false);
159
+ }
160
+ } else if (validateOn === "blur") {
161
+ setIsValidating(true);
162
+ setError(validate(currentValue));
163
+ setIsValidating(false);
164
+ }
165
+ },
166
+ [normalize, validate, normalizeOn, validateOn]
167
+ );
168
+ const handleCompositionStart = (0, import_react.useCallback)(
169
+ (_e) => {
170
+ isComposingRef.current = true;
171
+ },
172
+ []
173
+ );
174
+ const handleCompositionEnd = (0, import_react.useCallback)(
175
+ (e) => {
176
+ isComposingRef.current = false;
177
+ const currentValue = e.currentTarget.value;
178
+ if (normalizeOn === "compositionEnd") {
179
+ const normalized = normalize(currentValue);
180
+ setValue(normalized);
181
+ if (validateOn === "blur" || validateOn === "change") {
182
+ setIsValidating(true);
183
+ setError(validate(normalized));
184
+ setIsValidating(false);
185
+ }
186
+ }
187
+ },
188
+ [normalize, validate, normalizeOn, validateOn]
189
+ );
190
+ return {
191
+ value,
192
+ onChange: handleChange,
193
+ onBlur: handleBlur,
194
+ onCompositionStart: handleCompositionStart,
195
+ onCompositionEnd: handleCompositionEnd,
196
+ error,
197
+ isValidating,
198
+ isComposing: isComposingRef.current
199
+ };
200
+ }
201
+
202
+ // src/hooks/usePostalCodeField.ts
203
+ var import_react2 = require("react");
204
+
205
+ // src/validators/postalCode.ts
206
+ function validatePostalCode(value) {
207
+ if (!value) return true;
208
+ const normalized = value.replace(/[0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 65248)).replace(/[ー-]/g, "-");
209
+ const postalCodeRegex = /^\d{3}-?\d{4}$/;
210
+ return postalCodeRegex.test(normalized);
211
+ }
212
+ function isHalfWidthPostalCode(value) {
213
+ if (!value) return true;
214
+ const halfWidthRegex = /^[\d-]+$/;
215
+ return halfWidthRegex.test(value);
216
+ }
217
+ function isFullWidthPostalCode(value) {
218
+ if (!value) return true;
219
+ const fullWidthRegex = /^[0-9ー-]+$/;
220
+ return fullWidthRegex.test(value);
221
+ }
222
+
223
+ // src/normalizers/toHalfWidth.ts
224
+ function toHalfWidth(value) {
225
+ if (!value) return value;
226
+ return value.replace(/[\uFF01-\uFF5E]/g, (char) => {
227
+ return String.fromCharCode(char.charCodeAt(0) - 65248);
228
+ }).replace(/\u3000/g, " ");
229
+ }
230
+ function toHalfWidthNumbers(value) {
231
+ if (!value) return value;
232
+ return value.replace(/[0-9]/g, (char) => {
233
+ return String.fromCharCode(char.charCodeAt(0) - 65248);
234
+ });
235
+ }
236
+ function toHalfWidthHyphen(value) {
237
+ if (!value) return value;
238
+ return value.replace(/[ー-―]/g, "-");
239
+ }
240
+
241
+ // src/normalizers/toFullWidth.ts
242
+ function toFullWidth(value) {
243
+ if (!value) return value;
244
+ return value.replace(/[\x21-\x7E]/g, (char) => {
245
+ return String.fromCharCode(char.charCodeAt(0) + 65248);
246
+ }).replace(/ /g, "\u3000");
247
+ }
248
+ function toFullWidthNumbers(value) {
249
+ if (!value) return value;
250
+ return value.replace(/[0-9]/g, (char) => {
251
+ return String.fromCharCode(char.charCodeAt(0) + 65248);
252
+ });
253
+ }
254
+ function toFullWidthHyphen(value) {
255
+ if (!value) return value;
256
+ return value.replace(/-/g, "\u30FC");
257
+ }
258
+
259
+ // src/normalizers/addHyphen.ts
260
+ function addPostalCodeHyphen(value) {
261
+ if (!value) return value;
262
+ let normalized = toHalfWidthNumbers(value);
263
+ normalized = toHalfWidthHyphen(normalized);
264
+ const digitsOnly = normalized.replace(/-/g, "");
265
+ if (digitsOnly.length >= 4) {
266
+ return digitsOnly.slice(0, 3) + "-" + digitsOnly.slice(3, 7);
267
+ }
268
+ return digitsOnly;
269
+ }
270
+ function addPhoneNumberHyphen(value) {
271
+ if (!value) return value;
272
+ let normalized = toHalfWidthNumbers(value);
273
+ normalized = toHalfWidthHyphen(normalized);
274
+ const digitsOnly = normalized.replace(/-/g, "");
275
+ if (digitsOnly.length === 11) {
276
+ if (digitsOnly.startsWith("0")) {
277
+ return digitsOnly.slice(0, 3) + "-" + digitsOnly.slice(3, 7) + "-" + digitsOnly.slice(7);
278
+ }
279
+ } else if (digitsOnly.length === 10) {
280
+ if (digitsOnly.startsWith("0")) {
281
+ if (digitsOnly.startsWith("03") || digitsOnly.startsWith("06")) {
282
+ return digitsOnly.slice(0, 2) + "-" + digitsOnly.slice(2, 6) + "-" + digitsOnly.slice(6);
283
+ }
284
+ return digitsOnly.slice(0, 4) + "-" + digitsOnly.slice(4, 6) + "-" + digitsOnly.slice(6);
285
+ }
286
+ }
287
+ return digitsOnly;
288
+ }
289
+
290
+ // src/hooks/usePostalCodeField.ts
291
+ function usePostalCodeField(options) {
292
+ const {
293
+ widthMode,
294
+ onInvalid,
295
+ autoHyphen = true,
296
+ normalizeOn = "blur",
297
+ validateOn = "blur",
298
+ errorMessages = {}
299
+ } = options;
300
+ const [value, setValue] = (0, import_react2.useState)("");
301
+ const [error, setError] = (0, import_react2.useState)(null);
302
+ const [isValidating, setIsValidating] = (0, import_react2.useState)(false);
303
+ const isComposingRef = (0, import_react2.useRef)(false);
304
+ const messages = {
305
+ invalidWidth: errorMessages.invalidWidth ?? defaultErrorMessages.invalidWidth,
306
+ invalidFormat: errorMessages.invalidFormat ?? defaultErrorMessages.invalidPostalCode
307
+ };
308
+ const normalizeWidth = (0, import_react2.useCallback)(
309
+ (val) => {
310
+ if (widthMode === "half-width-only") {
311
+ let normalized = toHalfWidthNumbers(val);
312
+ normalized = toHalfWidthHyphen(normalized);
313
+ return normalized;
314
+ } else {
315
+ let normalized = toFullWidthNumbers(val);
316
+ normalized = toFullWidthHyphen(normalized);
317
+ return normalized;
318
+ }
319
+ },
320
+ [widthMode]
321
+ );
322
+ const normalize = (0, import_react2.useCallback)(
323
+ (val) => {
324
+ let normalized = val;
325
+ if (onInvalid === "auto-convert") {
326
+ normalized = normalizeWidth(normalized);
327
+ }
328
+ if (autoHyphen && widthMode === "half-width-only") {
329
+ normalized = addPostalCodeHyphen(normalized);
330
+ }
331
+ return normalized;
332
+ },
333
+ [onInvalid, autoHyphen, widthMode, normalizeWidth]
334
+ );
335
+ const validate = (0, import_react2.useCallback)(
336
+ (val) => {
337
+ if (!val) return null;
338
+ if (onInvalid === "error") {
339
+ if (widthMode === "half-width-only" && !isHalfWidthPostalCode(val)) {
340
+ return messages.invalidWidth;
341
+ }
342
+ if (widthMode === "full-width-only" && !isFullWidthPostalCode(val)) {
343
+ return messages.invalidWidth;
344
+ }
345
+ }
346
+ if (!validatePostalCode(val)) {
347
+ return messages.invalidFormat;
348
+ }
349
+ return null;
350
+ },
351
+ [onInvalid, widthMode, messages.invalidWidth, messages.invalidFormat]
352
+ );
353
+ const handleChange = (0, import_react2.useCallback)(
354
+ (e) => {
355
+ const newValue = e.target.value;
356
+ setValue(newValue);
357
+ if (isComposingRef.current) return;
358
+ if (normalizeOn === "change") {
359
+ setValue(normalize(newValue));
360
+ }
361
+ if (validateOn === "change") {
362
+ setIsValidating(true);
363
+ const validationError = validate(
364
+ normalizeOn === "change" ? normalize(newValue) : newValue
365
+ );
366
+ setError(validationError);
367
+ setIsValidating(false);
368
+ }
369
+ },
370
+ [normalize, validate, normalizeOn, validateOn]
371
+ );
372
+ const handleBlur = (0, import_react2.useCallback)(
373
+ (e) => {
374
+ const currentValue = e.target.value;
375
+ if (normalizeOn === "blur") {
376
+ const normalized = normalize(currentValue);
377
+ setValue(normalized);
378
+ if (validateOn === "blur") {
379
+ setIsValidating(true);
380
+ setError(validate(normalized));
381
+ setIsValidating(false);
382
+ }
383
+ } else if (validateOn === "blur") {
384
+ setIsValidating(true);
385
+ setError(validate(currentValue));
386
+ setIsValidating(false);
387
+ }
388
+ },
389
+ [normalize, validate, normalizeOn, validateOn]
390
+ );
391
+ const handleCompositionStart = (0, import_react2.useCallback)(
392
+ (_e) => {
393
+ isComposingRef.current = true;
394
+ },
395
+ []
396
+ );
397
+ const handleCompositionEnd = (0, import_react2.useCallback)(
398
+ (e) => {
399
+ isComposingRef.current = false;
400
+ const currentValue = e.currentTarget.value;
401
+ if (normalizeOn === "compositionEnd") {
402
+ const normalized = normalize(currentValue);
403
+ setValue(normalized);
404
+ if (validateOn === "blur" || validateOn === "change") {
405
+ setIsValidating(true);
406
+ setError(validate(normalized));
407
+ setIsValidating(false);
408
+ }
409
+ }
410
+ },
411
+ [normalize, validate, normalizeOn, validateOn]
412
+ );
413
+ return {
414
+ value,
415
+ onChange: handleChange,
416
+ onBlur: handleBlur,
417
+ onCompositionStart: handleCompositionStart,
418
+ onCompositionEnd: handleCompositionEnd,
419
+ error,
420
+ isValidating,
421
+ isComposing: isComposingRef.current
422
+ };
423
+ }
424
+
425
+ // src/hooks/usePrefectureField.ts
426
+ var import_react3 = require("react");
427
+
428
+ // src/validators/prefecture.ts
429
+ var PREFECTURES = [
430
+ "\u5317\u6D77\u9053",
431
+ "\u9752\u68EE\u770C",
432
+ "\u5CA9\u624B\u770C",
433
+ "\u5BAE\u57CE\u770C",
434
+ "\u79CB\u7530\u770C",
435
+ "\u5C71\u5F62\u770C",
436
+ "\u798F\u5CF6\u770C",
437
+ "\u8328\u57CE\u770C",
438
+ "\u6803\u6728\u770C",
439
+ "\u7FA4\u99AC\u770C",
440
+ "\u57FC\u7389\u770C",
441
+ "\u5343\u8449\u770C",
442
+ "\u6771\u4EAC\u90FD",
443
+ "\u795E\u5948\u5DDD\u770C",
444
+ "\u65B0\u6F5F\u770C",
445
+ "\u5BCC\u5C71\u770C",
446
+ "\u77F3\u5DDD\u770C",
447
+ "\u798F\u4E95\u770C",
448
+ "\u5C71\u68A8\u770C",
449
+ "\u9577\u91CE\u770C",
450
+ "\u5C90\u961C\u770C",
451
+ "\u9759\u5CA1\u770C",
452
+ "\u611B\u77E5\u770C",
453
+ "\u4E09\u91CD\u770C",
454
+ "\u6ECB\u8CC0\u770C",
455
+ "\u4EAC\u90FD\u5E9C",
456
+ "\u5927\u962A\u5E9C",
457
+ "\u5175\u5EAB\u770C",
458
+ "\u5948\u826F\u770C",
459
+ "\u548C\u6B4C\u5C71\u770C",
460
+ "\u9CE5\u53D6\u770C",
461
+ "\u5CF6\u6839\u770C",
462
+ "\u5CA1\u5C71\u770C",
463
+ "\u5E83\u5CF6\u770C",
464
+ "\u5C71\u53E3\u770C",
465
+ "\u5FB3\u5CF6\u770C",
466
+ "\u9999\u5DDD\u770C",
467
+ "\u611B\u5A9B\u770C",
468
+ "\u9AD8\u77E5\u770C",
469
+ "\u798F\u5CA1\u770C",
470
+ "\u4F50\u8CC0\u770C",
471
+ "\u9577\u5D0E\u770C",
472
+ "\u718A\u672C\u770C",
473
+ "\u5927\u5206\u770C",
474
+ "\u5BAE\u5D0E\u770C",
475
+ "\u9E7F\u5150\u5CF6\u770C",
476
+ "\u6C96\u7E04\u770C"
477
+ ];
478
+ var PREFECTURE_SHORT_NAMES = {
479
+ \u5317\u6D77: "\u5317\u6D77\u9053",
480
+ \u9752\u68EE: "\u9752\u68EE\u770C",
481
+ \u5CA9\u624B: "\u5CA9\u624B\u770C",
482
+ \u5BAE\u57CE: "\u5BAE\u57CE\u770C",
483
+ \u79CB\u7530: "\u79CB\u7530\u770C",
484
+ \u5C71\u5F62: "\u5C71\u5F62\u770C",
485
+ \u798F\u5CF6: "\u798F\u5CF6\u770C",
486
+ \u8328\u57CE: "\u8328\u57CE\u770C",
487
+ \u6803\u6728: "\u6803\u6728\u770C",
488
+ \u7FA4\u99AC: "\u7FA4\u99AC\u770C",
489
+ \u57FC\u7389: "\u57FC\u7389\u770C",
490
+ \u5343\u8449: "\u5343\u8449\u770C",
491
+ \u6771\u4EAC: "\u6771\u4EAC\u90FD",
492
+ \u795E\u5948\u5DDD: "\u795E\u5948\u5DDD\u770C",
493
+ \u65B0\u6F5F: "\u65B0\u6F5F\u770C",
494
+ \u5BCC\u5C71: "\u5BCC\u5C71\u770C",
495
+ \u77F3\u5DDD: "\u77F3\u5DDD\u770C",
496
+ \u798F\u4E95: "\u798F\u4E95\u770C",
497
+ \u5C71\u68A8: "\u5C71\u68A8\u770C",
498
+ \u9577\u91CE: "\u9577\u91CE\u770C",
499
+ \u5C90\u961C: "\u5C90\u961C\u770C",
500
+ \u9759\u5CA1: "\u9759\u5CA1\u770C",
501
+ \u611B\u77E5: "\u611B\u77E5\u770C",
502
+ \u4E09\u91CD: "\u4E09\u91CD\u770C",
503
+ \u6ECB\u8CC0: "\u6ECB\u8CC0\u770C",
504
+ \u4EAC\u90FD: "\u4EAC\u90FD\u5E9C",
505
+ \u5927\u962A: "\u5927\u962A\u5E9C",
506
+ \u5175\u5EAB: "\u5175\u5EAB\u770C",
507
+ \u5948\u826F: "\u5948\u826F\u770C",
508
+ \u548C\u6B4C\u5C71: "\u548C\u6B4C\u5C71\u770C",
509
+ \u9CE5\u53D6: "\u9CE5\u53D6\u770C",
510
+ \u5CF6\u6839: "\u5CF6\u6839\u770C",
511
+ \u5CA1\u5C71: "\u5CA1\u5C71\u770C",
512
+ \u5E83\u5CF6: "\u5E83\u5CF6\u770C",
513
+ \u5C71\u53E3: "\u5C71\u53E3\u770C",
514
+ \u5FB3\u5CF6: "\u5FB3\u5CF6\u770C",
515
+ \u9999\u5DDD: "\u9999\u5DDD\u770C",
516
+ \u611B\u5A9B: "\u611B\u5A9B\u770C",
517
+ \u9AD8\u77E5: "\u9AD8\u77E5\u770C",
518
+ \u798F\u5CA1: "\u798F\u5CA1\u770C",
519
+ \u4F50\u8CC0: "\u4F50\u8CC0\u770C",
520
+ \u9577\u5D0E: "\u9577\u5D0E\u770C",
521
+ \u718A\u672C: "\u718A\u672C\u770C",
522
+ \u5927\u5206: "\u5927\u5206\u770C",
523
+ \u5BAE\u5D0E: "\u5BAE\u5D0E\u770C",
524
+ \u9E7F\u5150\u5CF6: "\u9E7F\u5150\u5CF6\u770C",
525
+ \u6C96\u7E04: "\u6C96\u7E04\u770C"
526
+ };
527
+ function validatePrefecture(value) {
528
+ if (!value) return true;
529
+ return PREFECTURES.includes(value) || Object.keys(PREFECTURE_SHORT_NAMES).includes(value);
530
+ }
531
+ function normalizePrefecture(value) {
532
+ if (!value) return value;
533
+ if (PREFECTURES.includes(value)) {
534
+ return value;
535
+ }
536
+ return PREFECTURE_SHORT_NAMES[value] || value;
537
+ }
538
+
539
+ // src/hooks/usePrefectureField.ts
540
+ function usePrefectureField(options = {}) {
541
+ const {
542
+ autoComplete = true,
543
+ normalizeOn = "blur",
544
+ validateOn = "blur",
545
+ errorMessages = {}
546
+ } = options;
547
+ const [value, setValue] = (0, import_react3.useState)("");
548
+ const [error, setError] = (0, import_react3.useState)(null);
549
+ const [isValidating, setIsValidating] = (0, import_react3.useState)(false);
550
+ const isComposingRef = (0, import_react3.useRef)(false);
551
+ const messages = {
552
+ invalidPrefecture: errorMessages.invalidPrefecture ?? defaultErrorMessages.invalidPrefecture
553
+ };
554
+ const normalize = (0, import_react3.useCallback)(
555
+ (val) => {
556
+ if (autoComplete) {
557
+ return normalizePrefecture(val);
558
+ }
559
+ return val;
560
+ },
561
+ [autoComplete]
562
+ );
563
+ const validate = (0, import_react3.useCallback)(
564
+ (val) => {
565
+ if (!val) return null;
566
+ if (!validatePrefecture(val)) {
567
+ return messages.invalidPrefecture;
568
+ }
569
+ return null;
570
+ },
571
+ [messages.invalidPrefecture]
572
+ );
573
+ const handleChange = (0, import_react3.useCallback)(
574
+ (e) => {
575
+ const newValue = e.target.value;
576
+ setValue(newValue);
577
+ if (isComposingRef.current) return;
578
+ if (normalizeOn === "change") {
579
+ setValue(normalize(newValue));
580
+ }
581
+ if (validateOn === "change") {
582
+ setIsValidating(true);
583
+ const validationError = validate(
584
+ normalizeOn === "change" ? normalize(newValue) : newValue
585
+ );
586
+ setError(validationError);
587
+ setIsValidating(false);
588
+ }
589
+ },
590
+ [normalize, validate, normalizeOn, validateOn]
591
+ );
592
+ const handleBlur = (0, import_react3.useCallback)(
593
+ (e) => {
594
+ const currentValue = e.target.value;
595
+ if (normalizeOn === "blur") {
596
+ const normalized = normalize(currentValue);
597
+ setValue(normalized);
598
+ if (validateOn === "blur") {
599
+ setIsValidating(true);
600
+ setError(validate(normalized));
601
+ setIsValidating(false);
602
+ }
603
+ } else if (validateOn === "blur") {
604
+ setIsValidating(true);
605
+ setError(validate(currentValue));
606
+ setIsValidating(false);
607
+ }
608
+ },
609
+ [normalize, validate, normalizeOn, validateOn]
610
+ );
611
+ const handleCompositionStart = (0, import_react3.useCallback)(
612
+ (_e) => {
613
+ isComposingRef.current = true;
614
+ },
615
+ []
616
+ );
617
+ const handleCompositionEnd = (0, import_react3.useCallback)(
618
+ (e) => {
619
+ isComposingRef.current = false;
620
+ const currentValue = e.currentTarget.value;
621
+ if (normalizeOn === "compositionEnd") {
622
+ const normalized = normalize(currentValue);
623
+ setValue(normalized);
624
+ if (validateOn === "blur" || validateOn === "change") {
625
+ setIsValidating(true);
626
+ setError(validate(normalized));
627
+ setIsValidating(false);
628
+ }
629
+ }
630
+ },
631
+ [normalize, validate, normalizeOn, validateOn]
632
+ );
633
+ return {
634
+ value,
635
+ onChange: handleChange,
636
+ onBlur: handleBlur,
637
+ onCompositionStart: handleCompositionStart,
638
+ onCompositionEnd: handleCompositionEnd,
639
+ error,
640
+ isValidating,
641
+ isComposing: isComposingRef.current
642
+ };
643
+ }
644
+
645
+ // src/hooks/useAddressField.ts
646
+ var import_react4 = require("react");
647
+ function containsHalfWidthAlphanumeric(value) {
648
+ return /[A-Za-z0-9]/.test(value);
649
+ }
650
+ function useAddressField(options) {
651
+ const {
652
+ alphanumericMode,
653
+ onInvalid,
654
+ normalizeOn = "blur",
655
+ validateOn = "blur",
656
+ errorMessages = {}
657
+ } = options;
658
+ const [value, setValue] = (0, import_react4.useState)("");
659
+ const [error, setError] = (0, import_react4.useState)(null);
660
+ const [isValidating, setIsValidating] = (0, import_react4.useState)(false);
661
+ const isComposingRef = (0, import_react4.useRef)(false);
662
+ const messages = {
663
+ invalidWidth: errorMessages.invalidWidth ?? defaultErrorMessages.invalidWidth
664
+ };
665
+ const normalize = (0, import_react4.useCallback)(
666
+ (val) => {
667
+ if (alphanumericMode === "full-width-only" && onInvalid === "auto-convert") {
668
+ return toFullWidth(val);
669
+ }
670
+ return val;
671
+ },
672
+ [alphanumericMode, onInvalid]
673
+ );
674
+ const validate = (0, import_react4.useCallback)(
675
+ (val) => {
676
+ if (!val) return null;
677
+ if (alphanumericMode === "full-width-only" && onInvalid === "error" && containsHalfWidthAlphanumeric(val)) {
678
+ return messages.invalidWidth;
679
+ }
680
+ return null;
681
+ },
682
+ [alphanumericMode, onInvalid, messages.invalidWidth]
683
+ );
684
+ const handleChange = (0, import_react4.useCallback)(
685
+ (e) => {
686
+ const newValue = e.target.value;
687
+ setValue(newValue);
688
+ if (isComposingRef.current) return;
689
+ if (normalizeOn === "change") {
690
+ setValue(normalize(newValue));
691
+ }
692
+ if (validateOn === "change") {
693
+ setIsValidating(true);
694
+ const validationError = validate(
695
+ normalizeOn === "change" ? normalize(newValue) : newValue
696
+ );
697
+ setError(validationError);
698
+ setIsValidating(false);
699
+ }
700
+ },
701
+ [normalize, validate, normalizeOn, validateOn]
702
+ );
703
+ const handleBlur = (0, import_react4.useCallback)(
704
+ (e) => {
705
+ const currentValue = e.target.value;
706
+ if (normalizeOn === "blur") {
707
+ const normalized = normalize(currentValue);
708
+ setValue(normalized);
709
+ if (validateOn === "blur") {
710
+ setIsValidating(true);
711
+ setError(validate(normalized));
712
+ setIsValidating(false);
713
+ }
714
+ } else if (validateOn === "blur") {
715
+ setIsValidating(true);
716
+ setError(validate(currentValue));
717
+ setIsValidating(false);
718
+ }
719
+ },
720
+ [normalize, validate, normalizeOn, validateOn]
721
+ );
722
+ const handleCompositionStart = (0, import_react4.useCallback)(
723
+ (_e) => {
724
+ isComposingRef.current = true;
725
+ },
726
+ []
727
+ );
728
+ const handleCompositionEnd = (0, import_react4.useCallback)(
729
+ (e) => {
730
+ isComposingRef.current = false;
731
+ const currentValue = e.currentTarget.value;
732
+ if (normalizeOn === "compositionEnd") {
733
+ const normalized = normalize(currentValue);
734
+ setValue(normalized);
735
+ if (validateOn === "blur" || validateOn === "change") {
736
+ setIsValidating(true);
737
+ setError(validate(normalized));
738
+ setIsValidating(false);
739
+ }
740
+ }
741
+ },
742
+ [normalize, validate, normalizeOn, validateOn]
743
+ );
744
+ return {
745
+ value,
746
+ onChange: handleChange,
747
+ onBlur: handleBlur,
748
+ onCompositionStart: handleCompositionStart,
749
+ onCompositionEnd: handleCompositionEnd,
750
+ error,
751
+ isValidating,
752
+ isComposing: isComposingRef.current
753
+ };
754
+ }
755
+
756
+ // src/hooks/usePhoneNumberField.ts
757
+ var import_react5 = require("react");
758
+
759
+ // src/validators/phoneNumber.ts
760
+ function validatePhoneNumber(value) {
761
+ if (!value) return true;
762
+ const normalized = value.replace(/[0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 65248)).replace(/[ー-]/g, "-");
763
+ const digitsOnly = normalized.replace(/-/g, "");
764
+ if (digitsOnly.length < 10 || digitsOnly.length > 11) {
765
+ return false;
766
+ }
767
+ const phoneRegex = /^[\d-]+$/;
768
+ return phoneRegex.test(normalized);
769
+ }
770
+ function isHalfWidthPhoneNumber(value) {
771
+ if (!value) return true;
772
+ const halfWidthRegex = /^[\d-]+$/;
773
+ return halfWidthRegex.test(value);
774
+ }
775
+ function containsFullWidthPhoneNumber(value) {
776
+ if (!value) return false;
777
+ const fullWidthRegex = /[0-9ー-]/;
778
+ return fullWidthRegex.test(value);
779
+ }
780
+
781
+ // src/hooks/usePhoneNumberField.ts
782
+ function usePhoneNumberField(options) {
783
+ const {
784
+ onInvalid,
785
+ autoHyphen = true,
786
+ normalizeOn = "blur",
787
+ validateOn = "blur",
788
+ errorMessages = {}
789
+ } = options;
790
+ const [value, setValue] = (0, import_react5.useState)("");
791
+ const [error, setError] = (0, import_react5.useState)(null);
792
+ const [isValidating, setIsValidating] = (0, import_react5.useState)(false);
793
+ const isComposingRef = (0, import_react5.useRef)(false);
794
+ const messages = {
795
+ invalidWidth: errorMessages.invalidWidth ?? defaultErrorMessages.invalidWidth,
796
+ invalidFormat: errorMessages.invalidFormat ?? defaultErrorMessages.invalidPhoneNumber
797
+ };
798
+ const normalize = (0, import_react5.useCallback)(
799
+ (val) => {
800
+ let normalized = val;
801
+ if (onInvalid === "auto-convert") {
802
+ normalized = toHalfWidthNumbers(normalized);
803
+ normalized = toHalfWidthHyphen(normalized);
804
+ }
805
+ if (autoHyphen) {
806
+ normalized = addPhoneNumberHyphen(normalized);
807
+ }
808
+ return normalized;
809
+ },
810
+ [onInvalid, autoHyphen]
811
+ );
812
+ const validate = (0, import_react5.useCallback)(
813
+ (val) => {
814
+ if (!val) return null;
815
+ if (onInvalid === "error" && containsFullWidthPhoneNumber(val)) {
816
+ return messages.invalidWidth;
817
+ }
818
+ if (!validatePhoneNumber(val)) {
819
+ return messages.invalidFormat;
820
+ }
821
+ return null;
822
+ },
823
+ [onInvalid, messages.invalidWidth, messages.invalidFormat]
824
+ );
825
+ const handleChange = (0, import_react5.useCallback)(
826
+ (e) => {
827
+ const newValue = e.target.value;
828
+ setValue(newValue);
829
+ if (isComposingRef.current) return;
830
+ if (normalizeOn === "change") {
831
+ setValue(normalize(newValue));
832
+ }
833
+ if (validateOn === "change") {
834
+ setIsValidating(true);
835
+ const validationError = validate(
836
+ normalizeOn === "change" ? normalize(newValue) : newValue
837
+ );
838
+ setError(validationError);
839
+ setIsValidating(false);
840
+ }
841
+ },
842
+ [normalize, validate, normalizeOn, validateOn]
843
+ );
844
+ const handleBlur = (0, import_react5.useCallback)(
845
+ (e) => {
846
+ const currentValue = e.target.value;
847
+ if (normalizeOn === "blur") {
848
+ const normalized = normalize(currentValue);
849
+ setValue(normalized);
850
+ if (validateOn === "blur") {
851
+ setIsValidating(true);
852
+ setError(validate(normalized));
853
+ setIsValidating(false);
854
+ }
855
+ } else if (validateOn === "blur") {
856
+ setIsValidating(true);
857
+ setError(validate(currentValue));
858
+ setIsValidating(false);
859
+ }
860
+ },
861
+ [normalize, validate, normalizeOn, validateOn]
862
+ );
863
+ const handleCompositionStart = (0, import_react5.useCallback)(
864
+ (_e) => {
865
+ isComposingRef.current = true;
866
+ },
867
+ []
868
+ );
869
+ const handleCompositionEnd = (0, import_react5.useCallback)(
870
+ (e) => {
871
+ isComposingRef.current = false;
872
+ const currentValue = e.currentTarget.value;
873
+ if (normalizeOn === "compositionEnd") {
874
+ const normalized = normalize(currentValue);
875
+ setValue(normalized);
876
+ if (validateOn === "blur" || validateOn === "change") {
877
+ setIsValidating(true);
878
+ setError(validate(normalized));
879
+ setIsValidating(false);
880
+ }
881
+ }
882
+ },
883
+ [normalize, validate, normalizeOn, validateOn]
884
+ );
885
+ return {
886
+ value,
887
+ onChange: handleChange,
888
+ onBlur: handleBlur,
889
+ onCompositionStart: handleCompositionStart,
890
+ onCompositionEnd: handleCompositionEnd,
891
+ error,
892
+ isValidating,
893
+ isComposing: isComposingRef.current
894
+ };
895
+ }
896
+
897
+ // src/validators/hiragana.ts
898
+ function validateHiragana(value) {
899
+ if (!value) return true;
900
+ const hiraganaRegex = /^[\u3040-\u309F\u30FC\u3000\s]+$/;
901
+ return hiraganaRegex.test(value);
902
+ }
903
+ function containsKatakana(value) {
904
+ if (!value) return false;
905
+ const katakanaRegex = /[\u30A0-\u30FF]/;
906
+ return katakanaRegex.test(value);
907
+ }
908
+
909
+ // src/normalizers/toHiragana.ts
910
+ function toHiragana(value) {
911
+ if (!value) return value;
912
+ return value.replace(/[\u30A1-\u30F6]/g, (char) => {
913
+ return String.fromCharCode(char.charCodeAt(0) - 96);
914
+ });
915
+ }
916
+ // Annotate the CommonJS export names for ESM import in node:
917
+ 0 && (module.exports = {
918
+ PREFECTURES,
919
+ PREFECTURE_SHORT_NAMES,
920
+ addPhoneNumberHyphen,
921
+ addPostalCodeHyphen,
922
+ containsFullWidthPhoneNumber,
923
+ containsHiragana,
924
+ containsKatakana,
925
+ defaultErrorMessages,
926
+ isFullWidthPostalCode,
927
+ isHalfWidthPhoneNumber,
928
+ isHalfWidthPostalCode,
929
+ normalizePrefecture,
930
+ toFullWidth,
931
+ toFullWidthHyphen,
932
+ toFullWidthNumbers,
933
+ toHalfWidth,
934
+ toHalfWidthHyphen,
935
+ toHalfWidthNumbers,
936
+ toHiragana,
937
+ toKatakana,
938
+ useAddressField,
939
+ useNameField,
940
+ usePhoneNumberField,
941
+ usePostalCodeField,
942
+ usePrefectureField,
943
+ validateHiragana,
944
+ validateKatakana,
945
+ validatePhoneNumber,
946
+ validatePostalCode,
947
+ validatePrefecture
948
+ });