@eusilvio/cep-lookup-react 0.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -58
- package/dist/CepProvider.d.ts +1 -1
- package/dist/CepProvider.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/useBulkCepLookup.d.ts +3 -3
- package/dist/useBulkCepLookup.d.ts.map +1 -1
- package/dist/useCepLookup.d.ts +1 -1
- package/dist/useCepLookup.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,96 +1,106 @@
|
|
|
1
1
|
# @eusilvio/cep-lookup-react
|
|
2
2
|
|
|
3
|
-
React
|
|
4
|
-
|
|
5
|
-
Provides a flexible and easy-to-use React hook (`useCepLookup`) to look up Brazilian postal codes (CEPs), with built-in debounce, caching, and full configuration via a React Context Provider.
|
|
3
|
+
React hooks/provider for [`@eusilvio/cep-lookup`](https://www.npmjs.com/package/@eusilvio/cep-lookup).
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
npm install @eusilvio/cep-lookup @eusilvio/cep-lookup-react react
|
|
11
|
-
# or
|
|
12
|
-
yarn add @eusilvio/cep-lookup @eusilvio/cep-lookup-react react
|
|
8
|
+
npm install @eusilvio/cep-lookup @eusilvio/cep-lookup-react react react-dom
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
##
|
|
11
|
+
## Compatibility
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
- React: `>= 16.8`
|
|
14
|
+
- Node.js (tooling/tests): `20.x`, `22.x`, `24.x`
|
|
15
|
+
- Core peer: `@eusilvio/cep-lookup ^2.6.0`
|
|
16
|
+
|
|
17
|
+
## Basic Usage
|
|
18
18
|
|
|
19
|
-
```
|
|
20
|
-
import React from
|
|
21
|
-
import { CepProvider, useCepLookup } from
|
|
19
|
+
```tsx
|
|
20
|
+
import React from "react";
|
|
21
|
+
import { CepProvider, useCepLookup } from "@eusilvio/cep-lookup-react";
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
const [cep, setCep] = React.useState(
|
|
25
|
-
const { address, loading, error } = useCepLookup(cep);
|
|
23
|
+
function CepField() {
|
|
24
|
+
const [cep, setCep] = React.useState("01001000");
|
|
25
|
+
const { address, loading, error, warmup } = useCepLookup(cep);
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<div>
|
|
29
|
-
<input
|
|
29
|
+
<input
|
|
30
|
+
value={cep}
|
|
31
|
+
onFocus={() => warmup()}
|
|
32
|
+
onChange={(e) => setCep(e.target.value)}
|
|
33
|
+
/>
|
|
30
34
|
{loading && <p>Loading...</p>}
|
|
31
|
-
{error && <p>
|
|
32
|
-
{address && (
|
|
33
|
-
<pre>{JSON.stringify(address, null, 2)}</pre>
|
|
34
|
-
)}
|
|
35
|
+
{error && <p>{error.message}</p>}
|
|
36
|
+
{address && <pre>{JSON.stringify(address, null, 2)}</pre>}
|
|
35
37
|
</div>
|
|
36
38
|
);
|
|
37
|
-
}
|
|
39
|
+
}
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
export default function App() {
|
|
42
|
+
return (
|
|
43
|
+
<CepProvider>
|
|
44
|
+
<CepField />
|
|
45
|
+
</CepProvider>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
46
48
|
```
|
|
47
49
|
|
|
48
|
-
##
|
|
50
|
+
## Resilience Example (Provider Options)
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
```tsx
|
|
53
|
+
import { CepProvider } from "@eusilvio/cep-lookup-react";
|
|
54
|
+
import { viaCepProvider, brasilApiProvider } from "@eusilvio/cep-lookup/providers";
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
<CepProvider
|
|
57
|
+
providers={[viaCepProvider, brasilApiProvider]}
|
|
58
|
+
circuitBreaker={{ enabled: true, failureThreshold: 3, cooldownMs: 30000 }}
|
|
59
|
+
retries={1}
|
|
60
|
+
rateLimit={{ requests: 60, per: 60_000 }}
|
|
61
|
+
>
|
|
62
|
+
{/* app */}
|
|
63
|
+
</CepProvider>
|
|
64
|
+
```
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
import { CepProvider } from '@eusilvio/cep-lookup-react';
|
|
56
|
-
import { viaCepProvider } from '@eusilvio/cep-lookup/providers';
|
|
66
|
+
## Events Example
|
|
57
67
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
68
|
+
```tsx
|
|
69
|
+
<CepProvider
|
|
70
|
+
onSuccess={({ provider, duration }) => console.log("success", provider, duration)}
|
|
71
|
+
onFailure={({ provider, error }) => console.log("failure", provider, error.message)}
|
|
72
|
+
onCacheHit={({ cep }) => console.log("cache hit", cep)}
|
|
73
|
+
>
|
|
74
|
+
{/* app */}
|
|
75
|
+
</CepProvider>
|
|
63
76
|
```
|
|
64
77
|
|
|
65
78
|
## API
|
|
66
79
|
|
|
67
|
-
###
|
|
68
|
-
|
|
69
|
-
A React component that provides the `CepLookup` instance to its children.
|
|
80
|
+
### `useCepLookup<T = Address>(cep: string, delay?: number)`
|
|
70
81
|
|
|
71
|
-
|
|
82
|
+
Returns `{ address, error, loading, warmup }`.
|
|
72
83
|
|
|
73
|
-
|
|
84
|
+
### `useBulkCepLookup<T = Address>(ceps: string[], options?)`
|
|
74
85
|
|
|
75
|
-
|
|
76
|
-
- `cache` (optional): `Cache` - A cache instance. Defaults to a persistent `InMemoryCache`.
|
|
77
|
-
- `rateLimit` (optional): `RateLimitOptions` - Options for rate limiting.
|
|
78
|
-
- `mapper` (optional): `(address: Address) => T` - A function to transform the address object globally.
|
|
79
|
-
- `onSuccess` (optional): `(event) => void` - Callback triggered on successful lookups.
|
|
80
|
-
- `onFailure` (optional): `(event) => void` - Callback triggered on lookup failures.
|
|
81
|
-
- `onCacheHit` (optional): `(event) => void` - Callback triggered on cache hits.
|
|
86
|
+
Returns `{ results, error, loading, refresh }`.
|
|
82
87
|
|
|
83
|
-
###
|
|
88
|
+
### `<CepProvider />`
|
|
84
89
|
|
|
85
|
-
|
|
90
|
+
Accepts `CepLookupOptions` as props (`providers`, `cache`, `rateLimit`, `retries`, `retryDelay`, `circuitBreaker`, `staggerDelay`, `fetcher`) plus:
|
|
86
91
|
|
|
87
|
-
|
|
92
|
+
- `mapper`
|
|
93
|
+
- `onSuccess`
|
|
94
|
+
- `onFailure`
|
|
95
|
+
- `onCacheHit`
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
- `delay` (optional): `number` - The debounce delay in milliseconds. Defaults to `500`.
|
|
97
|
+
## Community
|
|
91
98
|
|
|
92
|
-
|
|
99
|
+
- [CONTRIBUTING.md](../../CONTRIBUTING.md)
|
|
100
|
+
- [CODE_OF_CONDUCT.md](../../CODE_OF_CONDUCT.md)
|
|
101
|
+
- [SECURITY.md](../../SECURITY.md)
|
|
93
102
|
|
|
94
|
-
|
|
103
|
+
## Production docs
|
|
95
104
|
|
|
96
|
-
-
|
|
105
|
+
- [Best Practices](../../docs/BEST_PRACTICES.md)
|
|
106
|
+
- [Cookbook](../../docs/COOKBOOK.md)
|
package/dist/CepProvider.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ interface CepProviderProps<T = Address> extends Partial<CepLookupOptions> {
|
|
|
12
12
|
onFailure?: (event: EventMap['failure']) => void;
|
|
13
13
|
onCacheHit?: (event: EventMap['cache:hit']) => void;
|
|
14
14
|
}
|
|
15
|
-
export declare const CepProvider: <T>({ children, mapper, onSuccess, onFailure, onCacheHit,
|
|
15
|
+
export declare const CepProvider: <T>({ children, mapper, onSuccess, onFailure, onCacheHit, providers, cache, rateLimit, staggerDelay, fetcher, }: CepProviderProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
16
16
|
export declare const useCepLookupInstance: () => CepContextValue<any>;
|
|
17
17
|
export {};
|
|
18
18
|
//# sourceMappingURL=CepProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CepProvider.d.ts","sourceRoot":"","sources":["../src/CepProvider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CepProvider.d.ts","sourceRoot":"","sources":["../src/CepProvider.tsx"],"names":[],"mappings":"AAMA,OAAc,EAEZ,SAAS,EAKV,MAAM,OAAO,CAAC;AACf,OAAO,EACL,OAAO,EACP,SAAS,EACT,gBAAgB,EAEhB,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,CAAC;IACjC,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAQD,UAAU,gBAAgB,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,OAAO,CAAC,gBAAgB,CAAC;IACvE,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,CAAC;IAEjC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;IACjD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,WAAW,GAAI,CAAC,EAAG,6GAW7B,gBAAgB,CAAC,CAAC,CAAC,4CAmDrB,CAAC;AAEF,eAAO,MAAM,oBAAoB,4BAOhC,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var A=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var N=(e,r)=>{for(var c in r)A(e,c,{get:r[c],enumerable:!0})},O=(e,r,c,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of b(r))!g.call(e,s)&&s!==c&&A(e,s,{get:()=>r[s],enumerable:!(t=M(r,s))||t.enumerable});return e};var V=e=>O(A({},"__esModule",{value:!0}),e);var q={};N(q,{CepProvider:()=>K,useBulkCepLookup:()=>j,useCepLookup:()=>S,useCepLookupInstance:()=>x});module.exports=V(q);var k=require("react");var R=require("@eusilvio/cep-lookup/providers"),C=require("react"),w=require("@eusilvio/cep-lookup"),B=require("react/jsx-runtime"),P=[R.viaCepProvider,R.brasilApiProvider,R.apicepProvider,R.openCepProvider],L=new w.InMemoryCache,h=new w.CepLookup({providers:P,cache:L}),y=(0,C.createContext)({instance:h,options:{providers:P,cache:L}}),K=({children:e,mapper:r,onSuccess:c,onFailure:t,onCacheHit:s,providers:p,cache:m,rateLimit:u,staggerDelay:a,fetcher:n})=>{let d=(0,C.useRef)(null);d.current||(d.current=new w.InMemoryCache);let o=(0,C.useMemo)(()=>{if(!p&&!m&&!u&&a===void 0&&!n)return h;let l=m??d.current;return new w.CepLookup({providers:p||P,cache:l,...u&&{rateLimit:u},...a!==void 0&&{staggerDelay:a},...n&&{fetcher:n}})},[p,m,u,a,n]);(0,C.useEffect)(()=>(c&&o.on("success",c),t&&o.on("failure",t),s&&o.on("cache:hit",s),()=>{c&&o.off("success",c),t&&o.off("failure",t),s&&o.off("cache:hit",s)}),[o,c,t,s]);let T=(0,C.useMemo)(()=>({instance:o,mapper:r,options:{providers:p||P,cache:m??d.current,...u&&{rateLimit:u},...a!==void 0&&{staggerDelay:a},...n&&{fetcher:n}}}),[o,r,p,m,u,a,n]);return(0,B.jsx)(y.Provider,{value:T,children:e})},x=()=>{let e=(0,C.useContext)(y);if(!e)throw new Error("useCepLookupInstance must be used within a CepProvider");return e};var S=(e,r=500)=>{let[c,t]=(0,k.useState)(null),[s,p]=(0,k.useState)(null),[m,u]=(0,k.useState)(!1),{instance:a,mapper:n}=x(),d=(0,k.useRef)(null),o=(0,k.useRef)("");return(0,k.useEffect)(()=>{let l=e.replace(/\D/g,"");return o.current=l,d.current&&clearTimeout(d.current),l.length===8?(u(!0),p(null),d.current=setTimeout(async()=>{try{let i=await a.lookup(l);if(l!==o.current)return;t(n?n(i):i),p(null)}catch(i){if(l!==o.current)return;p(i instanceof Error?i:new Error(String(i))),t(null)}finally{l===o.current&&u(!1)}},r)):(t(null),p(null),u(!1)),()=>{d.current&&clearTimeout(d.current)}},[e,r,a,n]),{address:c,error:s,loading:m,warmup:()=>a.warmup()}};var f=require("react");var j=(e,r)=>{let[c,t]=(0,f.useState)([]),[s,p]=(0,f.useState)(!1),[m,u]=(0,f.useState)(null),{instance:a,mapper:n}=x(),d=(0,f.useRef)([]),o=(0,f.useRef)([]),T=(0,f.useCallback)(async()=>{if(!e||e.length===0){t([]),p(!1),u(null);return}let l=e.map(v=>v.replace(/\D/g,""));if(l.join(",")!==d.current.join(",")){d.current=l,p(!0),u(null);try{let v=await a.lookupCeps(l,r?.concurrency);o.current=v;let I=v.map(E=>({...E,data:E.data&&n?n(E.data):E.data}));t(I)}catch(v){u(v instanceof Error?v:new Error(String(v))),t([])}finally{p(!1)}}},[e,r?.concurrency,a,n]);return(0,f.useEffect)(()=>{T()},[T]),(0,f.useEffect)(()=>{if(o.current.length===0)return;let l=o.current.map(i=>({...i,data:i.data&&n?n(i.data):i.data}));t(l)},[n]),{results:c,loading:s,error:m,refresh:T}};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect as
|
|
1
|
+
import{useEffect as J,useState as T,useRef as y}from"react";import{apicepProvider as b,brasilApiProvider as g,viaCepProvider as N,openCepProvider as O}from"@eusilvio/cep-lookup/providers";import{createContext as V,useContext as K,useEffect as S,useMemo as x,useRef as j}from"react";import{CepLookup as E,InMemoryCache as P}from"@eusilvio/cep-lookup";import{jsx as q}from"react/jsx-runtime";var v=[N,g,b,O],A=new P,L=new E({providers:v,cache:A}),h=V({instance:L,options:{providers:v,cache:A}}),$=({children:p,mapper:f,onSuccess:l,onFailure:o,onCacheHit:d,providers:t,cache:i,rateLimit:n,staggerDelay:s,fetcher:e})=>{let c=j(null);c.current||(c.current=new P);let r=x(()=>{if(!t&&!i&&!n&&s===void 0&&!e)return L;let u=i??c.current;return new E({providers:t||v,cache:u,...n&&{rateLimit:n},...s!==void 0&&{staggerDelay:s},...e&&{fetcher:e}})},[t,i,n,s,e]);S(()=>(l&&r.on("success",l),o&&r.on("failure",o),d&&r.on("cache:hit",d),()=>{l&&r.off("success",l),o&&r.off("failure",o),d&&r.off("cache:hit",d)}),[r,l,o,d]);let m=x(()=>({instance:r,mapper:f,options:{providers:t||v,cache:i??c.current,...n&&{rateLimit:n},...s!==void 0&&{staggerDelay:s},...e&&{fetcher:e}}}),[r,f,t,i,n,s,e]);return q(h.Provider,{value:m,children:p})},R=()=>{let p=K(h);if(!p)throw new Error("useCepLookupInstance must be used within a CepProvider");return p};var re=(p,f=500)=>{let[l,o]=T(null),[d,t]=T(null),[i,n]=T(!1),{instance:s,mapper:e}=R(),c=y(null),r=y("");return J(()=>{let u=p.replace(/\D/g,"");return r.current=u,c.current&&clearTimeout(c.current),u.length===8?(n(!0),t(null),c.current=setTimeout(async()=>{try{let a=await s.lookup(u);if(u!==r.current)return;o(e?e(a):a),t(null)}catch(a){if(u!==r.current)return;t(a instanceof Error?a:new Error(String(a))),o(null)}finally{u===r.current&&n(!1)}},f)):(o(null),t(null),n(!1)),()=>{c.current&&clearTimeout(c.current)}},[p,f,s,e]),{address:l,error:d,loading:i,warmup:()=>s.warmup()}};import{useState as w,useEffect as B,useCallback as z,useRef as I}from"react";var se=(p,f)=>{let[l,o]=w([]),[d,t]=w(!1),[i,n]=w(null),{instance:s,mapper:e}=R(),c=I([]),r=I([]),m=z(async()=>{if(!p||p.length===0){o([]),t(!1),n(null);return}let u=p.map(C=>C.replace(/\D/g,""));if(u.join(",")!==c.current.join(",")){c.current=u,t(!0),n(null);try{let C=await s.lookupCeps(u,f?.concurrency);r.current=C;let M=C.map(k=>({...k,data:k.data&&e?e(k.data):k.data}));o(M)}catch(C){n(C instanceof Error?C:new Error(String(C))),o([])}finally{t(!1)}}},[p,f?.concurrency,s,e]);return B(()=>{m()},[m]),B(()=>{if(r.current.length===0)return;let u=r.current.map(a=>({...a,data:a.data&&e?e(a.data):a.data}));o(u)},[e]),{results:l,loading:d,error:i,refresh:m}};export{$ as CepProvider,se as useBulkCepLookup,re as useCepLookup,R as useCepLookupInstance};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BulkCepResult } from '@eusilvio/cep-lookup';
|
|
2
|
-
export declare const useBulkCepLookup: <T =
|
|
1
|
+
import { Address, BulkCepResult } from '@eusilvio/cep-lookup';
|
|
2
|
+
export declare const useBulkCepLookup: <T = Address>(ceps: string[], options?: {
|
|
3
3
|
concurrency?: number;
|
|
4
4
|
}) => {
|
|
5
|
-
results: BulkCepResult[];
|
|
5
|
+
results: BulkCepResult<T>[];
|
|
6
6
|
loading: boolean;
|
|
7
7
|
error: Error | null;
|
|
8
8
|
refresh: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBulkCepLookup.d.ts","sourceRoot":"","sources":["../src/useBulkCepLookup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"useBulkCepLookup.d.ts","sourceRoot":"","sources":["../src/useBulkCepLookup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG9D,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,OAAO,EAC1C,MAAM,MAAM,EAAE,EACd,UAAU;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;CA2DnC,CAAC"}
|
package/dist/useCepLookup.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export declare const useCepLookup: <T = Address>(cep: string, delay?: number) =>
|
|
|
3
3
|
address: T | null;
|
|
4
4
|
error: Error | null;
|
|
5
5
|
loading: boolean;
|
|
6
|
-
warmup: () => Promise<
|
|
6
|
+
warmup: () => Promise<import("@eusilvio/cep-lookup").Provider[]>;
|
|
7
7
|
};
|
|
8
8
|
//# sourceMappingURL=useCepLookup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCepLookup.d.ts","sourceRoot":"","sources":["../src/useCepLookup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,eAAO,MAAM,YAAY,GAAI,CAAC,GAAG,OAAO,EAAE,KAAK,MAAM,EAAE,cAAW;;;;;
|
|
1
|
+
{"version":3,"file":"useCepLookup.d.ts","sourceRoot":"","sources":["../src/useCepLookup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,eAAO,MAAM,YAAY,GAAI,CAAC,GAAG,OAAO,EAAE,KAAK,MAAM,EAAE,cAAW;;;;;CAsDjE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eusilvio/cep-lookup-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "React hooks and provider for @eusilvio/cep-lookup",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@eusilvio/cep-lookup": "^2.
|
|
15
|
+
"@eusilvio/cep-lookup": "^2.6.0",
|
|
16
16
|
"react": ">=16.8.0",
|
|
17
17
|
"react-dom": ">=16.8.0"
|
|
18
18
|
},
|