@cp949/japanpost-react 1.0.2 → 1.0.4

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.
Files changed (33) hide show
  1. package/README.ko.md +27 -1
  2. package/README.md +24 -0
  3. package/dist/{src/core/types.d.ts → client.d.ts} +64 -29
  4. package/dist/client.es.js +495 -0
  5. package/dist/index.d.ts +291 -1
  6. package/dist/index.es.js +512 -459
  7. package/package.json +10 -10
  8. package/dist/index.umd.cjs +0 -6
  9. package/dist/src/components/AddressSearchInput.d.ts +0 -8
  10. package/dist/src/components/AddressSearchInput.d.ts.map +0 -1
  11. package/dist/src/components/PostalCodeInput.d.ts +0 -8
  12. package/dist/src/components/PostalCodeInput.d.ts.map +0 -1
  13. package/dist/src/core/errors.d.ts +0 -11
  14. package/dist/src/core/errors.d.ts.map +0 -1
  15. package/dist/src/core/formatters.d.ts +0 -12
  16. package/dist/src/core/formatters.d.ts.map +0 -1
  17. package/dist/src/core/normalizers.d.ts +0 -7
  18. package/dist/src/core/normalizers.d.ts.map +0 -1
  19. package/dist/src/core/types.d.ts.map +0 -1
  20. package/dist/src/core/validators.d.ts +0 -6
  21. package/dist/src/core/validators.d.ts.map +0 -1
  22. package/dist/src/index.d.ts +0 -11
  23. package/dist/src/index.d.ts.map +0 -1
  24. package/dist/src/react/toJapanAddressError.d.ts +0 -8
  25. package/dist/src/react/toJapanAddressError.d.ts.map +0 -1
  26. package/dist/src/react/useJapanAddress.d.ts +0 -8
  27. package/dist/src/react/useJapanAddress.d.ts.map +0 -1
  28. package/dist/src/react/useJapanAddressSearch.d.ts +0 -7
  29. package/dist/src/react/useJapanAddressSearch.d.ts.map +0 -1
  30. package/dist/src/react/useJapanPostalCode.d.ts +0 -7
  31. package/dist/src/react/useJapanPostalCode.d.ts.map +0 -1
  32. package/dist/src/react/useLatestRequestState.d.ts +0 -23
  33. package/dist/src/react/useLatestRequestState.d.ts.map +0 -1
package/dist/index.es.js CHANGED
@@ -1,477 +1,530 @@
1
- import { useCallback as e, useEffect as t, useMemo as n, useRef as r, useState as i } from "react";
2
- //#region \0rolldown/runtime.js
3
- var a = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), o = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
4
- if (typeof require < "u") return require.apply(this, arguments);
5
- throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
6
- }), s = /* @__PURE__ */ a(((e) => {
7
- var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
8
- function r(e, n, r) {
9
- var i = null;
10
- if (r !== void 0 && (i = "" + r), n.key !== void 0 && (i = "" + n.key), "key" in n) for (var a in r = {}, n) a !== "key" && (r[a] = n[a]);
11
- else r = n;
12
- return n = r.ref, {
13
- $$typeof: t,
14
- type: e,
15
- key: i,
16
- ref: n === void 0 ? null : n,
17
- props: r
18
- };
19
- }
20
- e.Fragment = n, e.jsx = r, e.jsxs = r;
21
- })), c = /* @__PURE__ */ a(((e) => {
22
- process.env.NODE_ENV !== "production" && (function() {
23
- function t(e) {
24
- if (e == null) return null;
25
- if (typeof e == "function") return e.$$typeof === k ? null : e.displayName || e.name || null;
26
- if (typeof e == "string") return e;
27
- switch (e) {
28
- case v: return "Fragment";
29
- case b: return "Profiler";
30
- case y: return "StrictMode";
31
- case w: return "Suspense";
32
- case T: return "SuspenseList";
33
- case O: return "Activity";
34
- }
35
- if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) {
36
- case _: return "Portal";
37
- case S: return e.displayName || "Context";
38
- case x: return (e._context.displayName || "Context") + ".Consumer";
39
- case C:
40
- var n = e.render;
41
- return e = e.displayName, e ||= (e = n.displayName || n.name || "", e === "" ? "ForwardRef" : "ForwardRef(" + e + ")"), e;
42
- case E: return n = e.displayName || null, n === null ? t(e.type) || "Memo" : n;
43
- case D:
44
- n = e._payload, e = e._init;
45
- try {
46
- return t(e(n));
47
- } catch {}
48
- }
49
- return null;
50
- }
51
- function n(e) {
52
- return "" + e;
53
- }
54
- function r(e) {
55
- try {
56
- n(e);
57
- var t = !1;
58
- } catch {
59
- t = !0;
60
- }
61
- if (t) {
62
- t = console;
63
- var r = t.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
64
- return r.call(t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), n(e);
65
- }
66
- }
67
- function i(e) {
68
- if (e === v) return "<>";
69
- if (typeof e == "object" && e && e.$$typeof === D) return "<...>";
70
- try {
71
- var n = t(e);
72
- return n ? "<" + n + ">" : "<...>";
73
- } catch {
74
- return "<...>";
75
- }
76
- }
77
- function a() {
78
- var e = A.A;
79
- return e === null ? null : e.getOwner();
80
- }
81
- function s() {
82
- return Error("react-stack-top-frame");
83
- }
84
- function c(e) {
85
- if (j.call(e, "key")) {
86
- var t = Object.getOwnPropertyDescriptor(e, "key").get;
87
- if (t && t.isReactWarning) return !1;
88
- }
89
- return e.key !== void 0;
90
- }
91
- function l(e, t) {
92
- function n() {
93
- P || (P = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", t));
94
- }
95
- n.isReactWarning = !0, Object.defineProperty(e, "key", {
96
- get: n,
97
- configurable: !0
98
- });
99
- }
100
- function u() {
101
- var e = t(this.type);
102
- return F[e] || (F[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), e = this.props.ref, e === void 0 ? null : e;
103
- }
104
- function d(e, t, n, r, i, a) {
105
- var o = n.ref;
106
- return e = {
107
- $$typeof: g,
108
- type: e,
109
- key: t,
110
- props: n,
111
- _owner: r
112
- }, (o === void 0 ? null : o) === null ? Object.defineProperty(e, "ref", {
113
- enumerable: !1,
114
- value: null
115
- }) : Object.defineProperty(e, "ref", {
116
- enumerable: !1,
117
- get: u
118
- }), e._store = {}, Object.defineProperty(e._store, "validated", {
119
- configurable: !1,
120
- enumerable: !1,
121
- writable: !0,
122
- value: 0
123
- }), Object.defineProperty(e, "_debugInfo", {
124
- configurable: !1,
125
- enumerable: !1,
126
- writable: !0,
127
- value: null
128
- }), Object.defineProperty(e, "_debugStack", {
129
- configurable: !1,
130
- enumerable: !1,
131
- writable: !0,
132
- value: i
133
- }), Object.defineProperty(e, "_debugTask", {
134
- configurable: !1,
135
- enumerable: !1,
136
- writable: !0,
137
- value: a
138
- }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
139
- }
140
- function f(e, n, i, o, s, u) {
141
- var f = n.children;
142
- if (f !== void 0) if (o) if (M(f)) {
143
- for (o = 0; o < f.length; o++) p(f[o]);
144
- Object.freeze && Object.freeze(f);
145
- } else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
146
- else p(f);
147
- if (j.call(n, "key")) {
148
- f = t(e);
149
- var m = Object.keys(n).filter(function(e) {
150
- return e !== "key";
151
- });
152
- o = 0 < m.length ? "{key: someKey, " + m.join(": ..., ") + ": ...}" : "{key: someKey}", R[f + o] || (m = 0 < m.length ? "{" + m.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", o, f, m, f), R[f + o] = !0);
153
- }
154
- if (f = null, i !== void 0 && (r(i), f = "" + i), c(n) && (r(n.key), f = "" + n.key), "key" in n) for (var h in i = {}, n) h !== "key" && (i[h] = n[h]);
155
- else i = n;
156
- return f && l(i, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), d(e, f, i, a(), s, u);
157
- }
158
- function p(e) {
159
- m(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e && e.$$typeof === D && (e._payload.status === "fulfilled" ? m(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
160
- }
161
- function m(e) {
162
- return typeof e == "object" && !!e && e.$$typeof === g;
163
- }
164
- var h = o("react"), g = Symbol.for("react.transitional.element"), _ = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), y = Symbol.for("react.strict_mode"), b = Symbol.for("react.profiler"), x = Symbol.for("react.consumer"), S = Symbol.for("react.context"), C = Symbol.for("react.forward_ref"), w = Symbol.for("react.suspense"), T = Symbol.for("react.suspense_list"), E = Symbol.for("react.memo"), D = Symbol.for("react.lazy"), O = Symbol.for("react.activity"), k = Symbol.for("react.client.reference"), A = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, j = Object.prototype.hasOwnProperty, M = Array.isArray, N = console.createTask ? console.createTask : function() {
165
- return null;
166
- };
167
- h = { react_stack_bottom_frame: function(e) {
168
- return e();
169
- } };
170
- var P, F = {}, I = h.react_stack_bottom_frame.bind(h, s)(), L = N(i(s)), R = {};
171
- e.Fragment = v, e.jsx = function(e, t, n) {
172
- var r = 1e4 > A.recentlyCreatedOwnerStacks++;
173
- return f(e, t, n, !1, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
174
- }, e.jsxs = function(e, t, n) {
175
- var r = 1e4 > A.recentlyCreatedOwnerStacks++;
176
- return f(e, t, n, !0, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
177
- };
178
- })();
179
- })), l = (/* @__PURE__ */ a(((e, t) => {
180
- process.env.NODE_ENV === "production" ? t.exports = s() : t.exports = c();
181
- })))();
182
- function u({ defaultValue: e = "", value: t, disabled: n, label: r = "Address keyword", buttonLabel: a = "Search", inputProps: o, buttonProps: s, onChange: c, onSearch: u }) {
183
- let [d, f] = i(e), p = t ?? d;
184
- function m(e) {
185
- e.preventDefault(), u(p.trim());
186
- }
187
- function h(e) {
188
- t === void 0 && f(e), c?.(e);
189
- }
190
- return /* @__PURE__ */ (0, l.jsxs)("form", {
191
- onSubmit: m,
192
- children: [/* @__PURE__ */ (0, l.jsxs)("label", { children: [r, /* @__PURE__ */ (0, l.jsx)("input", {
193
- ...o,
194
- disabled: n,
195
- value: p,
196
- onChange: (e) => h(e.target.value)
197
- })] }), /* @__PURE__ */ (0, l.jsx)("button", {
198
- ...s,
199
- disabled: n,
200
- type: "submit",
201
- children: a
202
- })]
203
- });
1
+ import { useState, useMemo, useRef, useCallback, useEffect } from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/AddressSearchInput.tsx
5
+ function AddressSearchInput({
6
+ defaultValue = "",
7
+ value,
8
+ disabled,
9
+ label = "Address keyword",
10
+ buttonLabel = "Search",
11
+ inputProps,
12
+ buttonProps,
13
+ onChange,
14
+ onSearch
15
+ }) {
16
+ const [internalValue, setInternalValue] = useState(defaultValue);
17
+ const currentValue = value ?? internalValue;
18
+ function handleSubmit(event) {
19
+ event.preventDefault();
20
+ onSearch(currentValue.trim());
21
+ }
22
+ function handleChange(nextValue) {
23
+ if (value === void 0) {
24
+ setInternalValue(nextValue);
25
+ }
26
+ onChange?.(nextValue);
27
+ }
28
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
29
+ /* @__PURE__ */ jsxs("label", { children: [
30
+ label,
31
+ /* @__PURE__ */ jsx(
32
+ "input",
33
+ {
34
+ ...inputProps,
35
+ disabled,
36
+ value: currentValue,
37
+ onChange: (event) => handleChange(event.target.value)
38
+ }
39
+ )
40
+ ] }),
41
+ /* @__PURE__ */ jsx("button", { ...buttonProps, disabled, type: "submit", children: buttonLabel })
42
+ ] });
204
43
  }
205
- //#endregion
206
- //#region src/core/formatters.ts
207
- function d(e) {
208
- return e.replace(/[^\d]/g, "");
44
+
45
+ // src/core/formatters.ts
46
+ function normalizeJapanPostalCode(value) {
47
+ return value.replace(/[^\d]/g, "");
209
48
  }
210
- function f(e) {
211
- let t = d(e);
212
- return t.length === 7 ? `${t.slice(0, 3)}-${t.slice(3)}` : t;
49
+ function formatJapanPostalCode(value) {
50
+ const normalized = normalizeJapanPostalCode(value);
51
+ if (normalized.length !== 7) {
52
+ return normalized;
53
+ }
54
+ return `${normalized.slice(0, 3)}-${normalized.slice(3)}`;
213
55
  }
214
- //#endregion
215
- //#region src/components/PostalCodeInput.tsx
216
- function p({ defaultValue: e = "", value: t, disabled: n, label: r = "Postal code", buttonLabel: a = "Search", inputProps: o, buttonProps: s, onChange: c, onSearch: u }) {
217
- let [f, p] = i(e), m = t ?? f;
218
- function h(e) {
219
- e.preventDefault(), u(d(m));
220
- }
221
- function g(e) {
222
- t === void 0 && p(e), c?.(e);
223
- }
224
- return /* @__PURE__ */ (0, l.jsxs)("form", {
225
- onSubmit: h,
226
- children: [/* @__PURE__ */ (0, l.jsxs)("label", { children: [r, /* @__PURE__ */ (0, l.jsx)("input", {
227
- ...o,
228
- disabled: n,
229
- inputMode: o?.inputMode ?? "numeric",
230
- value: m,
231
- onChange: (e) => g(e.target.value)
232
- })] }), /* @__PURE__ */ (0, l.jsx)("button", {
233
- ...s,
234
- disabled: n,
235
- type: "submit",
236
- children: a
237
- })]
238
- });
56
+ function PostalCodeInput({
57
+ defaultValue = "",
58
+ value,
59
+ disabled,
60
+ label = "Postal code",
61
+ buttonLabel = "Search",
62
+ inputProps,
63
+ buttonProps,
64
+ onChange,
65
+ onSearch
66
+ }) {
67
+ const [internalValue, setInternalValue] = useState(defaultValue);
68
+ const currentValue = value ?? internalValue;
69
+ function handleSubmit(event) {
70
+ event.preventDefault();
71
+ onSearch(normalizeJapanPostalCode(currentValue));
72
+ }
73
+ function handleChange(nextValue) {
74
+ if (value === void 0) {
75
+ setInternalValue(nextValue);
76
+ }
77
+ onChange?.(nextValue);
78
+ }
79
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
80
+ /* @__PURE__ */ jsxs("label", { children: [
81
+ label,
82
+ /* @__PURE__ */ jsx(
83
+ "input",
84
+ {
85
+ ...inputProps,
86
+ disabled,
87
+ inputMode: inputProps?.inputMode ?? "numeric",
88
+ value: currentValue,
89
+ onChange: (event) => handleChange(event.target.value)
90
+ }
91
+ )
92
+ ] }),
93
+ /* @__PURE__ */ jsx("button", { ...buttonProps, disabled, type: "submit", children: buttonLabel })
94
+ ] });
239
95
  }
240
- //#endregion
241
- //#region src/core/errors.ts
242
- function m(e, t, n) {
243
- let r = Error(t);
244
- return r.name = "JapanAddressError", r.code = e, r.cause = n?.cause, r.status = n?.status, r;
96
+
97
+ // src/core/errors.ts
98
+ function createJapanAddressError(code, message, options) {
99
+ const error = new Error(message);
100
+ error.name = "JapanAddressError";
101
+ error.code = code;
102
+ error.cause = options?.cause;
103
+ error.status = options?.status;
104
+ return error;
245
105
  }
246
- //#endregion
247
- //#region src/core/normalizers.ts
248
- function h(e) {
249
- return e.filter(Boolean).join(" ").trim();
106
+
107
+ // src/core/normalizers.ts
108
+ function joinAddressParts(parts) {
109
+ return parts.filter(Boolean).join(" ").trim();
250
110
  }
251
- function g(e) {
252
- let t = h([
253
- e.prefecture,
254
- e.city,
255
- e.town,
256
- e.detail ?? ""
257
- ]);
258
- return {
259
- postalCode: e.postalCode,
260
- prefecture: e.prefecture,
261
- prefectureKana: e.prefectureKana,
262
- city: e.city,
263
- cityKana: e.cityKana,
264
- town: e.town,
265
- townKana: e.townKana,
266
- address: t,
267
- provider: "japan-post"
268
- };
111
+ function normalizeJapanPostAddressRecord(record) {
112
+ const address = joinAddressParts([
113
+ record.prefecture,
114
+ record.city,
115
+ record.town,
116
+ record.detail ?? ""
117
+ ]);
118
+ return {
119
+ postalCode: record.postalCode,
120
+ prefecture: record.prefecture,
121
+ prefectureKana: record.prefectureKana,
122
+ city: record.city,
123
+ cityKana: record.cityKana,
124
+ town: record.town,
125
+ townKana: record.townKana,
126
+ address,
127
+ provider: "japan-post"
128
+ };
269
129
  }
270
- //#endregion
271
- //#region src/core/validators.ts
272
- function _(e) {
273
- return /^\d{7}$/.test(d(e));
130
+
131
+ // src/core/validators.ts
132
+ function isValidJapanPostalCode(value) {
133
+ return /^\d{7}$/.test(normalizeJapanPostalCode(value));
274
134
  }
275
- //#endregion
276
- //#region src/react/toJapanAddressError.ts
277
- function v(e) {
278
- return typeof e == "object" && e && "code" in e && typeof e.code == "string" ? e : m("data_source_error", e instanceof Error ? e.message : "Unknown error", { cause: e });
135
+
136
+ // src/react/toJapanAddressError.ts
137
+ function toJapanAddressError(error) {
138
+ if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
139
+ return error;
140
+ }
141
+ return createJapanAddressError(
142
+ "data_source_error",
143
+ error instanceof Error ? error.message : "Unknown error",
144
+ {
145
+ cause: error
146
+ }
147
+ );
279
148
  }
280
- //#endregion
281
- //#region src/react/useLatestRequestState.ts
282
- function y() {
283
- let n = r(0), a = r(!0), o = r(null), [s, c] = i(!1), [l, u] = i(null), [d, f] = i(null), p = e((e) => a.current && e === n.current, []), m = e(() => {
284
- n.current += 1, o.current?.abort(), o.current = null;
285
- }, []);
286
- t(() => (a.current = !0, () => {
287
- a.current = !1, m();
288
- }), [m]);
289
- let h = e(() => {
290
- let e = n.current + 1;
291
- n.current = e, o.current?.abort();
292
- let t = new AbortController();
293
- return o.current = t, c(!0), f(null), {
294
- requestId: e,
295
- signal: t.signal
296
- };
297
- }, []), g = e((e, t) => {
298
- p(e) && u(t);
299
- }, [p]), _ = e((e, t) => (p(e) && (f(t), u(null)), null), [p]), v = e(() => {
300
- m(), c(!1);
301
- }, [m]);
302
- return {
303
- loading: s,
304
- data: l,
305
- error: d,
306
- beginRequest: h,
307
- setSuccess: g,
308
- setFailure: _,
309
- finishRequest: e((e) => {
310
- p(e) && (c(!1), o.current = null);
311
- }, [p]),
312
- cancel: v,
313
- reset: e(() => {
314
- v(), u(null), f(null);
315
- }, [v])
316
- };
149
+ function useLatestRequestState() {
150
+ const requestIdRef = useRef(0);
151
+ const isMountedRef = useRef(true);
152
+ const abortControllerRef = useRef(null);
153
+ const [loading, setLoading] = useState(false);
154
+ const [data, setData] = useState(null);
155
+ const [error, setError] = useState(null);
156
+ const isCurrentRequest = useCallback((requestId) => {
157
+ return isMountedRef.current && requestId === requestIdRef.current;
158
+ }, []);
159
+ const invalidateCurrentRequest = useCallback(() => {
160
+ requestIdRef.current += 1;
161
+ abortControllerRef.current?.abort();
162
+ abortControllerRef.current = null;
163
+ }, []);
164
+ useEffect(() => {
165
+ isMountedRef.current = true;
166
+ return () => {
167
+ isMountedRef.current = false;
168
+ invalidateCurrentRequest();
169
+ };
170
+ }, [invalidateCurrentRequest]);
171
+ const beginRequest = useCallback(() => {
172
+ const requestId = requestIdRef.current + 1;
173
+ requestIdRef.current = requestId;
174
+ abortControllerRef.current?.abort();
175
+ const abortController = new AbortController();
176
+ abortControllerRef.current = abortController;
177
+ setLoading(true);
178
+ setError(null);
179
+ return {
180
+ requestId,
181
+ signal: abortController.signal
182
+ };
183
+ }, []);
184
+ const setSuccess = useCallback((requestId, result) => {
185
+ if (isCurrentRequest(requestId)) {
186
+ setData(result);
187
+ }
188
+ }, [isCurrentRequest]);
189
+ const setFailure = useCallback(
190
+ (requestId, nextError) => {
191
+ if (isCurrentRequest(requestId)) {
192
+ setError(nextError);
193
+ setData(null);
194
+ }
195
+ return null;
196
+ },
197
+ [isCurrentRequest]
198
+ );
199
+ const cancel = useCallback(() => {
200
+ invalidateCurrentRequest();
201
+ setLoading(false);
202
+ }, [invalidateCurrentRequest]);
203
+ const finishRequest = useCallback((requestId) => {
204
+ if (isCurrentRequest(requestId)) {
205
+ setLoading(false);
206
+ abortControllerRef.current = null;
207
+ }
208
+ }, [isCurrentRequest]);
209
+ const reset = useCallback(() => {
210
+ cancel();
211
+ setData(null);
212
+ setError(null);
213
+ }, [cancel]);
214
+ return {
215
+ loading,
216
+ data,
217
+ error,
218
+ beginRequest,
219
+ setSuccess,
220
+ setFailure,
221
+ finishRequest,
222
+ cancel,
223
+ reset
224
+ };
317
225
  }
318
- //#endregion
319
- //#region src/react/useJapanAddressSearch.ts
320
- function b(e) {
321
- if (e) return e;
322
- throw Error("useJapanAddressSearch requires options.dataSource");
226
+
227
+ // src/react/useJapanAddressSearch.ts
228
+ function resolveAddressSearchDataSource(dataSource) {
229
+ if (dataSource) {
230
+ return dataSource;
231
+ }
232
+ throw new Error("useJapanAddressSearch requires options.dataSource");
323
233
  }
324
- function x(e) {
325
- return e?.trim() || void 0;
234
+ function normalizeSearchText(value) {
235
+ const normalized = value?.trim();
236
+ return normalized ? normalized : void 0;
326
237
  }
327
- function S(e) {
328
- let t = typeof e == "string" ? { addressQuery: e } : e, n = x(t.addressQuery), r = x(t.prefCode), i = x(t.prefName), a = x(t.prefKana), o = x(t.prefRoma), s = x(t.cityCode), c = x(t.cityName), l = x(t.cityKana), u = x(t.cityRoma), d = x(t.townName), f = x(t.townKana), p = x(t.townRoma);
329
- return n === void 0 && r === void 0 && i === void 0 && a === void 0 && o === void 0 && s === void 0 && c === void 0 && l === void 0 && u === void 0 && d === void 0 && f === void 0 && p === void 0 ? null : {
330
- ...n === void 0 ? {} : { addressQuery: n },
331
- ...r === void 0 ? {} : { prefCode: r },
332
- ...i === void 0 ? {} : { prefName: i },
333
- ...a === void 0 ? {} : { prefKana: a },
334
- ...o === void 0 ? {} : { prefRoma: o },
335
- ...s === void 0 ? {} : { cityCode: s },
336
- ...c === void 0 ? {} : { cityName: c },
337
- ...l === void 0 ? {} : { cityKana: l },
338
- ...u === void 0 ? {} : { cityRoma: u },
339
- ...d === void 0 ? {} : { townName: d },
340
- ...f === void 0 ? {} : { townKana: f },
341
- ...p === void 0 ? {} : { townRoma: p },
342
- pageNumber: t.pageNumber ?? 0,
343
- rowsPerPage: t.rowsPerPage ?? 100,
344
- ...t.includeCityDetails === void 0 ? {} : { includeCityDetails: t.includeCityDetails },
345
- ...t.includePrefectureDetails === void 0 ? {} : { includePrefectureDetails: t.includePrefectureDetails }
346
- };
238
+ function normalizeAddressSearchInput(input) {
239
+ const request = typeof input === "string" ? { addressQuery: input } : input;
240
+ const addressQuery = normalizeSearchText(request.addressQuery);
241
+ const prefCode = normalizeSearchText(request.prefCode);
242
+ const prefName = normalizeSearchText(request.prefName);
243
+ const prefKana = normalizeSearchText(request.prefKana);
244
+ const prefRoma = normalizeSearchText(request.prefRoma);
245
+ const cityCode = normalizeSearchText(request.cityCode);
246
+ const cityName = normalizeSearchText(request.cityName);
247
+ const cityKana = normalizeSearchText(request.cityKana);
248
+ const cityRoma = normalizeSearchText(request.cityRoma);
249
+ const townName = normalizeSearchText(request.townName);
250
+ const townKana = normalizeSearchText(request.townKana);
251
+ const townRoma = normalizeSearchText(request.townRoma);
252
+ if (addressQuery === void 0 && prefCode === void 0 && prefName === void 0 && prefKana === void 0 && prefRoma === void 0 && cityCode === void 0 && cityName === void 0 && cityKana === void 0 && cityRoma === void 0 && townName === void 0 && townKana === void 0 && townRoma === void 0) {
253
+ return null;
254
+ }
255
+ return {
256
+ ...addressQuery === void 0 ? {} : { addressQuery },
257
+ ...prefCode === void 0 ? {} : { prefCode },
258
+ ...prefName === void 0 ? {} : { prefName },
259
+ ...prefKana === void 0 ? {} : { prefKana },
260
+ ...prefRoma === void 0 ? {} : { prefRoma },
261
+ ...cityCode === void 0 ? {} : { cityCode },
262
+ ...cityName === void 0 ? {} : { cityName },
263
+ ...cityKana === void 0 ? {} : { cityKana },
264
+ ...cityRoma === void 0 ? {} : { cityRoma },
265
+ ...townName === void 0 ? {} : { townName },
266
+ ...townKana === void 0 ? {} : { townKana },
267
+ ...townRoma === void 0 ? {} : { townRoma },
268
+ pageNumber: request.pageNumber ?? 0,
269
+ rowsPerPage: request.rowsPerPage ?? 100,
270
+ ...request.includeCityDetails === void 0 ? {} : {
271
+ includeCityDetails: request.includeCityDetails
272
+ },
273
+ ...request.includePrefectureDetails === void 0 ? {} : {
274
+ includePrefectureDetails: request.includePrefectureDetails
275
+ }
276
+ };
347
277
  }
348
- function C(e) {
349
- return e.aborted ? Promise.resolve(null) : new Promise((t) => {
350
- let n = () => {
351
- e.removeEventListener("abort", n), t(null);
352
- };
353
- e.addEventListener("abort", n, { once: !0 });
354
- });
278
+ function waitForAbort(signal) {
279
+ if (signal.aborted) {
280
+ return Promise.resolve(null);
281
+ }
282
+ return new Promise((resolve) => {
283
+ const onAbort = () => {
284
+ signal.removeEventListener("abort", onAbort);
285
+ resolve(null);
286
+ };
287
+ signal.addEventListener("abort", onAbort, { once: true });
288
+ });
355
289
  }
356
- function w(i) {
357
- let a = n(() => b(i.dataSource), [i.dataSource]), o = i.debounceMs ?? 0, s = r(null), c = r(null), { loading: l, data: u, error: d, beginRequest: f, setSuccess: p, setFailure: h, finishRequest: g, cancel: _, reset: x } = y(), w = e((e) => {
358
- s.current !== null && (globalThis.clearTimeout(s.current), s.current = null), c.current?.(e), c.current = null;
359
- }, []);
360
- t(() => () => {
361
- w(null);
362
- }, [w]);
363
- let T = e(() => {
364
- w(null), x();
365
- }, [w, x]), E = e(() => {
366
- w(null), _();
367
- }, [w, _]), D = e(async (e, t, n) => {
368
- try {
369
- let r = { signal: t }, i = a.searchAddress(n, r), o = await Promise.race([i, C(t)]);
370
- return t.aborted || o === null ? null : (p(e, o), o);
371
- } catch (n) {
372
- return t.aborted ? null : h(e, v(n));
373
- } finally {
374
- g(e);
375
- }
376
- }, [
377
- a,
378
- g,
379
- h,
380
- p
381
- ]);
382
- return {
383
- loading: l,
384
- data: u,
385
- error: d,
386
- cancel: E,
387
- reset: T,
388
- search: e((e) => {
389
- let t = S(e), { requestId: n, signal: r } = f();
390
- if (w(null), t === null) {
391
- let e = h(n, m("invalid_query", "Address query is required"));
392
- return g(n), Promise.resolve(e);
393
- }
394
- return o <= 0 ? new Promise((e) => {
395
- c.current = e, D(n, r, t).then((t) => {
396
- e(t), c.current === e && (c.current = null);
397
- });
398
- }) : new Promise((e) => {
399
- c.current = e, s.current = globalThis.setTimeout(() => {
400
- s.current = null;
401
- let e = c.current;
402
- c.current = null, D(n, r, t).then((t) => {
403
- e?.(t);
404
- });
405
- }, o);
406
- });
407
- }, [
408
- f,
409
- w,
410
- o,
411
- D
412
- ])
413
- };
290
+ function useJapanAddressSearch(options) {
291
+ const dataSource = useMemo(
292
+ () => resolveAddressSearchDataSource(options.dataSource),
293
+ [options.dataSource]
294
+ );
295
+ const debounceMs = options.debounceMs ?? 0;
296
+ const timeoutRef = useRef(
297
+ null
298
+ );
299
+ const pendingResolveRef = useRef(null);
300
+ const {
301
+ loading,
302
+ data,
303
+ error,
304
+ beginRequest,
305
+ setSuccess,
306
+ setFailure,
307
+ finishRequest,
308
+ cancel: cancelRequestState,
309
+ reset: resetRequestState
310
+ } = useLatestRequestState();
311
+ const clearPendingDebounce = useCallback(
312
+ (result) => {
313
+ if (timeoutRef.current !== null) {
314
+ globalThis.clearTimeout(timeoutRef.current);
315
+ timeoutRef.current = null;
316
+ }
317
+ pendingResolveRef.current?.(result);
318
+ pendingResolveRef.current = null;
319
+ },
320
+ []
321
+ );
322
+ useEffect(() => {
323
+ return () => {
324
+ clearPendingDebounce(null);
325
+ };
326
+ }, [clearPendingDebounce]);
327
+ const reset = useCallback(() => {
328
+ clearPendingDebounce(null);
329
+ resetRequestState();
330
+ }, [clearPendingDebounce, resetRequestState]);
331
+ const cancel = useCallback(() => {
332
+ clearPendingDebounce(null);
333
+ cancelRequestState();
334
+ }, [clearPendingDebounce, cancelRequestState]);
335
+ const runSearch = useCallback(async (requestId, signal, request) => {
336
+ try {
337
+ const requestOptions = {
338
+ signal
339
+ };
340
+ const searchPromise = dataSource.searchAddress(
341
+ request,
342
+ requestOptions
343
+ );
344
+ const result = await Promise.race([
345
+ searchPromise,
346
+ waitForAbort(signal)
347
+ ]);
348
+ if (signal.aborted || result === null) {
349
+ return null;
350
+ }
351
+ setSuccess(requestId, result);
352
+ return result;
353
+ } catch (caughtError) {
354
+ if (signal.aborted) {
355
+ return null;
356
+ }
357
+ return setFailure(requestId, toJapanAddressError(caughtError));
358
+ } finally {
359
+ finishRequest(requestId);
360
+ }
361
+ }, [dataSource, finishRequest, setFailure, setSuccess]);
362
+ const search = useCallback((input) => {
363
+ const request = normalizeAddressSearchInput(input);
364
+ const { requestId, signal } = beginRequest();
365
+ clearPendingDebounce(null);
366
+ if (request === null) {
367
+ const result = setFailure(
368
+ requestId,
369
+ createJapanAddressError(
370
+ "invalid_query",
371
+ "Address query is required"
372
+ )
373
+ );
374
+ finishRequest(requestId);
375
+ return Promise.resolve(result);
376
+ }
377
+ if (debounceMs <= 0) {
378
+ return new Promise((resolve) => {
379
+ pendingResolveRef.current = resolve;
380
+ void runSearch(requestId, signal, request).then((result) => {
381
+ resolve(result);
382
+ if (pendingResolveRef.current === resolve) {
383
+ pendingResolveRef.current = null;
384
+ }
385
+ });
386
+ });
387
+ }
388
+ return new Promise((resolve) => {
389
+ pendingResolveRef.current = resolve;
390
+ timeoutRef.current = globalThis.setTimeout(() => {
391
+ timeoutRef.current = null;
392
+ const pendingResolve = pendingResolveRef.current;
393
+ pendingResolveRef.current = null;
394
+ void runSearch(requestId, signal, request).then((result) => {
395
+ pendingResolve?.(result);
396
+ });
397
+ }, debounceMs);
398
+ });
399
+ }, [beginRequest, clearPendingDebounce, debounceMs, runSearch]);
400
+ return {
401
+ loading,
402
+ data,
403
+ error,
404
+ cancel,
405
+ reset,
406
+ search
407
+ };
414
408
  }
415
- //#endregion
416
- //#region src/react/useJapanPostalCode.ts
417
- function T(e) {
418
- if (e) return e;
419
- throw Error("useJapanPostalCode requires options.dataSource");
409
+ function resolvePostalCodeDataSource(dataSource) {
410
+ if (dataSource) {
411
+ return dataSource;
412
+ }
413
+ throw new Error("useJapanPostalCode requires options.dataSource");
420
414
  }
421
- function E(t) {
422
- let r = n(() => T(t.dataSource), [t.dataSource]), { loading: i, data: a, error: o, beginRequest: s, setSuccess: c, setFailure: l, finishRequest: u, cancel: f, reset: p } = y();
423
- return {
424
- loading: i,
425
- data: a,
426
- error: o,
427
- cancel: f,
428
- reset: p,
429
- search: e(async (e) => {
430
- let { requestId: t, signal: n } = s();
431
- try {
432
- let i = typeof e == "string" ? { postalCode: e } : e, a = d(i.postalCode);
433
- if (!/^\d{3,7}$/.test(a)) throw m("invalid_postal_code", "Postal code must contain between 3 and 7 digits");
434
- let o = { signal: n }, s = {
435
- postalCode: a,
436
- pageNumber: i.pageNumber ?? 0,
437
- rowsPerPage: i.rowsPerPage ?? 100,
438
- ...i.includeParenthesesTown === void 0 ? {} : { includeParenthesesTown: i.includeParenthesesTown }
439
- }, l = await r.lookupPostalCode(s, o);
440
- return n.aborted ? null : (c(t, l), l);
441
- } catch (e) {
442
- return n.aborted ? null : l(t, v(e));
443
- } finally {
444
- u(t);
445
- }
446
- }, [
447
- s,
448
- r,
449
- u,
450
- l,
451
- c
452
- ])
453
- };
415
+ function useJapanPostalCode(options) {
416
+ const dataSource = useMemo(
417
+ () => resolvePostalCodeDataSource(options.dataSource),
418
+ [options.dataSource]
419
+ );
420
+ const {
421
+ loading,
422
+ data,
423
+ error,
424
+ beginRequest,
425
+ setSuccess,
426
+ setFailure,
427
+ finishRequest,
428
+ cancel,
429
+ reset
430
+ } = useLatestRequestState();
431
+ const search = useCallback(
432
+ async (input) => {
433
+ const { requestId, signal } = beginRequest();
434
+ try {
435
+ const requestInput = typeof input === "string" ? { postalCode: input } : input;
436
+ const postalCode = normalizeJapanPostalCode(requestInput.postalCode);
437
+ if (!/^\d{3,7}$/.test(postalCode)) {
438
+ throw createJapanAddressError(
439
+ "invalid_postal_code",
440
+ "Postal code must contain between 3 and 7 digits"
441
+ );
442
+ }
443
+ const requestOptions = {
444
+ signal
445
+ };
446
+ const request = {
447
+ postalCode,
448
+ pageNumber: requestInput.pageNumber ?? 0,
449
+ rowsPerPage: requestInput.rowsPerPage ?? 100,
450
+ ...requestInput.includeParenthesesTown === void 0 ? {} : {
451
+ includeParenthesesTown: requestInput.includeParenthesesTown
452
+ }
453
+ };
454
+ const result = await dataSource.lookupPostalCode(
455
+ request,
456
+ requestOptions
457
+ );
458
+ if (signal.aborted) {
459
+ return null;
460
+ }
461
+ setSuccess(requestId, result);
462
+ return result;
463
+ } catch (caughtError) {
464
+ if (signal.aborted) {
465
+ return null;
466
+ }
467
+ return setFailure(requestId, toJapanAddressError(caughtError));
468
+ } finally {
469
+ finishRequest(requestId);
470
+ }
471
+ },
472
+ [beginRequest, dataSource, finishRequest, setFailure, setSuccess]
473
+ );
474
+ return {
475
+ loading,
476
+ data,
477
+ error,
478
+ cancel,
479
+ reset,
480
+ search
481
+ };
454
482
  }
455
- //#endregion
456
- //#region src/react/useJapanAddress.ts
457
- function D(t) {
458
- let r = n(() => {
459
- if (t.dataSource) return t.dataSource;
460
- throw Error("useJapanAddress requires options.dataSource");
461
- }, [t.dataSource]), a = E({ dataSource: r }), o = w({
462
- dataSource: r,
463
- debounceMs: t.debounceMs
464
- }), s = a.reset, c = a.search, l = o.reset, u = o.search, [d, f] = i(null), p = e(async (e) => (l(), f("postalCode"), c(e)), [l, c]), m = e(async (e) => (s(), f("addressQuery"), u(e)), [s, u]), h = e(() => {
465
- s(), l(), f(null);
466
- }, [l, s]), g = d === "postalCode" ? a.data : d === "addressQuery" ? o.data : null, _ = d === "postalCode" ? a.error : d === "addressQuery" ? o.error : null;
467
- return {
468
- loading: a.loading || o.loading,
469
- data: g,
470
- error: _,
471
- reset: h,
472
- searchByPostalCode: p,
473
- searchByAddressQuery: m
474
- };
483
+
484
+ // src/react/useJapanAddress.ts
485
+ function useJapanAddress(options) {
486
+ const dataSource = useMemo(() => {
487
+ if (options.dataSource) {
488
+ return options.dataSource;
489
+ }
490
+ throw new Error("useJapanAddress requires options.dataSource");
491
+ }, [options.dataSource]);
492
+ const postalCode = useJapanPostalCode({ dataSource });
493
+ const addressSearch = useJapanAddressSearch({
494
+ dataSource,
495
+ debounceMs: options.debounceMs
496
+ });
497
+ const resetPostalCode = postalCode.reset;
498
+ const searchPostalCode = postalCode.search;
499
+ const resetAddressSearch = addressSearch.reset;
500
+ const searchAddressKeyword = addressSearch.search;
501
+ const [activeSearch, setActiveSearch] = useState(null);
502
+ const searchByPostalCode = useCallback(async (input) => {
503
+ resetAddressSearch();
504
+ setActiveSearch("postalCode");
505
+ return searchPostalCode(input);
506
+ }, [resetAddressSearch, searchPostalCode]);
507
+ const searchByAddressQuery = useCallback(async (input) => {
508
+ resetPostalCode();
509
+ setActiveSearch("addressQuery");
510
+ return searchAddressKeyword(input);
511
+ }, [resetPostalCode, searchAddressKeyword]);
512
+ const reset = useCallback(() => {
513
+ resetPostalCode();
514
+ resetAddressSearch();
515
+ setActiveSearch(null);
516
+ }, [resetAddressSearch, resetPostalCode]);
517
+ const data = activeSearch === "postalCode" ? postalCode.data : activeSearch === "addressQuery" ? addressSearch.data : null;
518
+ const error = activeSearch === "postalCode" ? postalCode.error : activeSearch === "addressQuery" ? addressSearch.error : null;
519
+ return {
520
+ // 사용자는 현재 활성 모드만 보더라도, 내부에서는 두 훅 중 하나라도 정리 중이면 로딩으로 본다.
521
+ loading: postalCode.loading || addressSearch.loading,
522
+ data,
523
+ error,
524
+ reset,
525
+ searchByPostalCode,
526
+ searchByAddressQuery
527
+ };
475
528
  }
476
- //#endregion
477
- export { u as AddressSearchInput, p as PostalCodeInput, m as createJapanAddressError, f as formatJapanPostalCode, _ as isValidJapanPostalCode, g as normalizeJapanPostAddressRecord, d as normalizeJapanPostalCode, D as useJapanAddress, w as useJapanAddressSearch, E as useJapanPostalCode };
529
+
530
+ export { AddressSearchInput, PostalCodeInput, createJapanAddressError, formatJapanPostalCode, isValidJapanPostalCode, normalizeJapanPostAddressRecord, normalizeJapanPostalCode, useJapanAddress, useJapanAddressSearch, useJapanPostalCode };