@vue-lynx-example/gallery 0.1.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 +25 -0
- package/dist/gallery-autoscroll.lynx.bundle +0 -0
- package/dist/gallery-autoscroll.web.bundle +1 -0
- package/dist/gallery-complete.lynx.bundle +0 -0
- package/dist/gallery-complete.web.bundle +1 -0
- package/dist/gallery-image-card.lynx.bundle +0 -0
- package/dist/gallery-image-card.web.bundle +1 -0
- package/dist/gallery-like-card.lynx.bundle +0 -0
- package/dist/gallery-like-card.web.bundle +1 -0
- package/dist/gallery-list.lynx.bundle +0 -0
- package/dist/gallery-list.web.bundle +1 -0
- package/dist/gallery-scrollbar-compare.lynx.bundle +0 -0
- package/dist/gallery-scrollbar-compare.web.bundle +1 -0
- package/dist/gallery-scrollbar.lynx.bundle +0 -0
- package/dist/gallery-scrollbar.web.bundle +1 -0
- package/dist/static/image/0.1ec73866.png +0 -0
- package/dist/static/image/1.c8baad9e.png +0 -0
- package/dist/static/image/10.c5f92ea5.png +0 -0
- package/dist/static/image/11.c70f5ba7.png +0 -0
- package/dist/static/image/12.512c6362.png +0 -0
- package/dist/static/image/13.1d74c22d.png +0 -0
- package/dist/static/image/14.869ed1e0.png +0 -0
- package/dist/static/image/2.d34b0fb3.png +0 -0
- package/dist/static/image/3.b229c89b.png +0 -0
- package/dist/static/image/4.610a08cd.png +0 -0
- package/dist/static/image/5.de3eae9e.png +0 -0
- package/dist/static/image/6.f2581914.png +0 -0
- package/dist/static/image/7.4e481ae9.png +0 -0
- package/dist/static/image/8.3b550db5.png +0 -0
- package/dist/static/image/9.5e33c8e0.png +0 -0
- package/lynx.config.ts +26 -0
- package/package.json +34 -0
- package/src/Components/LikeIcon.vue +20 -0
- package/src/Components/LikeImageCard.vue +19 -0
- package/src/GalleryAutoScroll/Gallery.vue +43 -0
- package/src/GalleryAutoScroll/index.ts +7 -0
- package/src/GalleryComplete/Gallery.vue +70 -0
- package/src/GalleryComplete/NiceScrollbarMTS.vue +16 -0
- package/src/GalleryComplete/index.ts +7 -0
- package/src/GalleryList/Gallery.vue +27 -0
- package/src/GalleryList/index.ts +7 -0
- package/src/GalleryScrollbar/Gallery.vue +54 -0
- package/src/GalleryScrollbar/NiceScrollbar.vue +25 -0
- package/src/GalleryScrollbar/index.ts +7 -0
- package/src/GalleryScrollbarCompare/Gallery.vue +80 -0
- package/src/GalleryScrollbarCompare/NiceScrollbar.vue +25 -0
- package/src/GalleryScrollbarCompare/NiceScrollbarMTS.vue +22 -0
- package/src/GalleryScrollbarCompare/index.ts +7 -0
- package/src/ImageCard/ImageCard.vue +16 -0
- package/src/ImageCard/index.ts +21 -0
- package/src/LikeCard/index.ts +21 -0
- package/src/Pictures/furnitures/0.png +0 -0
- package/src/Pictures/furnitures/1.png +0 -0
- package/src/Pictures/furnitures/10.png +0 -0
- package/src/Pictures/furnitures/11.png +0 -0
- package/src/Pictures/furnitures/12.png +0 -0
- package/src/Pictures/furnitures/13.png +0 -0
- package/src/Pictures/furnitures/14.png +0 -0
- package/src/Pictures/furnitures/2.png +0 -0
- package/src/Pictures/furnitures/3.png +0 -0
- package/src/Pictures/furnitures/4.png +0 -0
- package/src/Pictures/furnitures/5.png +0 -0
- package/src/Pictures/furnitures/6.png +0 -0
- package/src/Pictures/furnitures/7.png +0 -0
- package/src/Pictures/furnitures/8.png +0 -0
- package/src/Pictures/furnitures/9.png +0 -0
- package/src/Pictures/furnituresPictures.ts +47 -0
- package/src/Pictures/redHeart.png +0 -0
- package/src/Pictures/whiteHeart.png +0 -0
- package/src/gallery.css +129 -0
- package/src/shims-vue.d.ts +11 -0
- package/src/utils.ts +14 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, onMounted, nextTick, useMainThreadRef, useTemplateRef } from 'vue-lynx';
|
|
3
|
+
import type { ShadowElement } from 'vue-lynx';
|
|
4
|
+
|
|
5
|
+
import { furnituresPictures } from '../Pictures/furnituresPictures';
|
|
6
|
+
import { calculateEstimatedSize } from '../utils';
|
|
7
|
+
|
|
8
|
+
import LikeImageCard from '../Components/LikeImageCard.vue';
|
|
9
|
+
import NiceScrollbar from './NiceScrollbar.vue';
|
|
10
|
+
import NiceScrollbarMTS from './NiceScrollbarMTS.vue';
|
|
11
|
+
|
|
12
|
+
declare const SystemInfo: { pixelHeight: number; pixelRatio: number };
|
|
13
|
+
|
|
14
|
+
const scrollbarRef = ref<InstanceType<typeof NiceScrollbar> | null>(null);
|
|
15
|
+
const scrollbarThumbRef = useMainThreadRef(null);
|
|
16
|
+
const listRef = useTemplateRef<ShadowElement>('listRef');
|
|
17
|
+
|
|
18
|
+
// BTS scroll handler
|
|
19
|
+
function onScroll(event: { detail?: { scrollTop?: number; scrollHeight?: number } }) {
|
|
20
|
+
const scrollTop = event.detail?.scrollTop ?? 0;
|
|
21
|
+
const scrollHeight = event.detail?.scrollHeight ?? 0;
|
|
22
|
+
scrollbarRef.value?.adjustScrollbar(scrollTop, scrollHeight);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// MTS scrollbar adjuster — runs directly on Main Thread (no -48 offset, full height)
|
|
26
|
+
function adjustScrollbarCompare(
|
|
27
|
+
scrollTop: number,
|
|
28
|
+
scrollHeight: number,
|
|
29
|
+
ref: { current?: { setStyleProperty?(k: string, v: string): void } },
|
|
30
|
+
) {
|
|
31
|
+
'main thread';
|
|
32
|
+
const listHeight = SystemInfo.pixelHeight / SystemInfo.pixelRatio;
|
|
33
|
+
const scrollbarHeight = listHeight * (listHeight / scrollHeight);
|
|
34
|
+
const scrollbarTop = listHeight * (scrollTop / scrollHeight);
|
|
35
|
+
ref.current?.setStyleProperty?.('height', `${scrollbarHeight}px`);
|
|
36
|
+
ref.current?.setStyleProperty?.('top', `${scrollbarTop}px`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const onScrollMTS = (event: { detail: { scrollTop: number; scrollHeight: number } }) => {
|
|
40
|
+
'main thread';
|
|
41
|
+
adjustScrollbarCompare(event.detail.scrollTop, event.detail.scrollHeight, scrollbarThumbRef);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
onMounted(() => {
|
|
45
|
+
nextTick(() => {
|
|
46
|
+
listRef.value
|
|
47
|
+
?.invoke({
|
|
48
|
+
method: 'autoScroll',
|
|
49
|
+
params: { rate: '60', start: 'true' },
|
|
50
|
+
})
|
|
51
|
+
.exec();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<view class="gallery-wrapper">
|
|
58
|
+
<NiceScrollbar ref="scrollbarRef" />
|
|
59
|
+
<NiceScrollbarMTS :thumb-ref="scrollbarThumbRef" />
|
|
60
|
+
<list
|
|
61
|
+
ref="listRef"
|
|
62
|
+
class="list"
|
|
63
|
+
list-type="waterfall"
|
|
64
|
+
:column-count="2"
|
|
65
|
+
scroll-orientation="vertical"
|
|
66
|
+
@scroll="onScroll"
|
|
67
|
+
:main-thread-bindscroll="onScrollMTS"
|
|
68
|
+
:scroll-event-throttle="0"
|
|
69
|
+
>
|
|
70
|
+
<list-item
|
|
71
|
+
v-for="(pic, i) in furnituresPictures"
|
|
72
|
+
:key="i"
|
|
73
|
+
:item-key="String(i)"
|
|
74
|
+
:estimated-main-axis-size-px="calculateEstimatedSize(pic.width, pic.height)"
|
|
75
|
+
>
|
|
76
|
+
<LikeImageCard :picture="pic" />
|
|
77
|
+
</list-item>
|
|
78
|
+
</list>
|
|
79
|
+
</view>
|
|
80
|
+
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue-lynx';
|
|
3
|
+
|
|
4
|
+
declare const SystemInfo: { pixelHeight: number; pixelRatio: number };
|
|
5
|
+
|
|
6
|
+
const scrollbarHeight = ref(0);
|
|
7
|
+
const scrollbarTop = ref(0);
|
|
8
|
+
|
|
9
|
+
function adjustScrollbar(scrollTop: number, scrollHeight: number) {
|
|
10
|
+
const listHeight = SystemInfo.pixelHeight / SystemInfo.pixelRatio;
|
|
11
|
+
scrollbarHeight.value = listHeight * (listHeight / scrollHeight);
|
|
12
|
+
scrollbarTop.value = listHeight * (scrollTop / scrollHeight);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
defineExpose({ adjustScrollbar });
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<view
|
|
20
|
+
class="scrollbar"
|
|
21
|
+
:style="{ right: '3px', height: scrollbarHeight + 'px', top: scrollbarTop + 'px' }"
|
|
22
|
+
>
|
|
23
|
+
<view class="scrollbar-effect glow" />
|
|
24
|
+
</view>
|
|
25
|
+
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { MainThreadRef } from 'vue-lynx';
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
thumbRef: MainThreadRef;
|
|
6
|
+
}>();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<view
|
|
11
|
+
class="scrollbar"
|
|
12
|
+
:main-thread-ref="thumbRef"
|
|
13
|
+
:style="{
|
|
14
|
+
right: '14px',
|
|
15
|
+
backgroundColor: 'darkkhaki',
|
|
16
|
+
height: '60px',
|
|
17
|
+
top: '0px',
|
|
18
|
+
}"
|
|
19
|
+
>
|
|
20
|
+
<view class="scrollbar-effect glow" />
|
|
21
|
+
</view>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { Picture } from '../Pictures/furnituresPictures';
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
picture: Picture;
|
|
6
|
+
}>();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<view class="picture-wrapper">
|
|
11
|
+
<image
|
|
12
|
+
:style="{ width: '100%', aspectRatio: picture.width / picture.height }"
|
|
13
|
+
:src="picture.src"
|
|
14
|
+
/>
|
|
15
|
+
</view>
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import '../gallery.css';
|
|
2
|
+
import { createApp, defineComponent, h } from 'vue-lynx';
|
|
3
|
+
|
|
4
|
+
import ImageCard from './ImageCard.vue';
|
|
5
|
+
import { furnituresPicturesSubArray } from '../Pictures/furnituresPictures.js';
|
|
6
|
+
|
|
7
|
+
// Wrapper that displays a single image card centered on screen
|
|
8
|
+
const App = defineComponent({
|
|
9
|
+
setup() {
|
|
10
|
+
const picture = furnituresPicturesSubArray[0]!;
|
|
11
|
+
return () =>
|
|
12
|
+
h(
|
|
13
|
+
'view',
|
|
14
|
+
{ class: 'gallery-wrapper single-card' },
|
|
15
|
+
[h(ImageCard, { picture })],
|
|
16
|
+
);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const app = createApp(App);
|
|
21
|
+
app.mount();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import '../gallery.css';
|
|
2
|
+
import { createApp, defineComponent, h } from 'vue-lynx';
|
|
3
|
+
|
|
4
|
+
import LikeImageCard from '../Components/LikeImageCard.vue';
|
|
5
|
+
import { furnituresPicturesSubArray } from '../Pictures/furnituresPictures.js';
|
|
6
|
+
|
|
7
|
+
// Wrapper that displays a single like-able image card centered on screen
|
|
8
|
+
const App = defineComponent({
|
|
9
|
+
setup() {
|
|
10
|
+
const picture = furnituresPicturesSubArray[0]!;
|
|
11
|
+
return () =>
|
|
12
|
+
h(
|
|
13
|
+
'view',
|
|
14
|
+
{ class: 'gallery-wrapper single-card' },
|
|
15
|
+
[h(LikeImageCard, { picture })],
|
|
16
|
+
);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const app = createApp(App);
|
|
21
|
+
app.mount();
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import pic0 from './furnitures/0.png';
|
|
2
|
+
import pic1 from './furnitures/1.png';
|
|
3
|
+
import pic10 from './furnitures/10.png';
|
|
4
|
+
import pic11 from './furnitures/11.png';
|
|
5
|
+
import pic12 from './furnitures/12.png';
|
|
6
|
+
import pic13 from './furnitures/13.png';
|
|
7
|
+
import pic14 from './furnitures/14.png';
|
|
8
|
+
import pic2 from './furnitures/2.png';
|
|
9
|
+
import pic3 from './furnitures/3.png';
|
|
10
|
+
import pic4 from './furnitures/4.png';
|
|
11
|
+
import pic5 from './furnitures/5.png';
|
|
12
|
+
import pic6 from './furnitures/6.png';
|
|
13
|
+
import pic7 from './furnitures/7.png';
|
|
14
|
+
import pic8 from './furnitures/8.png';
|
|
15
|
+
import pic9 from './furnitures/9.png';
|
|
16
|
+
|
|
17
|
+
export interface Picture {
|
|
18
|
+
src: string;
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const furnituresPicturesSubArray: Picture[] = [
|
|
24
|
+
{ src: pic0, width: 512, height: 429 },
|
|
25
|
+
{ src: pic1, width: 511, height: 437 },
|
|
26
|
+
{ src: pic2, width: 1024, height: 1589 },
|
|
27
|
+
{ src: pic3, width: 510, height: 418 },
|
|
28
|
+
{ src: pic4, width: 509, height: 438 },
|
|
29
|
+
{ src: pic5, width: 1024, height: 1557 },
|
|
30
|
+
{ src: pic6, width: 509, height: 415 },
|
|
31
|
+
{ src: pic7, width: 509, height: 426 },
|
|
32
|
+
{ src: pic8, width: 1024, height: 1544 },
|
|
33
|
+
{ src: pic9, width: 510, height: 432 },
|
|
34
|
+
{ src: pic10, width: 1024, height: 1467 },
|
|
35
|
+
{ src: pic11, width: 1024, height: 1545 },
|
|
36
|
+
{ src: pic12, width: 512, height: 416 },
|
|
37
|
+
{ src: pic13, width: 1024, height: 1509 },
|
|
38
|
+
{ src: pic14, width: 512, height: 411 },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export const furnituresPictures: Picture[] = [
|
|
42
|
+
...furnituresPicturesSubArray,
|
|
43
|
+
...furnituresPicturesSubArray,
|
|
44
|
+
...furnituresPicturesSubArray,
|
|
45
|
+
...furnituresPicturesSubArray,
|
|
46
|
+
...furnituresPicturesSubArray,
|
|
47
|
+
];
|
|
Binary file
|
|
Binary file
|
package/src/gallery.css
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Gallery CSS for Lynx
|
|
3
|
+
*
|
|
4
|
+
* Styles matching React Gallery original (lynx-examples/Gallery).
|
|
5
|
+
* Lynx constraints: no pseudo-elements, no :hover/:focus,
|
|
6
|
+
* class selectors + descendant combinators only.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* ─── Gallery Wrapper ─────────────────────────────────── */
|
|
10
|
+
|
|
11
|
+
.gallery-wrapper {
|
|
12
|
+
height: 100%;
|
|
13
|
+
background-color: black;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.single-card {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ─── Scrollbar ───────────────────────────────────────── */
|
|
23
|
+
|
|
24
|
+
.scrollbar {
|
|
25
|
+
position: absolute;
|
|
26
|
+
right: 7px;
|
|
27
|
+
z-index: 1000;
|
|
28
|
+
width: 4px;
|
|
29
|
+
background: linear-gradient(to bottom, #ff6448, #ccddff, #3deae7);
|
|
30
|
+
border-radius: 5px;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
box-shadow:
|
|
33
|
+
0px 0px 4px 1px rgba(12, 205, 223, 0.4),
|
|
34
|
+
0px 0px 16px 5px rgba(12, 205, 223, 0.5);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.scrollbar-effect {
|
|
38
|
+
width: 100%;
|
|
39
|
+
height: 80%;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.glow {
|
|
43
|
+
background-color: #333;
|
|
44
|
+
border-radius: 4px;
|
|
45
|
+
background: linear-gradient(
|
|
46
|
+
45deg,
|
|
47
|
+
rgba(255, 255, 255, 0) 20%,
|
|
48
|
+
rgba(255, 255, 255, 0.8) 50%,
|
|
49
|
+
rgba(255, 255, 255, 0) 80%
|
|
50
|
+
);
|
|
51
|
+
animation: flow 3s linear infinite;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@keyframes flow {
|
|
55
|
+
0% {
|
|
56
|
+
transform: translateY(-100%);
|
|
57
|
+
}
|
|
58
|
+
100% {
|
|
59
|
+
transform: translateY(100%);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ─── List ────────────────────────────────────────────── */
|
|
64
|
+
|
|
65
|
+
.list {
|
|
66
|
+
width: 100%;
|
|
67
|
+
padding-bottom: 20px;
|
|
68
|
+
padding-left: 20px;
|
|
69
|
+
padding-right: 20px;
|
|
70
|
+
height: calc(100% - 48px);
|
|
71
|
+
list-main-axis-gap: 10px;
|
|
72
|
+
list-cross-axis-gap: 10px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ─── Image Card ──────────────────────────────────────── */
|
|
76
|
+
|
|
77
|
+
.picture-wrapper {
|
|
78
|
+
border-radius: 10px;
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
width: 100%;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* ─── Like Icon ───────────────────────────────────────── */
|
|
84
|
+
|
|
85
|
+
.like-icon {
|
|
86
|
+
position: absolute;
|
|
87
|
+
display: flex;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
align-items: center;
|
|
90
|
+
top: 0px;
|
|
91
|
+
right: 0px;
|
|
92
|
+
width: 48px;
|
|
93
|
+
height: 48px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.heart-love {
|
|
97
|
+
width: 16px;
|
|
98
|
+
height: 16px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ─── Ripple Animation ────────────────────────────────── */
|
|
102
|
+
|
|
103
|
+
.circle {
|
|
104
|
+
position: absolute;
|
|
105
|
+
top: calc(50% - 8px);
|
|
106
|
+
left: calc(50% - 8px);
|
|
107
|
+
height: 16px;
|
|
108
|
+
width: 16px;
|
|
109
|
+
border: 2px solid red;
|
|
110
|
+
border-radius: 50%;
|
|
111
|
+
transform: scale(0);
|
|
112
|
+
opacity: 1;
|
|
113
|
+
animation: ripple 1s 1 ease-out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.circleAfter {
|
|
117
|
+
animation-delay: 0.5s;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@keyframes ripple {
|
|
121
|
+
0% {
|
|
122
|
+
transform: scale(1);
|
|
123
|
+
opacity: 1;
|
|
124
|
+
}
|
|
125
|
+
100% {
|
|
126
|
+
transform: scale(2);
|
|
127
|
+
opacity: 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const SystemInfo: { pixelWidth: number; pixelRatio: number };
|
|
2
|
+
|
|
3
|
+
export const calculateEstimatedSize = (
|
|
4
|
+
pictureWidth: number,
|
|
5
|
+
pictureHeight: number,
|
|
6
|
+
): number => {
|
|
7
|
+
const galleryPadding = 20;
|
|
8
|
+
const galleryMainAxisGap = 10;
|
|
9
|
+
const gallerySpanCount = 2;
|
|
10
|
+
const galleryWidth = SystemInfo.pixelWidth / SystemInfo.pixelRatio;
|
|
11
|
+
const itemWidth = (galleryWidth - galleryPadding * 2 - galleryMainAxisGap)
|
|
12
|
+
/ gallerySpanCount;
|
|
13
|
+
return (itemWidth / pictureWidth) * pictureHeight;
|
|
14
|
+
};
|