@phila/phila-ui-collapse-panel 0.0.1-beta.1
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 +75 -0
- package/dist/CollapsePanel.vue.d.ts +43 -0
- package/dist/CollapsePanel.vue.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +134 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CollapsePanel Component
|
|
2
|
+
|
|
3
|
+
A simple, customizable Vue 3. CollapsePanel component built with TypeScript and Vite.
|
|
4
|
+
Customizable component for toggling visibility of content.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- 🎯 TypeScript support with full type definitions
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @phila/phila-ui-collapse-panel
|
|
14
|
+
# or
|
|
15
|
+
yarn add @phila/phila-ui-collapse-panel
|
|
16
|
+
# or
|
|
17
|
+
pnpm add @phila/phila-ui-collapse-panel
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```vue
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { CollapsePanel } from "@phila/phila-ui-collapse-panel";
|
|
25
|
+
</script>
|
|
26
|
+
<template>...Add basic component template here...</template>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Props
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
| ---- | ---- | ------- | ----------- |
|
|
33
|
+
|
|
34
|
+
| ...Add props here...
|
|
35
|
+
|
|
36
|
+
## Events
|
|
37
|
+
|
|
38
|
+
| Event | Payload | Description |
|
|
39
|
+
| ----- | ------- | ----------- |
|
|
40
|
+
|
|
41
|
+
| ...Add events here...
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
|
|
45
|
+
...Add examples here...
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
### Install Dependencies
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm install
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Run Demo
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pnpm dev
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Build Library
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pnpm build
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Type Check
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm type-check
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CollapsePanelProps } from './index';
|
|
2
|
+
declare function __VLS_template(): {
|
|
3
|
+
attrs: Partial<{}>;
|
|
4
|
+
slots: {
|
|
5
|
+
toggle?(_: {
|
|
6
|
+
open: boolean;
|
|
7
|
+
ariaLabel: string;
|
|
8
|
+
ariaExpanded: boolean;
|
|
9
|
+
ariaControls: string;
|
|
10
|
+
onClickToggle: (event: Event) => void;
|
|
11
|
+
onClickOpen: (event?: Event) => void;
|
|
12
|
+
focusChange: (e: FocusEvent) => void;
|
|
13
|
+
onClick: (event: Event) => void;
|
|
14
|
+
}): any;
|
|
15
|
+
default?(_: {
|
|
16
|
+
id: string;
|
|
17
|
+
open: boolean;
|
|
18
|
+
onClickToggle: (event: Event) => void;
|
|
19
|
+
focusChange: (e: FocusEvent) => void;
|
|
20
|
+
hidden: boolean;
|
|
21
|
+
}): any;
|
|
22
|
+
};
|
|
23
|
+
refs: {};
|
|
24
|
+
rootEl: HTMLDivElement;
|
|
25
|
+
};
|
|
26
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
27
|
+
declare const __VLS_component: import('vue').DefineComponent<CollapsePanelProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<CollapsePanelProps> & Readonly<{}>, {
|
|
28
|
+
group: string;
|
|
29
|
+
blurClose: boolean;
|
|
30
|
+
openSingle: boolean;
|
|
31
|
+
mouseOverToggle: boolean;
|
|
32
|
+
outsideClickClose: boolean;
|
|
33
|
+
escapeKeyClose: boolean;
|
|
34
|
+
toggleAttrs: Partial<import('vue').ButtonHTMLAttributes>;
|
|
35
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
36
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
37
|
+
export default _default;
|
|
38
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
39
|
+
new (): {
|
|
40
|
+
$slots: S;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=CollapsePanel.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CollapsePanel.vue.d.ts","sourceRoot":"","sources":["../src/CollapsePanel.vue"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA0BlD,iBAAS,cAAc;WA+CT,OAAO,IAA6B;;;;;;;;;;;YAXtB,GAAG;;;;;;;YACF,GAAG;;;;EAe/B;AAeD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;;;;wFAQnB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BaseProps } from '@phila/phila-ui-core';
|
|
2
|
+
import { UseCollapseProps } from '@phila/phila-ui-core/utils';
|
|
3
|
+
export { default as CollapsePanel } from './CollapsePanel.vue';
|
|
4
|
+
export type CollapsePanelProps = BaseProps & UseCollapseProps;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("vue");o.ref("");o.reactive({validateOnBlur:!1,validateOnInput:!1,validateOnChange:!1,validateOnMount:!1,required:!1,isValid:!0,errors:[]});const d=o.ref({}),c=o.ref(),y=400,T=o.ref(null);function A(e){const n=e?.group??"global",t=(l,r)=>{d.value[n][l]=r},f=(l,r)=>{d.value[n]={[l]:r}},p=l=>d.value[n][l]??!1,s=l=>{t(l,!p(l))},k=l=>{f(l,!p(l))},v=()=>{d.value[n]={}},a=l=>{l.key==="Escape"&&(t(e.id,!1),m())},g=l=>{if(!e)return;const r=l.target,[C]=Object.keys(d.value[n]).filter(w=>d.value[n][w]===!0),b=document.getElementById(C),P=document.querySelector(`[aria-controls="${C}"]`),h=r.getAttribute("aria-controls")===C||P?.contains(l.target);b&&!b.contains(r)&&!h&&(t(e.id,!1),m())},u=()=>{e&&(c.value=setTimeout(()=>{t(e.id,!1),m()},y))},i=()=>{e&&e.mouseOverToggle===!0&&(T.value=e.id,c.value=setTimeout(()=>{O()},y))},B=()=>{e&&e.mouseOverToggle===!0&&(T.value=null,clearTimeout(c.value),c.value=setTimeout(()=>{T.value!==e.id&&(t(e.id,!1),m())},y))},S=l=>{if(!e)return;const{relatedTarget:r}=l;if(!r||r.getAttribute("aria-controls")===e.id)return;const C=document.getElementById(e.id);C&&C.contains(r)||(clearTimeout(c.value),c.value=setTimeout(()=>{e.openSingle?f(e.id,!1):t(e.id,!1),m()},y))},L=()=>{e&&(e.outsideClickClose&&(document.addEventListener("click",g),document.addEventListener("touchend",g)),e.escapeKeyClose&&document.addEventListener("keydown",a))},m=()=>{document.removeEventListener("click",g),document.removeEventListener("touchend",g),document.removeEventListener("keydown",a),document.removeEventListener("scroll",u)},E=l=>{e&&(l?.preventDefault(),clearTimeout(c.value),L())},M=l=>{e&&(E(l),e.openSingle?k(e.id):s(e.id))},O=l=>{e&&(E(l),e.openSingle?f(e.id,!0):t(e.id,!0))};return o.onBeforeMount(()=>{d.value[n]||v()}),o.onUnmounted(()=>{m()}),{state:d,timeout:c,toggle:s,toggleSingle:k,setCollapsed:t,setSingleCollapsed:f,isCollapsed:p,reset:v,onMouseEnter:i,onMouseLeave:B,focusChange:S,onClickToggle:M,onClickOpen:O}}const I=["data-toggle","aria-label","aria-expanded","aria-controls"],q=o.defineComponent({__name:"CollapsePanel",props:{className:{},id:{},group:{default:void 0},blurClose:{type:Boolean,default:!1},openSingle:{type:Boolean,default:!1},mouseOverToggle:{type:Boolean,default:!1},outsideClickClose:{type:Boolean,default:!1},escapeKeyClose:{type:Boolean,default:!1},toggleAttrs:{default:void 0}},setup(e){const n=e,{isCollapsed:t,onMouseEnter:f,onMouseLeave:p,onClickToggle:s,onClickOpen:k,focusChange:v}=A(n),a=o.computed(()=>t(n.id));return(g,u)=>(o.openBlock(),o.createElementBlock("div",{onMouseenter:u[1]||(u[1]=(...i)=>o.unref(f)&&o.unref(f)(...i)),onMouseleave:u[2]||(u[2]=(...i)=>o.unref(p)&&o.unref(p)(...i)),onFocusout:u[3]||(u[3]=(...i)=>o.unref(v)&&o.unref(v)(...i))},[o.renderSlot(g.$slots,"toggle",o.normalizeProps(o.guardReactiveProps({open:a.value,ariaLabel:a.value?"Close panel":"Open panel",ariaExpanded:a.value,ariaControls:e.id,onClickToggle:o.unref(s),onClickOpen:o.unref(k),focusChange:o.unref(v),onClick:o.unref(s)})),()=>[o.createElementVNode("button",o.mergeProps({"data-toggle":e.id,"aria-label":a.value?"Close panel":"Open panel","aria-expanded":a.value,"aria-controls":e.id},e.toggleAttrs,{onClick:u[0]||(u[0]=o.withModifiers((...i)=>o.unref(s)&&o.unref(s)(...i),["prevent"]))}),null,16,I)]),o.renderSlot(g.$slots,"default",o.normalizeProps(o.guardReactiveProps({id:e.id,open:a.value,onClickToggle:o.unref(s),focusChange:o.unref(v),hidden:!a.value})))],32))}});exports.CollapsePanel=q;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { ref as T, reactive as q, onBeforeMount as D, onUnmounted as K, defineComponent as N, computed as V, createElementBlock as j, openBlock as z, unref as l, renderSlot as b, normalizeProps as M, guardReactiveProps as S, createElementVNode as F, mergeProps as R, withModifiers as U } from "vue";
|
|
2
|
+
T("");
|
|
3
|
+
q({
|
|
4
|
+
validateOnBlur: !1,
|
|
5
|
+
validateOnInput: !1,
|
|
6
|
+
validateOnChange: !1,
|
|
7
|
+
validateOnMount: !1,
|
|
8
|
+
required: !1,
|
|
9
|
+
isValid: !0,
|
|
10
|
+
errors: []
|
|
11
|
+
});
|
|
12
|
+
const d = T({}), c = T(), E = 400, y = T(null);
|
|
13
|
+
function G(e) {
|
|
14
|
+
const t = e?.group ?? "global", n = (o, i) => {
|
|
15
|
+
d.value[t][o] = i;
|
|
16
|
+
}, v = (o, i) => {
|
|
17
|
+
d.value[t] = { [o]: i };
|
|
18
|
+
}, p = (o) => d.value[t][o] ?? !1, r = (o) => {
|
|
19
|
+
n(o, !p(o));
|
|
20
|
+
}, k = (o) => {
|
|
21
|
+
v(o, !p(o));
|
|
22
|
+
}, g = () => {
|
|
23
|
+
d.value[t] = {};
|
|
24
|
+
}, a = (o) => {
|
|
25
|
+
o.key === "Escape" && (n(e.id, !1), m());
|
|
26
|
+
}, f = (o) => {
|
|
27
|
+
if (!e) return;
|
|
28
|
+
const i = o.target, [C] = Object.keys(d.value[t]).filter(($) => d.value[t][$] === !0), L = document.getElementById(C), I = document.querySelector(`[aria-controls="${C}"]`), x = i.getAttribute("aria-controls") === C || I?.contains(o.target);
|
|
29
|
+
L && !L.contains(i) && !x && (n(e.id, !1), m());
|
|
30
|
+
}, u = () => {
|
|
31
|
+
e && (c.value = setTimeout(() => {
|
|
32
|
+
n(e.id, !1), m();
|
|
33
|
+
}, E));
|
|
34
|
+
}, s = () => {
|
|
35
|
+
e && e.mouseOverToggle === !0 && (y.value = e.id, c.value = setTimeout(() => {
|
|
36
|
+
B();
|
|
37
|
+
}, E));
|
|
38
|
+
}, P = () => {
|
|
39
|
+
e && e.mouseOverToggle === !0 && (y.value = null, clearTimeout(c.value), c.value = setTimeout(() => {
|
|
40
|
+
y.value !== e.id && (n(e.id, !1), m());
|
|
41
|
+
}, E));
|
|
42
|
+
}, h = (o) => {
|
|
43
|
+
if (!e) return;
|
|
44
|
+
const { relatedTarget: i } = o;
|
|
45
|
+
if (!i || i.getAttribute("aria-controls") === e.id)
|
|
46
|
+
return;
|
|
47
|
+
const C = document.getElementById(e.id);
|
|
48
|
+
C && C.contains(i) || (clearTimeout(c.value), c.value = setTimeout(() => {
|
|
49
|
+
e.openSingle ? v(e.id, !1) : n(e.id, !1), m();
|
|
50
|
+
}, E));
|
|
51
|
+
}, w = () => {
|
|
52
|
+
e && (e.outsideClickClose && (document.addEventListener("click", f), document.addEventListener("touchend", f)), e.escapeKeyClose && document.addEventListener("keydown", a));
|
|
53
|
+
}, m = () => {
|
|
54
|
+
document.removeEventListener("click", f), document.removeEventListener("touchend", f), document.removeEventListener("keydown", a), document.removeEventListener("scroll", u);
|
|
55
|
+
}, O = (o) => {
|
|
56
|
+
e && (o?.preventDefault(), clearTimeout(c.value), w());
|
|
57
|
+
}, A = (o) => {
|
|
58
|
+
e && (O(o), e.openSingle ? k(e.id) : r(e.id));
|
|
59
|
+
}, B = (o) => {
|
|
60
|
+
e && (O(o), e.openSingle ? v(e.id, !0) : n(e.id, !0));
|
|
61
|
+
};
|
|
62
|
+
return D(() => {
|
|
63
|
+
d.value[t] || g();
|
|
64
|
+
}), K(() => {
|
|
65
|
+
m();
|
|
66
|
+
}), {
|
|
67
|
+
state: d,
|
|
68
|
+
timeout: c,
|
|
69
|
+
toggle: r,
|
|
70
|
+
toggleSingle: k,
|
|
71
|
+
setCollapsed: n,
|
|
72
|
+
setSingleCollapsed: v,
|
|
73
|
+
isCollapsed: p,
|
|
74
|
+
reset: g,
|
|
75
|
+
onMouseEnter: s,
|
|
76
|
+
onMouseLeave: P,
|
|
77
|
+
focusChange: h,
|
|
78
|
+
onClickToggle: A,
|
|
79
|
+
onClickOpen: B
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const H = ["data-toggle", "aria-label", "aria-expanded", "aria-controls"], Q = /* @__PURE__ */ N({
|
|
83
|
+
__name: "CollapsePanel",
|
|
84
|
+
props: {
|
|
85
|
+
className: {},
|
|
86
|
+
id: {},
|
|
87
|
+
group: { default: void 0 },
|
|
88
|
+
blurClose: { type: Boolean, default: !1 },
|
|
89
|
+
openSingle: { type: Boolean, default: !1 },
|
|
90
|
+
mouseOverToggle: { type: Boolean, default: !1 },
|
|
91
|
+
outsideClickClose: { type: Boolean, default: !1 },
|
|
92
|
+
escapeKeyClose: { type: Boolean, default: !1 },
|
|
93
|
+
toggleAttrs: { default: void 0 }
|
|
94
|
+
},
|
|
95
|
+
setup(e) {
|
|
96
|
+
const t = e, { isCollapsed: n, onMouseEnter: v, onMouseLeave: p, onClickToggle: r, onClickOpen: k, focusChange: g } = G(t), a = V(() => n(t.id));
|
|
97
|
+
return (f, u) => (z(), j("div", {
|
|
98
|
+
onMouseenter: u[1] || (u[1] = //@ts-ignore
|
|
99
|
+
(...s) => l(v) && l(v)(...s)),
|
|
100
|
+
onMouseleave: u[2] || (u[2] = //@ts-ignore
|
|
101
|
+
(...s) => l(p) && l(p)(...s)),
|
|
102
|
+
onFocusout: u[3] || (u[3] = //@ts-ignore
|
|
103
|
+
(...s) => l(g) && l(g)(...s))
|
|
104
|
+
}, [
|
|
105
|
+
b(f.$slots, "toggle", M(S({
|
|
106
|
+
open: a.value,
|
|
107
|
+
ariaLabel: a.value ? "Close panel" : "Open panel",
|
|
108
|
+
ariaExpanded: a.value,
|
|
109
|
+
ariaControls: e.id,
|
|
110
|
+
onClickToggle: l(r),
|
|
111
|
+
onClickOpen: l(k),
|
|
112
|
+
focusChange: l(g),
|
|
113
|
+
onClick: l(r)
|
|
114
|
+
})), () => [
|
|
115
|
+
F("button", R({
|
|
116
|
+
"data-toggle": e.id,
|
|
117
|
+
"aria-label": a.value ? "Close panel" : "Open panel",
|
|
118
|
+
"aria-expanded": a.value,
|
|
119
|
+
"aria-controls": e.id
|
|
120
|
+
}, e.toggleAttrs, {
|
|
121
|
+
onClick: u[0] || (u[0] = U(
|
|
122
|
+
//@ts-ignore
|
|
123
|
+
(...s) => l(r) && l(r)(...s),
|
|
124
|
+
["prevent"]
|
|
125
|
+
))
|
|
126
|
+
}), null, 16, H)
|
|
127
|
+
]),
|
|
128
|
+
b(f.$slots, "default", M(S({ id: e.id, open: a.value, onClickToggle: l(r), focusChange: l(g), hidden: !a.value })))
|
|
129
|
+
], 32));
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
export {
|
|
133
|
+
Q as CollapsePanel
|
|
134
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@phila/phila-ui-collapse-panel",
|
|
3
|
+
"version": "0.0.1-beta.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Customizable component for toggling visibility of content. ",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"ui",
|
|
21
|
+
"collapse-panel",
|
|
22
|
+
"vue",
|
|
23
|
+
"component"
|
|
24
|
+
],
|
|
25
|
+
"author": "",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"vue": "^3.0.0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@phila/phila-ui-core": "2.2.0-beta.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^24.0.0",
|
|
35
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
36
|
+
"eslint": "^9.0.0",
|
|
37
|
+
"typescript": "^5.8.3",
|
|
38
|
+
"vite": "^7.0.6",
|
|
39
|
+
"vite-plugin-dts": "^4.5.4",
|
|
40
|
+
"vite-plugin-lib-inject-css": "^2.2.2"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "vite build",
|
|
44
|
+
"build-win": "vite build",
|
|
45
|
+
"dev": "vite build --watch",
|
|
46
|
+
"lint": "eslint src --ext .ts,.tsx,.vue",
|
|
47
|
+
"lint:fix": "eslint src --ext .ts,.tsx,.vue --fix",
|
|
48
|
+
"type-check": "tsc --noEmit",
|
|
49
|
+
"clean": "rm -rf dist",
|
|
50
|
+
"format": "prettier --write .",
|
|
51
|
+
"format:check": "prettier --check ."
|
|
52
|
+
}
|
|
53
|
+
}
|