@esportsplus/ui 0.0.67 → 0.0.68
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/build/components/field/file.d.ts +22 -0
- package/build/components/field/file.js +45 -0
- package/build/components/field/index.d.ts +23 -0
- package/build/components/field/index.js +2 -1
- package/build/components/field/title.js +2 -1
- package/build/components/form/layout.js +1 -1
- package/build/components/tooltip/index.d.ts +44 -31
- package/build/components/tooltip/index.js +43 -29
- package/build/components/tooltip/menu.d.ts +4 -1
- package/build/components/tooltip/menu.js +3 -6
- package/package.json +1 -1
- package/src/components/field/file.ts +64 -0
- package/src/components/field/index.ts +2 -1
- package/src/components/field/title.ts +3 -1
- package/src/components/form/layout.ts +1 -1
- package/src/components/tooltip/index.ts +47 -31
- package/src/components/tooltip/menu.ts +4 -7
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import description from './description';
|
|
2
|
+
import title from './title';
|
|
3
|
+
type Data = {
|
|
4
|
+
accept?: string;
|
|
5
|
+
class?: string;
|
|
6
|
+
mask?: {
|
|
7
|
+
class?: string;
|
|
8
|
+
content?: any;
|
|
9
|
+
style?: string;
|
|
10
|
+
};
|
|
11
|
+
name?: string;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
style?: string;
|
|
14
|
+
type?: string;
|
|
15
|
+
value?: unknown;
|
|
16
|
+
} & Parameters<typeof description>[0] & Parameters<typeof title>[0];
|
|
17
|
+
declare const _default: (data: Data) => {
|
|
18
|
+
content: string;
|
|
19
|
+
type: string;
|
|
20
|
+
values: never[];
|
|
21
|
+
};
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { reactive } from '@esportsplus/reactivity';
|
|
2
|
+
import { html } from '@esportsplus/template';
|
|
3
|
+
import { form } from '../../components';
|
|
4
|
+
import description from './description';
|
|
5
|
+
import error from './error';
|
|
6
|
+
import title from './title';
|
|
7
|
+
export default (data) => {
|
|
8
|
+
let state = reactive({
|
|
9
|
+
active: false,
|
|
10
|
+
error: ''
|
|
11
|
+
});
|
|
12
|
+
return html `
|
|
13
|
+
<div
|
|
14
|
+
class="field ${data?.class || ''} ${() => state.active ? '--active' : ''} --flex-column"
|
|
15
|
+
onfocusin='${() => {
|
|
16
|
+
state.active = true;
|
|
17
|
+
}}'
|
|
18
|
+
onfocusout='${() => {
|
|
19
|
+
state.active = false;
|
|
20
|
+
}}'
|
|
21
|
+
style='${data?.style || ''}'
|
|
22
|
+
>
|
|
23
|
+
${title(data)}
|
|
24
|
+
|
|
25
|
+
<label
|
|
26
|
+
class='field-mask field-mask--input --flex-row ${data?.mask?.class || ''} ${(data?.title || (data?.class || '').indexOf('field--optional') !== -1) && '--margin-top'} --margin-300'
|
|
27
|
+
style='${data?.mask?.style || ''}'
|
|
28
|
+
>
|
|
29
|
+
<input
|
|
30
|
+
${data?.accept ? `accept='${data.accept}'` : ''}
|
|
31
|
+
class='field-tag field-tag--hidden'
|
|
32
|
+
name='${data.name}'
|
|
33
|
+
onrender='${form.input.attributes(state)}'
|
|
34
|
+
type='file'
|
|
35
|
+
${data?.value !== undefined ? `value='${data.value}'` : ''}
|
|
36
|
+
>
|
|
37
|
+
|
|
38
|
+
${data?.mask?.content || ''}
|
|
39
|
+
</label>
|
|
40
|
+
|
|
41
|
+
${description(data)}
|
|
42
|
+
${error(state)}
|
|
43
|
+
</div>
|
|
44
|
+
`;
|
|
45
|
+
};
|
|
@@ -19,6 +19,29 @@ declare const _default: {
|
|
|
19
19
|
type: string;
|
|
20
20
|
values: never[];
|
|
21
21
|
};
|
|
22
|
+
file: (data: {
|
|
23
|
+
accept?: string | undefined;
|
|
24
|
+
class?: string | undefined;
|
|
25
|
+
mask?: {
|
|
26
|
+
class?: string | undefined;
|
|
27
|
+
content?: any;
|
|
28
|
+
style?: string | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
name?: string | undefined;
|
|
31
|
+
placeholder?: string | undefined;
|
|
32
|
+
style?: string | undefined;
|
|
33
|
+
type?: string | undefined;
|
|
34
|
+
value?: unknown;
|
|
35
|
+
} & {
|
|
36
|
+
description?: string | undefined;
|
|
37
|
+
} & {
|
|
38
|
+
required?: boolean | undefined;
|
|
39
|
+
title?: string | undefined;
|
|
40
|
+
}) => {
|
|
41
|
+
content: string;
|
|
42
|
+
type: string;
|
|
43
|
+
values: never[];
|
|
44
|
+
};
|
|
22
45
|
optional: {
|
|
23
46
|
select: (data: {
|
|
24
47
|
class?: string | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import checkbox from './checkbox';
|
|
2
|
+
import file from './file';
|
|
2
3
|
import optional from './optional';
|
|
3
4
|
import select from './select';
|
|
4
5
|
import s from './switch';
|
|
5
6
|
import text from './text';
|
|
6
|
-
export default { checkbox, optional, select, switch: s, text };
|
|
7
|
+
export default { checkbox, file, optional, select, switch: s, text };
|
|
@@ -4,12 +4,13 @@ export default (data) => {
|
|
|
4
4
|
if (!data?.title) {
|
|
5
5
|
return '';
|
|
6
6
|
}
|
|
7
|
+
let { attributes } = tooltip.onhover();
|
|
7
8
|
return html `
|
|
8
9
|
<div class="field-title --flex-horizontal-space-between --flex-vertical">
|
|
9
10
|
${data.title}
|
|
10
11
|
|
|
11
12
|
${data?.required && html `
|
|
12
|
-
<div class="bubble --background-primary --margin-left" ${
|
|
13
|
+
<div class="bubble --background-primary --margin-left" ${attributes}>
|
|
13
14
|
<span class="tooltip-message tooltip-message--w">Required</span>
|
|
14
15
|
</div>
|
|
15
16
|
`}
|
|
@@ -6,7 +6,7 @@ export default (data) => html `
|
|
|
6
6
|
<form class='${data?.class}' ${data?.action || ''}>
|
|
7
7
|
${data?.content || ''}
|
|
8
8
|
|
|
9
|
-
${data?.button ? html `
|
|
9
|
+
${data?.button?.content ? html `
|
|
10
10
|
<button class="button ${data?.button?.class || ''}" style='${data?.button?.style || ''}'>
|
|
11
11
|
${data?.button?.content || ''}
|
|
12
12
|
</button>
|
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
-
onclick: (
|
|
2
|
+
onclick: (data?: {
|
|
3
3
|
active?: boolean | undefined;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
content: string;
|
|
12
|
-
type: string;
|
|
13
|
-
values: never[];
|
|
14
|
-
};
|
|
15
|
-
menu: (data: {
|
|
16
|
-
class?: string | undefined;
|
|
17
|
-
direction?: string | undefined;
|
|
18
|
-
items?: {
|
|
19
|
-
border?: {
|
|
4
|
+
menu?: {
|
|
5
|
+
class?: string | undefined;
|
|
6
|
+
direction?: string | undefined;
|
|
7
|
+
items?: {
|
|
8
|
+
border?: {
|
|
9
|
+
class?: string | undefined;
|
|
10
|
+
} | undefined;
|
|
20
11
|
class?: string | undefined;
|
|
12
|
+
onclick?: ((...args: any[]) => void) | undefined;
|
|
13
|
+
style?: string | undefined;
|
|
14
|
+
svg?: string | undefined;
|
|
15
|
+
target?: string | undefined;
|
|
16
|
+
text: string;
|
|
17
|
+
url?: string | undefined;
|
|
18
|
+
}[] | undefined;
|
|
19
|
+
state?: {
|
|
20
|
+
active?: boolean | undefined;
|
|
21
21
|
} | undefined;
|
|
22
|
-
class?: string | undefined;
|
|
23
|
-
onclick?: ((...args: any[]) => void) | undefined;
|
|
24
22
|
style?: string | undefined;
|
|
25
|
-
svg?: string | undefined;
|
|
26
|
-
target?: string | undefined;
|
|
27
|
-
text: string;
|
|
28
|
-
url?: string | undefined;
|
|
29
|
-
}[] | undefined;
|
|
30
|
-
state?: {
|
|
31
|
-
active?: boolean | undefined;
|
|
32
23
|
} | undefined;
|
|
33
|
-
|
|
34
|
-
}) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
toggle?: boolean | undefined;
|
|
25
|
+
}) => {
|
|
26
|
+
attributes: {
|
|
27
|
+
content: string;
|
|
28
|
+
type: string;
|
|
29
|
+
values: never[];
|
|
30
|
+
};
|
|
31
|
+
content: (() => "" | {
|
|
32
|
+
content: string;
|
|
33
|
+
type: string;
|
|
34
|
+
values: never[];
|
|
35
|
+
}) | undefined;
|
|
36
|
+
state: {
|
|
37
|
+
active: boolean;
|
|
38
|
+
render: boolean | undefined;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
onhover: (active?: boolean) => {
|
|
42
|
+
attributes: {
|
|
43
|
+
content: string;
|
|
44
|
+
type: string;
|
|
45
|
+
values: never[];
|
|
46
|
+
};
|
|
47
|
+
state: {
|
|
48
|
+
active: boolean;
|
|
49
|
+
render: boolean | undefined;
|
|
50
|
+
};
|
|
38
51
|
};
|
|
39
52
|
};
|
|
40
53
|
export default _default;
|
|
@@ -2,38 +2,52 @@ import { reactive } from '@esportsplus/reactivity';
|
|
|
2
2
|
import { html } from '@esportsplus/template';
|
|
3
3
|
import { root } from '../../components';
|
|
4
4
|
import menu from './menu';
|
|
5
|
-
const onclick = (
|
|
6
|
-
let state = reactive({
|
|
7
|
-
active: active || false
|
|
5
|
+
const onclick = (data = {}) => {
|
|
6
|
+
let content, state = reactive({
|
|
7
|
+
active: data.active || false,
|
|
8
|
+
render: undefined
|
|
8
9
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
if (data.menu) {
|
|
11
|
+
content = menu(data.menu, state);
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
attributes: html({
|
|
15
|
+
class: () => {
|
|
16
|
+
return `tooltip ${state.active ? '--active' : ''}`;
|
|
17
|
+
},
|
|
18
|
+
onclick: function (e) {
|
|
19
|
+
let active = true;
|
|
20
|
+
if (data.toggle && e.target && this.isSameNode(e.target)) {
|
|
21
|
+
active = !state.active;
|
|
22
|
+
}
|
|
23
|
+
state.active = active;
|
|
24
|
+
if (active) {
|
|
25
|
+
root.queue.onclick(() => state.active = false);
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
|
-
}
|
|
23
|
-
|
|
28
|
+
}),
|
|
29
|
+
content,
|
|
30
|
+
state
|
|
31
|
+
};
|
|
24
32
|
};
|
|
25
33
|
const onhover = (active = false) => {
|
|
26
|
-
let state = reactive({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return `tooltip ${state.active ? '--active' : ''}`;
|
|
30
|
-
},
|
|
31
|
-
onmouseover: () => {
|
|
32
|
-
state.active = true;
|
|
33
|
-
},
|
|
34
|
-
onmouseout: () => {
|
|
35
|
-
state.active = false;
|
|
36
|
-
}
|
|
34
|
+
let state = reactive({
|
|
35
|
+
active,
|
|
36
|
+
render: undefined
|
|
37
37
|
});
|
|
38
|
+
return {
|
|
39
|
+
attributes: html({
|
|
40
|
+
class: () => {
|
|
41
|
+
return `tooltip ${state.active ? '--active' : ''}`;
|
|
42
|
+
},
|
|
43
|
+
onmouseover: () => {
|
|
44
|
+
state.active = true;
|
|
45
|
+
},
|
|
46
|
+
onmouseout: () => {
|
|
47
|
+
state.active = false;
|
|
48
|
+
}
|
|
49
|
+
}),
|
|
50
|
+
state
|
|
51
|
+
};
|
|
38
52
|
};
|
|
39
|
-
export default { onclick, onhover
|
|
53
|
+
export default { onclick, onhover };
|
|
@@ -18,7 +18,10 @@ type Data = {
|
|
|
18
18
|
};
|
|
19
19
|
style?: string;
|
|
20
20
|
};
|
|
21
|
-
declare const _default: (data: Data
|
|
21
|
+
declare const _default: (data: Data, state: {
|
|
22
|
+
active?: boolean;
|
|
23
|
+
render?: boolean;
|
|
24
|
+
}) => () => "" | {
|
|
22
25
|
content: string;
|
|
23
26
|
type: string;
|
|
24
27
|
values: never[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { effect
|
|
1
|
+
import { effect } from '@esportsplus/reactivity';
|
|
2
2
|
import { html } from '@esportsplus/template';
|
|
3
3
|
function template(data) {
|
|
4
4
|
return html `
|
|
@@ -33,12 +33,9 @@ function template(data) {
|
|
|
33
33
|
</div>
|
|
34
34
|
`;
|
|
35
35
|
}
|
|
36
|
-
export default (data) => {
|
|
37
|
-
let state = reactive({
|
|
38
|
-
render: false
|
|
39
|
-
});
|
|
36
|
+
export default (data, state) => {
|
|
40
37
|
effect(() => {
|
|
41
|
-
if (!
|
|
38
|
+
if (!state.active || state.render) {
|
|
42
39
|
return;
|
|
43
40
|
}
|
|
44
41
|
state.render = true;
|
package/package.json
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { reactive } from '@esportsplus/reactivity';
|
|
2
|
+
import { html } from '@esportsplus/template';
|
|
3
|
+
import { form } from '~/components';
|
|
4
|
+
import description from './description';
|
|
5
|
+
import error from './error';
|
|
6
|
+
import title from './title';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
type Data = {
|
|
10
|
+
accept?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
mask?: {
|
|
13
|
+
class?: string;
|
|
14
|
+
content?: any;
|
|
15
|
+
style?: string;
|
|
16
|
+
};
|
|
17
|
+
name?: string;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
style?: string;
|
|
20
|
+
type?: string;
|
|
21
|
+
value?: unknown;
|
|
22
|
+
} & Parameters<typeof description>[0] & Parameters<typeof title>[0];
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export default (data: Data) => {
|
|
26
|
+
let state = reactive({
|
|
27
|
+
active: false,
|
|
28
|
+
error: ''
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return html`
|
|
32
|
+
<div
|
|
33
|
+
class="field ${data?.class || ''} ${() => state.active ? '--active' : ''} --flex-column"
|
|
34
|
+
onfocusin='${() => {
|
|
35
|
+
state.active = true;
|
|
36
|
+
}}'
|
|
37
|
+
onfocusout='${() => {
|
|
38
|
+
state.active = false;
|
|
39
|
+
}}'
|
|
40
|
+
style='${data?.style || ''}'
|
|
41
|
+
>
|
|
42
|
+
${title(data)}
|
|
43
|
+
|
|
44
|
+
<label
|
|
45
|
+
class='field-mask field-mask--input --flex-row ${data?.mask?.class || ''} ${(data?.title || (data?.class || '').indexOf('field--optional') !== -1) && '--margin-top'} --margin-300'
|
|
46
|
+
style='${data?.mask?.style || ''}'
|
|
47
|
+
>
|
|
48
|
+
<input
|
|
49
|
+
${data?.accept ? `accept='${data.accept}'` : ''}
|
|
50
|
+
class='field-tag field-tag--hidden'
|
|
51
|
+
name='${data.name}'
|
|
52
|
+
onrender='${form.input.attributes(state)}'
|
|
53
|
+
type='file'
|
|
54
|
+
${data?.value !== undefined ? `value='${data.value}'` : ''}
|
|
55
|
+
>
|
|
56
|
+
|
|
57
|
+
${data?.mask?.content || ''}
|
|
58
|
+
</label>
|
|
59
|
+
|
|
60
|
+
${description(data)}
|
|
61
|
+
${error(state)}
|
|
62
|
+
</div>
|
|
63
|
+
`;
|
|
64
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import checkbox from './checkbox';
|
|
2
|
+
import file from './file';
|
|
2
3
|
import optional from './optional';
|
|
3
4
|
import select from './select';
|
|
4
5
|
import s from './switch';
|
|
5
6
|
import text from './text';
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
export default { checkbox, optional, select, switch: s, text };
|
|
9
|
+
export default { checkbox, file, optional, select, switch: s, text };
|
|
@@ -7,12 +7,14 @@ export default (data: { required?: boolean, title?: string }) => {
|
|
|
7
7
|
return '';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
let { attributes } = tooltip.onhover();
|
|
11
|
+
|
|
10
12
|
return html`
|
|
11
13
|
<div class="field-title --flex-horizontal-space-between --flex-vertical">
|
|
12
14
|
${data.title}
|
|
13
15
|
|
|
14
16
|
${data?.required && html`
|
|
15
|
-
<div class="bubble --background-primary --margin-left" ${
|
|
17
|
+
<div class="bubble --background-primary --margin-left" ${attributes}>
|
|
16
18
|
<span class="tooltip-message tooltip-message--w">Required</span>
|
|
17
19
|
</div>
|
|
18
20
|
`}
|
|
@@ -20,7 +20,7 @@ export default (data: Data) => html`
|
|
|
20
20
|
<form class='${data?.class}' ${data?.action || ''}>
|
|
21
21
|
${data?.content || ''}
|
|
22
22
|
|
|
23
|
-
${data?.button ? html`
|
|
23
|
+
${data?.button?.content ? html`
|
|
24
24
|
<button class="button ${data?.button?.class || ''}" style='${data?.button?.style || ''}'>
|
|
25
25
|
${data?.button?.content || ''}
|
|
26
26
|
</button>
|
|
@@ -4,46 +4,62 @@ import { root } from '~/components';
|
|
|
4
4
|
import menu from './menu';
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
const onclick = (
|
|
8
|
-
let
|
|
9
|
-
|
|
7
|
+
const onclick = (data: { active?: boolean, menu?: Parameters<typeof menu>[0], toggle?: boolean } = {}) => {
|
|
8
|
+
let content,
|
|
9
|
+
state = reactive({
|
|
10
|
+
active: data.active || false,
|
|
11
|
+
render: undefined as boolean | undefined
|
|
10
12
|
});
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
onclick: function(this: HTMLElement, e: Event) {
|
|
17
|
-
let active = true;
|
|
14
|
+
if (data.menu) {
|
|
15
|
+
content = menu(data.menu, state);
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
return {
|
|
19
|
+
attributes: html({
|
|
20
|
+
class: () => {
|
|
21
|
+
return `tooltip ${state.active ? '--active' : ''}`;
|
|
22
|
+
},
|
|
23
|
+
onclick: function(this: HTMLElement, e: Event) {
|
|
24
|
+
let active = true;
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
if (data.toggle && e.target && this.isSameNode(e.target as Node)) {
|
|
27
|
+
active = !state.active;
|
|
28
|
+
}
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
state.active = active;
|
|
31
|
+
|
|
32
|
+
if (active) {
|
|
33
|
+
root.queue.onclick(() => state.active = false);
|
|
34
|
+
}
|
|
27
35
|
}
|
|
28
|
-
}
|
|
29
|
-
|
|
36
|
+
}),
|
|
37
|
+
content,
|
|
38
|
+
state
|
|
39
|
+
};
|
|
30
40
|
};
|
|
31
41
|
|
|
32
42
|
const onhover = (active: boolean = false) => {
|
|
33
|
-
let state = reactive({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
let state = reactive({
|
|
44
|
+
active,
|
|
45
|
+
render: undefined as boolean | undefined
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
attributes: html({
|
|
50
|
+
class: () => {
|
|
51
|
+
return `tooltip ${state.active ? '--active' : ''}`;
|
|
52
|
+
},
|
|
53
|
+
onmouseover: () => {
|
|
54
|
+
state.active = true;
|
|
55
|
+
},
|
|
56
|
+
onmouseout: () => {
|
|
57
|
+
state.active = false;
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
60
|
+
state
|
|
61
|
+
};
|
|
46
62
|
};
|
|
47
63
|
|
|
48
64
|
|
|
49
|
-
export default { onclick, onhover
|
|
65
|
+
export default { onclick, onhover };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { effect
|
|
1
|
+
import { effect } from '@esportsplus/reactivity';
|
|
2
2
|
import { html } from '@esportsplus/template';
|
|
3
3
|
|
|
4
4
|
|
|
@@ -57,13 +57,10 @@ function template(data: Data) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
render: false
|
|
63
|
-
});
|
|
64
|
-
|
|
60
|
+
// TODO: There's nothing binding activate to tooltip menu ( this is never called outside initial effect run )
|
|
61
|
+
export default (data: Data, state: { active?: boolean, render?: boolean }) => {
|
|
65
62
|
effect(() => {
|
|
66
|
-
if (!
|
|
63
|
+
if (!state.active || state.render) {
|
|
67
64
|
return;
|
|
68
65
|
}
|
|
69
66
|
|