state-in-url 1.0.2 → 1.2.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 +20 -2
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/urlstate/index.d.ts +2 -1
- package/dist/urlstate/useInsertionEffect.d.ts +2 -0
- package/dist/urlstate/useSharedState/index.d.ts +1 -0
- package/dist/urlstate/useSharedState/useSharedState.d.ts +24 -0
- package/package.json +41 -12
- package/dist/urlstate/useCommonState.d.ts +0 -6
package/README.md
CHANGED
|
@@ -42,7 +42,8 @@ Add a ⭐️ to support the project!
|
|
|
42
42
|
|
|
43
43
|
## Why use state-in-url?
|
|
44
44
|
|
|
45
|
-
`state-in-url` Simple state management with URL
|
|
45
|
+
`state-in-url` Simple state management with URL sync. Share complex states between unrelated React components, sync state to URL, TS-friendly, NextJS compatible.
|
|
46
|
+
|
|
46
47
|
|
|
47
48
|
# Use cases
|
|
48
49
|
|
|
@@ -66,6 +67,7 @@ Add a ⭐️ to support the project!
|
|
|
66
67
|
|
|
67
68
|
- [Installation](#installation)
|
|
68
69
|
- [`useUrlState` for Next.js](#useurlstate-hook-for-nextjs)
|
|
70
|
+
- [`useSharedState` for React.js](#usesharedstate-hook-for-reactjs)
|
|
69
71
|
- [`useUrlEncode` for React.js](#useurlencode-hook-for-reactjs)
|
|
70
72
|
- [`encodeState` and `decodeState` for pure JS usage](#encodestate-and-decodestate-helpers)
|
|
71
73
|
- [auto sync state with url](#auto-sync-state)
|
|
@@ -92,7 +94,7 @@ pnpm add state-in-url
|
|
|
92
94
|
|
|
93
95
|
### 2. Edit tsconfig.json
|
|
94
96
|
|
|
95
|
-
set `"moduleResolution": "Node16"` or `"moduleResolution": "NodeNext"`
|
|
97
|
+
In `tsconfig.json` in `compilerOptions` set `"moduleResolution": "Node16"` or `"moduleResolution": "NodeNext"`
|
|
96
98
|
|
|
97
99
|
## useUrlState hook for Next.js
|
|
98
100
|
|
|
@@ -257,6 +259,22 @@ function SettingsComponent() {
|
|
|
257
259
|
}
|
|
258
260
|
```
|
|
259
261
|
|
|
262
|
+
## `useSharedState` hook for React.js
|
|
263
|
+
Hook to share state between any React components, tested with Next.js and Vite.
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
'use client'
|
|
267
|
+
import { useSharedState } from 'state-in-url';
|
|
268
|
+
|
|
269
|
+
export const someState = { name: '' };
|
|
270
|
+
|
|
271
|
+
function SettingsComponent() {
|
|
272
|
+
const { state, setState } = useSharedState(someState);
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
[Docs](packages/urlstate/useSharedState/README.md)
|
|
277
|
+
|
|
260
278
|
## `useUrlEncode` hook for React.js
|
|
261
279
|
|
|
262
280
|
[Docs](packages/urlstate/useUrlEncode/README.md)
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("next/navigation");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(e);const o={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"},s=e=>{const t=null===e,n=Array.isArray(e),r=e instanceof Date;return(t?"null":r&&"date")||n&&"array"||!t&&!r&&!n&&"object"==typeof e&&"object"||typeof e},c=()=>"undefined"==typeof window,u=e=>new URLSearchParams("string"==typeof e?e:e?.toString?.()||""),a=(e,t)=>JSON.stringify(e)===JSON.stringify(t);function
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("next/navigation");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(e);const o={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"},s=e=>{const t=null===e,n=Array.isArray(e),r=e instanceof Date;return(t?"null":r&&"date")||n&&"array"||!t&&!r&&!n&&"object"==typeof e&&"object"||typeof e},c=()=>"undefined"==typeof window,u=e=>new URLSearchParams("string"==typeof e?a(e):e?.toString?.()||""),a=e=>e.split("?")?.[1]||e||"",i=(e,t)=>JSON.stringify(e)===JSON.stringify(t);function l(e){switch(s(e)){case"function":case"symbol":return"";case"date":return o.date+e.toISOString();case"string":return`${o.string}${encodeURIComponent(e)}`;case"number":return o.number+String(e);case"boolean":return o.boolean+String(e);case"object":case"array":return JSON.stringify(e,d).replaceAll('"',"'");case"null":return o.null;case"undefined":return o.undefined;default:return String(e)}}function f(e,t){return function(e,t){try{return JSON.parse(e,y)}catch{const n=p(e);return n!==g?n:t}}(e.replaceAll("'",'"'),t)}const d=(e,t)=>{const n=s(t);return e&&"object"!==n&&"array"!==n?l(t):t},p=e=>e===o.null?null:e!==o.undefined?e?.startsWith?.(o.number)?Number.parseFloat(e.replace(o.number,"")):e?.startsWith?.(o.boolean)?!!e.includes("true"):e?.startsWith?.(o.date)?new Date(e.slice(1)):e?.startsWith?.(o.string)?decodeURIComponent(e).replace(/^◖/,""):g:void 0,g=Symbol("isError"),y=(e,t)=>{const n="string"==typeof t,r=n&&p(t);return r===g?t:e&&n?r:t};const b=(e,t)=>{const n="string"==typeof t,r=n&&f(t?.replaceAll?.("'",'"'));return e&&n?r:t};function S(e,t){try{return JSON.parse(e,b)}catch{const n=p(e);return n!==g?n:t}}function h(e,t,n){const r=u(n);return Object.entries(e||{}).forEach((([e,n])=>{const o=t?.[e];JSON.stringify(n)!==JSON.stringify(o)&&r.set(e,l(n))})),r.toString()}function w(e,t){return{...t||{},...Object.fromEntries([...u(e).entries()].map((([e,n])=>{const r=t?.[e];return[e,f(n,r)??r]})))}}const m=new WeakMap,O=new WeakMap,v={get:e=>O.get(e)||[],add(e,t){const n=this.get(e);return O.set(e,n.concat(t)),()=>this.remove(e,t)},remove(e,t){const n=this.get(e).filter((e=>e!==t));n.length?O.set(e,n):O.delete(e)}},E={get:function(e){return m.get(e)},set:function(e,t){m.set(e,t)}},j=r.default.useInsertionEffect||r.default.useEffect;function N(e){const t=r.default.useCallback((function(t,n){return"object"===s(t)?h(t,e,n):""}),[e]);return{parse:r.default.useCallback((function(t){return w(t,e)}),[e]),stringify:t}}exports.decode=f,exports.decodeState=w,exports.encode=l,exports.encodeState=h,exports.useUrlEncode=N,exports.useUrlState=function(e,n){const{parse:o,stringify:s}=N(e),{state:u,getState:a,setState:l}=function(e,t){const n=r.default.useRef(e),[o,s]=r.default.useState((()=>{if(c())return t?t?.():n.current;const e=t?.()||E.get(n.current)||n.current,r=E.get(n.current);return i(r,e)||E.set(n.current,e),e})),u=r.default.useCallback((e=>{const t=E.get(n.current);if("function"==typeof e){const r=e(t);if(i(t,r))return;E.set(n.current,r),v.get(n.current).forEach((e=>{e()}))}else{if(i(t,e))return;E.set(n.current,e),v.get(n.current).forEach((e=>{e()}))}}),[]);return j((()=>{const e=v.add(n.current,(()=>{s(E.get(n.current)||n.current)}));return()=>{e()}}),[]),{state:o,getState:r.default.useCallback((()=>E.get(n.current)||n.current),[]),setState:u}}(e,(()=>{return c()?(t=n,r=e,{...r,...S(JSON.stringify(t),r)}):o(window.location.search);var t,r})),f=t.useRouter();r.default.useInsertionEffect((()=>{const e=()=>{const e=o(window.location.search);l(e)},t="popstate";return window.addEventListener(t,e),()=>{window.removeEventListener(t,e)}}),[l]);const d=r.default.useCallback(((e,t)=>{const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`;let o,c;"function"==typeof e?(o=e(a()),c=s(o)):(o=e??a(),c=s(o)),l(o);const u=`${window.location.pathname}${c.length?"?":""}${c}`;if(r!==u){const{replace:e,...n}=t||{};f[e?"replace":"push"](u,{scroll:!1,...n})}}),[f,s,a]);return{updateState:l,updateUrl:d,state:u}};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useRouter as e}from"next/navigation";const n={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"},r=t=>{const e=null===t,n=Array.isArray(t),r=t instanceof Date;return(e?"null":r&&"date")||n&&"array"||!e&&!r&&!n&&"object"==typeof t&&"object"||typeof t},c=()=>"undefined"==typeof window,o=t=>new URLSearchParams("string"==typeof t?t:t?.toString?.()||""),s=(t,e)=>JSON.stringify(t)===JSON.stringify(e);function
|
|
1
|
+
import t from"react";import{useRouter as e}from"next/navigation";const n={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"},r=t=>{const e=null===t,n=Array.isArray(t),r=t instanceof Date;return(e?"null":r&&"date")||n&&"array"||!e&&!r&&!n&&"object"==typeof t&&"object"||typeof t},c=()=>"undefined"==typeof window,o=t=>new URLSearchParams("string"==typeof t?s(t):t?.toString?.()||""),s=t=>t.split("?")?.[1]||t||"",a=(t,e)=>JSON.stringify(t)===JSON.stringify(e);function u(t){switch(r(t)){case"function":case"symbol":return"";case"date":return n.date+t.toISOString();case"string":return`${n.string}${encodeURIComponent(t)}`;case"number":return n.number+String(t);case"boolean":return n.boolean+String(t);case"object":case"array":return JSON.stringify(t,l).replaceAll('"',"'");case"null":return n.null;case"undefined":return n.undefined;default:return String(t)}}function i(t,e){return function(t,e){try{return JSON.parse(t,g)}catch{const n=f(t);return n!==d?n:e}}(t.replaceAll("'",'"'),e)}const l=(t,e)=>{const n=r(e);return t&&"object"!==n&&"array"!==n?u(e):e},f=t=>t===n.null?null:t!==n.undefined?t?.startsWith?.(n.number)?Number.parseFloat(t.replace(n.number,"")):t?.startsWith?.(n.boolean)?!!t.includes("true"):t?.startsWith?.(n.date)?new Date(t.slice(1)):t?.startsWith?.(n.string)?decodeURIComponent(t).replace(/^◖/,""):d:void 0,d=Symbol("isError"),g=(t,e)=>{const n="string"==typeof e,r=n&&f(e);return r===d?e:t&&n?r:e};const p=(t,e)=>{const n="string"==typeof e,r=n&&i(e?.replaceAll?.("'",'"'));return t&&n?r:e};function y(t,e){try{return JSON.parse(t,p)}catch{const n=f(t);return n!==d?n:e}}function b(t,e,n){const r=o(n);return Object.entries(t||{}).forEach((([t,n])=>{const c=e?.[t];JSON.stringify(n)!==JSON.stringify(c)&&r.set(t,u(n))})),r.toString()}function h(t,e){return{...e||{},...Object.fromEntries([...o(t).entries()].map((([t,n])=>{const r=e?.[t];return[t,i(n,r)??r]})))}}const S=new WeakMap,m=new WeakMap,w={get:t=>m.get(t)||[],add(t,e){const n=this.get(t);return m.set(t,n.concat(e)),()=>this.remove(t,e)},remove(t,e){const n=this.get(t).filter((t=>t!==e));n.length?m.set(t,n):m.delete(t)}},O={get:function(t){return S.get(t)},set:function(t,e){S.set(t,e)}},E=t.useInsertionEffect||t.useEffect;function N(e){const n=t.useCallback((function(t,n){return"object"===r(t)?b(t,e,n):""}),[e]);return{parse:t.useCallback((function(t){return h(t,e)}),[e]),stringify:n}}function v(n,r){const{parse:o,stringify:s}=N(n),{state:u,getState:i,setState:l}=function(e,n){const r=t.useRef(e),[o,s]=t.useState((()=>{if(c())return n?n?.():r.current;const t=n?.()||O.get(r.current)||r.current,e=O.get(r.current);return a(e,t)||O.set(r.current,t),t})),u=t.useCallback((t=>{const e=O.get(r.current);if("function"==typeof t){const n=t(e);if(a(e,n))return;O.set(r.current,n),w.get(r.current).forEach((t=>{t()}))}else{if(a(e,t))return;O.set(r.current,t),w.get(r.current).forEach((t=>{t()}))}}),[]);return E((()=>{const t=w.add(r.current,(()=>{s(O.get(r.current)||r.current)}));return()=>{t()}}),[]),{state:o,getState:t.useCallback((()=>O.get(r.current)||r.current),[]),setState:u}}(n,(()=>{return c()?(t=r,e=n,{...e,...y(JSON.stringify(t),e)}):o(window.location.search);var t,e})),f=e();t.useInsertionEffect((()=>{const t=()=>{const t=o(window.location.search);l(t)},e="popstate";return window.addEventListener(e,t),()=>{window.removeEventListener(e,t)}}),[l]);const d=t.useCallback(((t,e)=>{const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`;let c,o;"function"==typeof t?(c=t(i()),o=s(c)):(c=t??i(),o=s(c)),l(c);const a=`${window.location.pathname}${o.length?"?":""}${o}`;if(r!==a){const{replace:t,...n}=e||{};f[t?"replace":"push"](a,{scroll:!1,...n})}}),[f,s,i]);return{updateState:l,updateUrl:d,state:u}}export{i as decode,h as decodeState,u as encode,b as encodeState,N as useUrlEncode,v as useUrlState};
|
package/dist/urlstate/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { decode, encode, parseSsrQs } from './encoder';
|
|
2
2
|
import { decodeState, encodeState } from './encodeState';
|
|
3
|
+
import { useSharedState } from './useSharedState';
|
|
3
4
|
import { useUrlEncode } from './useUrlEncode';
|
|
4
5
|
import { useUrlState } from './useUrlState';
|
|
5
6
|
import { isSSR, type JSONCompatible, type Type, typeOf } from './utils';
|
|
6
|
-
export { decode, decodeState, encode, encodeState, isSSR, parseSsrQs, typeOf, useUrlEncode, useUrlState, };
|
|
7
|
+
export { decode, decodeState, encode, encodeState, isSSR, parseSsrQs, typeOf, useSharedState, useUrlEncode, useUrlState, };
|
|
7
8
|
export type { JSONCompatible, Type };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSharedState } from './useSharedState';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type DeepReadonly, type JSONCompatible } from '../utils';
|
|
2
|
+
/**
|
|
3
|
+
* Custom React hook for sharing state between unrelated components.
|
|
4
|
+
*
|
|
5
|
+
* @param {T} defaultState - The default state object
|
|
6
|
+
* @param {() => T} [_getInitial] - Optional function to get initial state
|
|
7
|
+
* @returns {Object} Object containing `state`, `getState`, and `setState` functions
|
|
8
|
+
*
|
|
9
|
+
* * Example:
|
|
10
|
+
* ```ts
|
|
11
|
+
* export const form = { name: '' };
|
|
12
|
+
* const { state, setState } = useSharedState(form);
|
|
13
|
+
*
|
|
14
|
+
* setState({ name: 'test' });
|
|
15
|
+
* // OR
|
|
16
|
+
* setState(curr => ({ ...curr, name: 'test' }))
|
|
17
|
+
* ```
|
|
18
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url/tree/main/packages/urlstate/useSharedState}
|
|
19
|
+
*/
|
|
20
|
+
export declare function useSharedState<T extends JSONCompatible>(defaultState: T, _getInitial?: () => T): {
|
|
21
|
+
state: T;
|
|
22
|
+
getState: () => T;
|
|
23
|
+
setState: (value: T | DeepReadonly<T> | ((currState: T) => T)) => void;
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-in-url",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Library to store state in browser URL, includes hook for NextJS, hook for pure React, and low level helpers.",
|
|
5
5
|
"homepage": "https://github.com/asmyshlyaev177/state-in-url#readme",
|
|
6
6
|
"keywords": [
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"workspaces": [
|
|
38
38
|
"packages/urlstate",
|
|
39
|
-
"packages/example-nextjs"
|
|
39
|
+
"packages/example-nextjs",
|
|
40
|
+
"packages/example-react"
|
|
40
41
|
],
|
|
41
42
|
"files": [
|
|
42
43
|
"dist"
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"types": "./dist/index.d.ts",
|
|
68
69
|
"scripts": {
|
|
69
70
|
"test:unit": "wireit",
|
|
70
|
-
"test:int": "
|
|
71
|
+
"test:int": "wireit",
|
|
71
72
|
"test:int:watch": "npx chokidar-cli 'packages/**/*.ts' 'packages/**/*.tsx' -i '.next' -t 500 -c 'npx playwright test -j 2 --project=chromium'",
|
|
72
73
|
"test": "wireit",
|
|
73
74
|
"tsc": "wireit",
|
|
@@ -75,10 +76,10 @@
|
|
|
75
76
|
"dev:lib": "wireit",
|
|
76
77
|
"dev:nextjs": "wireit",
|
|
77
78
|
"bump": "npx standard-version --no-verify",
|
|
78
|
-
"bump:ex": "npm i state-in-url@latest --workspace=packages/example-nextjs",
|
|
79
79
|
"build": "wireit",
|
|
80
|
-
"build:demo": "
|
|
80
|
+
"build:demo": "wireit",
|
|
81
81
|
"start:demo": "npm run build && cd packages/example-nextjs && npm run build && npm run start",
|
|
82
|
+
"kill-next": "wireit",
|
|
82
83
|
"cleanup": "rm -rf dist",
|
|
83
84
|
"setup": "playwright install --with-deps",
|
|
84
85
|
"cleanupDist": "wireit",
|
|
@@ -89,11 +90,19 @@
|
|
|
89
90
|
"test": {
|
|
90
91
|
"dependencies": [
|
|
91
92
|
"tsc",
|
|
92
|
-
"build",
|
|
93
93
|
"test:unit",
|
|
94
|
-
"
|
|
94
|
+
"kill-next"
|
|
95
95
|
],
|
|
96
|
-
"command": "
|
|
96
|
+
"command": "npm run test:int -- --retries=1"
|
|
97
|
+
},
|
|
98
|
+
"kill-next": {
|
|
99
|
+
"command": "ps aux | grep .next | grep -v grep | awk '{print $2}' | xargs kill -9 2>&1; exit 0"
|
|
100
|
+
},
|
|
101
|
+
"test:int": {
|
|
102
|
+
"command": "playwright test",
|
|
103
|
+
"dependencies": [
|
|
104
|
+
"example:react"
|
|
105
|
+
]
|
|
97
106
|
},
|
|
98
107
|
"tsc": {
|
|
99
108
|
"command": "npx tsc --noEmit"
|
|
@@ -124,12 +133,35 @@
|
|
|
124
133
|
},
|
|
125
134
|
"dev:nextjs": {
|
|
126
135
|
"command": "cd packages/example-nextjs && npm run dev",
|
|
136
|
+
"dependencies": [
|
|
137
|
+
"dev:react"
|
|
138
|
+
],
|
|
127
139
|
"service": {
|
|
128
140
|
"readyWhen": {
|
|
129
141
|
"lineMatches": "Ready in"
|
|
130
142
|
}
|
|
131
143
|
}
|
|
132
144
|
},
|
|
145
|
+
"build:demo": {
|
|
146
|
+
"dependencies": [
|
|
147
|
+
"example:react"
|
|
148
|
+
],
|
|
149
|
+
"command": "cd packages/example-nextjs && npm run build"
|
|
150
|
+
},
|
|
151
|
+
"dev:react": {
|
|
152
|
+
"command": "cd packages/example-react && npm run dev",
|
|
153
|
+
"service": {
|
|
154
|
+
"readyWhen": {
|
|
155
|
+
"lineMatches": "✓ built in"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"example:react": {
|
|
160
|
+
"command": "cd packages/example-react && npm run build",
|
|
161
|
+
"dependencies": [
|
|
162
|
+
"build"
|
|
163
|
+
]
|
|
164
|
+
},
|
|
133
165
|
"build": {
|
|
134
166
|
"command": "rollup -c rollup.config.js",
|
|
135
167
|
"dependencies": [
|
|
@@ -168,8 +200,8 @@
|
|
|
168
200
|
"@commitlint/cli": "^19.0.3",
|
|
169
201
|
"@commitlint/config-conventional": "^19.0.3",
|
|
170
202
|
"@playwright/test": "^1.45.1",
|
|
171
|
-
"@rollup/plugin-commonjs": "^25.0.7",
|
|
172
203
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
204
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
173
205
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
174
206
|
"@testing-library/dom": "^10.2.0",
|
|
175
207
|
"@testing-library/jest-dom": "^6.4.2",
|
|
@@ -193,11 +225,8 @@
|
|
|
193
225
|
"playwright": "^1.45.1",
|
|
194
226
|
"prettier": "^3.2.5",
|
|
195
227
|
"rollup": "^2.79.1",
|
|
196
|
-
"rollup-plugin-copy": "^3.5.0",
|
|
197
228
|
"rollup-plugin-filesize": "^10.0.0",
|
|
198
|
-
"rollup-plugin-ignore": "^1.0.10",
|
|
199
229
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
200
|
-
"rollup-plugin-terser": "^7.0.2",
|
|
201
230
|
"standard-version": "^9.5.0",
|
|
202
231
|
"ts-jest": "^29.1.5",
|
|
203
232
|
"ts-node": "^10.9.2",
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type DeepReadonly, type JSONCompatible } from './utils';
|
|
2
|
-
export declare function useCommonState<T extends JSONCompatible>(defaultState: T, _getInitial?: () => T): {
|
|
3
|
-
state: T;
|
|
4
|
-
getState: () => T;
|
|
5
|
-
setState: (value: T | DeepReadonly<T> | ((currState: T) => T)) => void;
|
|
6
|
-
};
|