@egjs/vue3-flicking 4.14.1 → 4.16.0-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.
Files changed (40) hide show
  1. package/LICENSE +19 -0
  2. package/declaration/FlickingProps.d.ts +1 -1
  3. package/declaration/VuePanel.d.ts +1 -1
  4. package/declaration/VueRenderer.d.ts +1 -1
  5. package/declaration/types.d.ts +3 -3
  6. package/dev/archive/App.vue +156 -0
  7. package/dev/archive/BasicDemo.vue +171 -0
  8. package/dev/archive/MainApp.vue +73 -0
  9. package/dev/archive/ReactiveDemo.vue +120 -0
  10. package/dev/archive/components/Test.vue +3 -0
  11. package/dev/archive/components/Test2.vue +3 -0
  12. package/dev/archive/demo-common.css +208 -0
  13. package/dev/archive/main.ts +15 -0
  14. package/dev/archive/router.ts +29 -0
  15. package/dev/basic-sample/App.vue +32 -0
  16. package/dev/basic-sample/index.html +15 -0
  17. package/dev/basic-sample/main.ts +13 -0
  18. package/dev/index.html +18 -0
  19. package/dev/plugin-check/App.vue +245 -0
  20. package/dev/plugin-check/index.html +15 -0
  21. package/dev/plugin-check/main.ts +13 -0
  22. package/dev/scratch/App.vue +32 -0
  23. package/dev/scratch/index.html +15 -0
  24. package/dev/scratch/main.ts +13 -0
  25. package/dev/vite-env.d.ts +9 -0
  26. package/dist/flicking.cjs.js +446 -542
  27. package/dist/flicking.cjs.js.map +1 -1
  28. package/dist/flicking.esm.js +450 -541
  29. package/dist/flicking.esm.js.map +1 -1
  30. package/package.json +16 -22
  31. package/src/Flicking.ts +55 -62
  32. package/src/FlickingProps.ts +3 -2
  33. package/src/VueElementProvider.ts +3 -1
  34. package/src/VueRenderer.ts +3 -8
  35. package/src/reactive.ts +1 -2
  36. package/src/types.ts +27 -30
  37. package/vite.config.ts +34 -0
  38. package/vite.dev.config.ts +49 -0
  39. package/public/favicon.ico +0 -0
  40. package/public/index.html +0 -18
@@ -0,0 +1,208 @@
1
+ /* 공통 데모 스타일 */
2
+
3
+ /* 기본 레이아웃 */
4
+ .demo-container {
5
+ max-width: 1200px;
6
+ margin: 0 auto;
7
+ padding: 40px 20px;
8
+ font-family: Avenir, Helvetica, Arial, sans-serif;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ }
12
+
13
+ /* 타이포그래피 */
14
+ h1 {
15
+ color: #333;
16
+ margin: 40px 0 20px;
17
+ font-size: 24px;
18
+ font-weight: 600;
19
+ }
20
+
21
+ h1:first-child {
22
+ margin-top: 0;
23
+ }
24
+
25
+ h2 {
26
+ color: #333;
27
+ text-align: center;
28
+ margin-bottom: 30px;
29
+ font-size: 28px;
30
+ }
31
+
32
+ h3 {
33
+ color: #666;
34
+ margin-bottom: 15px;
35
+ font-size: 20px;
36
+ }
37
+
38
+ /* 섹션 */
39
+ .section {
40
+ margin-bottom: 30px;
41
+ }
42
+
43
+ /* 패널 스타일 */
44
+ .panel {
45
+ width: 200px;
46
+ height: 200px;
47
+ margin-right: 20px;
48
+ display: inline-flex;
49
+ justify-content: center;
50
+ align-items: center;
51
+ font-size: 48px;
52
+ font-weight: bold;
53
+ color: white;
54
+ border-radius: 8px;
55
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
56
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
57
+ }
58
+
59
+ .panel:nth-child(2) {
60
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
61
+ }
62
+
63
+ .panel:nth-child(3) {
64
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
65
+ }
66
+
67
+ .panel:nth-child(4) {
68
+ background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
69
+ }
70
+
71
+ .panel:nth-child(5) {
72
+ background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%);
73
+ }
74
+
75
+ .panel:nth-child(6) {
76
+ background: linear-gradient(135deg, #fa8bff 0%, #2bd2ff 100%);
77
+ }
78
+
79
+ .panel:nth-child(7) {
80
+ background: linear-gradient(135deg, #ff6b6b 0%, #ffa502 100%);
81
+ }
82
+
83
+ .panel:nth-child(n + 8) {
84
+ background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
85
+ }
86
+
87
+ /* 컨트롤 버튼 */
88
+ .controls {
89
+ display: flex;
90
+ gap: 10px;
91
+ justify-content: center;
92
+ margin: 20px 0;
93
+ flex-wrap: wrap;
94
+ }
95
+
96
+ .button,
97
+ .btn,
98
+ button {
99
+ padding: 10px 20px;
100
+ background-color: #007bff;
101
+ color: white;
102
+ border: none;
103
+ border-radius: 5px;
104
+ cursor: pointer;
105
+ font-size: 14px;
106
+ transition: background-color 0.3s;
107
+ }
108
+
109
+ .button:hover,
110
+ .btn:hover:not(:disabled),
111
+ button:hover:not(:disabled) {
112
+ background-color: #0056b3;
113
+ }
114
+
115
+ .button:active,
116
+ .btn:active:not(:disabled),
117
+ button:active:not(:disabled) {
118
+ transform: translateY(1px);
119
+ }
120
+
121
+ .btn:disabled,
122
+ button:disabled {
123
+ background-color: #ccc;
124
+ cursor: not-allowed;
125
+ }
126
+
127
+ /* 상태 표시 */
128
+ .status {
129
+ background-color: #f8f9fa;
130
+ padding: 15px;
131
+ border-radius: 5px;
132
+ margin: 20px 0;
133
+ text-align: center;
134
+ }
135
+
136
+ .status p {
137
+ margin: 5px 0;
138
+ color: #666;
139
+ }
140
+
141
+ /* 폼 요소 */
142
+ label {
143
+ display: inline-block;
144
+ margin: 10px 20px 10px 0;
145
+ cursor: pointer;
146
+ }
147
+
148
+ input[type="checkbox"] {
149
+ margin-right: 5px;
150
+ }
151
+
152
+ /* 페이지네이션 */
153
+ .pagination {
154
+ display: flex;
155
+ gap: 10px;
156
+ justify-content: center;
157
+ margin: 20px 0;
158
+ flex-wrap: wrap;
159
+ }
160
+
161
+ .pagination-btn {
162
+ padding: 10px 20px;
163
+ background-color: #007bff;
164
+ color: white;
165
+ border: none;
166
+ border-radius: 5px;
167
+ cursor: pointer;
168
+ font-size: 14px;
169
+ transition: background-color 0.3s;
170
+ }
171
+
172
+ .pagination-btn:hover {
173
+ background-color: #0056b3;
174
+ }
175
+
176
+ .pagination-btn:active {
177
+ transform: translateY(1px);
178
+ }
179
+
180
+ .pagination-btn.active {
181
+ background-color: #28a745;
182
+ }
183
+
184
+ /* 프로그레스 바 */
185
+ .progress-container {
186
+ position: relative;
187
+ width: 100%;
188
+ height: 20px;
189
+ background: #f0f0f0;
190
+ border-radius: 10px;
191
+ overflow: hidden;
192
+ margin: 20px 0;
193
+ }
194
+
195
+ .progress-bar {
196
+ height: 100%;
197
+ background: linear-gradient(90deg, #007bff, #28a745);
198
+ transition: width 0.3s ease;
199
+ border-radius: 10px;
200
+ }
201
+
202
+ .progress-text {
203
+ text-align: center;
204
+ margin-top: 10px;
205
+ font-size: 14px;
206
+ color: #666;
207
+ font-weight: bold;
208
+ }
@@ -0,0 +1,15 @@
1
+ import { createApp } from "vue";
2
+ import MainApp from "./MainApp.vue";
3
+ import router from "./router";
4
+
5
+ // CSS imports
6
+ import "@dev/flicking-css";
7
+ import "@dev/plugins-css";
8
+
9
+ // @ts-expect-error - injected by vite
10
+ const buildMode = __DEV__ ? "source" : "build";
11
+ console.log(`🔧 Vue3 Flicking Dev - ${buildMode} 모드`);
12
+
13
+ const app = createApp(MainApp);
14
+ app.use(router);
15
+ app.mount("#app");
@@ -0,0 +1,29 @@
1
+ import { createRouter, createWebHistory } from "vue-router";
2
+ import App from "./App.vue";
3
+ import BasicDemo from "./BasicDemo.vue";
4
+ import ReactiveDemo from "./ReactiveDemo.vue";
5
+
6
+ const routes = [
7
+ {
8
+ path: "/",
9
+ name: "Home",
10
+ component: App
11
+ },
12
+ {
13
+ path: "/basic",
14
+ name: "BasicDemo",
15
+ component: BasicDemo
16
+ },
17
+ {
18
+ path: "/reactive",
19
+ name: "ReactiveDemo",
20
+ component: ReactiveDemo
21
+ }
22
+ ];
23
+
24
+ const router = createRouter({
25
+ history: createWebHistory(),
26
+ routes
27
+ });
28
+
29
+ export default router;
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <div :style="css.container">
3
+ <h1>Basic Sample</h1>
4
+ <Flicking :options="{ align: 'prev', circular: true }">
5
+ <div v-for="n in 5" :key="n" :style="css.panel">{{ n }}</div>
6
+ </Flicking>
7
+ </div>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import Flicking from "@dev/vue3-flicking";
12
+
13
+ const css = {
14
+ container: {
15
+ maxWidth: "800px",
16
+ margin: "0 auto",
17
+ padding: "20px"
18
+ },
19
+ panel: {
20
+ minWidth: "200px",
21
+ height: "200px",
22
+ margin: "0 5px",
23
+ background: "#e0e7ff",
24
+ borderRadius: "8px",
25
+ display: "flex",
26
+ alignItems: "center",
27
+ justifyContent: "center",
28
+ fontSize: "24px",
29
+ fontWeight: "bold"
30
+ }
31
+ };
32
+ </script>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Basic Sample - Vue3 Flicking</title>
7
+ <style>
8
+ body { margin: 0; padding: 20px; font-family: sans-serif; }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div id="app"></div>
13
+ <script type="module" src="./main.ts"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Basic Sample - 기본 동작 확인용
3
+ *
4
+ * http://localhost:3002/basic-sample/
5
+ *
6
+ * 이 파일은 수정하지 마세요.
7
+ * 샘플 코드는 App.vue에 작성합니다.
8
+ */
9
+ import { createApp } from "vue";
10
+ import "@dev/flicking-css";
11
+ import App from "./App.vue";
12
+
13
+ createApp(App).mount("#app");
package/dev/index.html ADDED
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Vue3 Flicking - Dev</title>
7
+ <style>
8
+ body { margin: 0; padding: 40px; font-family: sans-serif; }
9
+ a { display: block; margin: 8px 0; font-size: 18px; }
10
+ </style>
11
+ </head>
12
+ <body>
13
+ <h1>Vue3 Flicking Dev</h1>
14
+ <a href="/basic-sample/">Basic Sample</a>
15
+ <a href="/plugin-check/">Plugin Check (마이그레이션 검증용)</a>
16
+ <a href="/scratch/">Scratch (이슈 재현)</a>
17
+ </body>
18
+ </html>
@@ -0,0 +1,245 @@
1
+ <!--
2
+ 플러그인 마이그레이션 검증용 (임시)
3
+ docs 데모 추가 후 제거 예정
4
+
5
+ 참고: https://naver.github.io/egjs-flicking/ko/Plugins
6
+ -->
7
+ <template>
8
+ <div :style="{ maxWidth: '640px', margin: '0 auto', padding: '20px' }">
9
+ <h1>Plugin Check</h1>
10
+ <p :style="css.note">마이그레이션 검증용 — docs 데모 추가 후 제거 예정</p>
11
+
12
+ <!-- Arrow -->
13
+ <section :style="css.section">
14
+ <div :style="css.title">Arrow</div>
15
+ <Flicking :options="{ circular: true }" :plugins="arrowPlugins">
16
+ <div v-for="n in 5" :key="n" :style="css.panel">{{ n }}</div>
17
+ <template #viewport>
18
+ <span class="flicking-arrow-prev"></span>
19
+ <span class="flicking-arrow-next"></span>
20
+ </template>
21
+ </Flicking>
22
+ </section>
23
+
24
+ <!-- AutoPlay -->
25
+ <section :style="css.section">
26
+ <div :style="css.title">AutoPlay</div>
27
+ <Flicking :options="{ circular: true, preventDefaultOnDrag: true }" :plugins="autoPlayPlugins">
28
+ <div v-for="(src, i) in images.slice(0, 3)" :key="i" :style="css.pluginsPanel">
29
+ <img :style="css.panelImage" :src="src" />
30
+ </div>
31
+ </Flicking>
32
+ </section>
33
+
34
+ <!-- Pagination -->
35
+ <section :style="css.section">
36
+ <div :style="css.title">Pagination (bullet)</div>
37
+ <Flicking :options="{ circular: true }" :plugins="paginationPlugins">
38
+ <div v-for="n in 8" :key="n" :style="css.panel">{{ n }}</div>
39
+ <template #viewport>
40
+ <div class="flicking-pagination"></div>
41
+ </template>
42
+ </Flicking>
43
+ </section>
44
+
45
+ <!-- Fade -->
46
+ <section :style="css.section">
47
+ <div :style="css.title">Fade</div>
48
+ <Flicking :options="{ circular: true, preventDefaultOnDrag: true }" :plugins="fadePlugins">
49
+ <div v-for="(src, i) in images.slice(0, 3)" :key="i" :style="css.pluginsPanel">
50
+ <img :style="css.panelImage" :src="src" />
51
+ </div>
52
+ </Flicking>
53
+ </section>
54
+
55
+ <!-- Parallax -->
56
+ <section :style="css.section">
57
+ <div :style="css.title">Parallax</div>
58
+ <Flicking :options="{ circular: true, preventDefaultOnDrag: true, gap: 2 }" :plugins="parallaxPlugins">
59
+ <div v-for="(src, i) in images.slice(0, 3)" :key="i" :style="{ ...css.pluginsPanel, width: '100%' }">
60
+ <img :style="{ ...css.panelImage, width: '150%', maxWidth: 'none' }" :src="src" />
61
+ </div>
62
+ </Flicking>
63
+ </section>
64
+
65
+ <!-- Perspective -->
66
+ <section :style="css.section">
67
+ <div :style="css.title">Perspective</div>
68
+ <Flicking :options="{ circular: true }" :plugins="perspectivePlugins">
69
+ <div v-for="n in 5" :key="n" :style="css.panel">{{ n }}</div>
70
+ </Flicking>
71
+ </section>
72
+
73
+ <!-- Sync (camera) -->
74
+ <section :style="css.section">
75
+ <div :style="css.title">Sync (camera)</div>
76
+ <Flicking ref="syncCam0" :options="{ align: 'prev', bound: true, bounce: 30 }" :plugins="syncCameraPlugins">
77
+ <span v-for="item in fruits" :key="item" :style="css.syncItem">{{ item }}</span>
78
+ </Flicking>
79
+ <div style="margin-top: 4px;">
80
+ <Flicking ref="syncCam1" :options="{ align: 'prev', bound: true, bounce: 30 }">
81
+ <span v-for="item in foods" :key="item" :style="css.syncItem">{{ item }}</span>
82
+ </Flicking>
83
+ </div>
84
+ <div style="margin-top: 4px;">
85
+ <Flicking ref="syncCam2" :options="{ align: 'prev', bound: true, bounce: 30 }">
86
+ <span v-for="item in drinks" :key="item" :style="css.syncItem">{{ item }}</span>
87
+ </Flicking>
88
+ </div>
89
+ </section>
90
+
91
+ <!-- Sync (index + thumbnail) -->
92
+ <section :style="css.section">
93
+ <div :style="css.title">Sync (index + thumbnail)</div>
94
+ <Flicking ref="syncMain" :options="{ bounce: 30, preventDefaultOnDrag: true }" :plugins="syncIndexPlugins">
95
+ <div v-for="(src, i) in images" :key="i" :style="css.pluginsPanel">
96
+ <img :style="css.panelImage" :src="src" />
97
+ </div>
98
+ </Flicking>
99
+ <div style="margin-top: 8px;">
100
+ <Flicking ref="syncThumb" :options="{ moveType: 'freeScroll', bound: true, bounce: 30, preventDefaultOnDrag: true }">
101
+ <div v-for="(src, i) in images" :key="i" :style="css.thumbPanel">
102
+ <img :style="css.thumbImage" :src="src" />
103
+ </div>
104
+ </Flicking>
105
+ </div>
106
+ </section>
107
+ </div>
108
+ </template>
109
+
110
+ <script setup lang="ts">
111
+ import { Arrow, AutoPlay, Fade, Pagination, Parallax, Perspective, Sync } from "@dev/plugins";
112
+ import Flicking from "@dev/vue3-flicking";
113
+ import { onMounted, ref } from "vue";
114
+
115
+ const css = {
116
+ section: { marginBottom: "48px" },
117
+ title: {
118
+ fontSize: "18px",
119
+ fontWeight: "bold",
120
+ marginBottom: "12px",
121
+ borderBottom: "2px solid #333",
122
+ paddingBottom: "4px"
123
+ },
124
+ note: { fontSize: "12px", color: "#666", marginTop: "8px" },
125
+ panel: {
126
+ minWidth: "200px",
127
+ height: "160px",
128
+ margin: "0 5px",
129
+ background: "#e0e7ff",
130
+ borderRadius: "8px",
131
+ display: "flex",
132
+ alignItems: "center",
133
+ justifyContent: "center",
134
+ fontSize: "24px",
135
+ fontWeight: "bold",
136
+ overflow: "hidden"
137
+ },
138
+ pluginsPanel: { position: "relative" as const, width: "100%", height: "200px", overflow: "hidden" },
139
+ panelImage: { width: "100%", height: "100%", objectFit: "cover" as const },
140
+ thumbPanel: {
141
+ width: "100px",
142
+ height: "70px",
143
+ margin: "0 2px",
144
+ overflow: "hidden",
145
+ opacity: "0.5",
146
+ transition: "opacity 0.3s"
147
+ },
148
+ thumbImage: { width: "100%", height: "100%", objectFit: "cover" as const },
149
+ syncItem: {
150
+ display: "inline-block",
151
+ padding: "8px 16px",
152
+ margin: "0 4px",
153
+ background: "#f5f5f5",
154
+ borderRadius: "4px",
155
+ whiteSpace: "nowrap"
156
+ }
157
+ };
158
+
159
+ const images = [
160
+ "https://picsum.photos/seed/a/600/300",
161
+ "https://picsum.photos/seed/b/600/300",
162
+ "https://picsum.photos/seed/c/600/300",
163
+ "https://picsum.photos/seed/d/600/300",
164
+ "https://picsum.photos/seed/e/600/300",
165
+ "https://picsum.photos/seed/f/600/300"
166
+ ];
167
+
168
+ const fruits = [
169
+ "🍎 Apple",
170
+ "🍉 Watermelon",
171
+ "🥝 Kiwi",
172
+ "🍊 Orange",
173
+ "🍇 Grape",
174
+ "🍓 Strawberry",
175
+ "🍑 Peach",
176
+ "🍋 Lemon",
177
+ "🫐 Blueberry",
178
+ "🍌 Banana"
179
+ ];
180
+ const foods = [
181
+ "🍔 Hamburger",
182
+ "🍕 Pizza",
183
+ "🍞 Bread",
184
+ "🌮 Taco",
185
+ "🍜 Ramen",
186
+ "🍣 Sushi",
187
+ "🥗 Salad",
188
+ "🍝 Pasta",
189
+ "🥘 Stew",
190
+ "🍱 Bento"
191
+ ];
192
+ const drinks = [
193
+ "🥛 Milk",
194
+ "☕ Coffee",
195
+ "🍵 Green tea",
196
+ "🧃 Juice",
197
+ "🥤 Soda",
198
+ "🍺 Beer",
199
+ "🧋 Bubble tea",
200
+ "🍷 Wine",
201
+ "🥥 Coconut",
202
+ "🍶 Sake"
203
+ ];
204
+
205
+ // Simple plugins (no ref dependency)
206
+ const arrowPlugins = [new Arrow()];
207
+ const autoPlayPlugins = [new AutoPlay()];
208
+ const paginationPlugins = [new Pagination({ type: "bullet" })];
209
+ const fadePlugins = [new Fade()];
210
+ const parallaxPlugins = [new Parallax("img")];
211
+ const perspectivePlugins = [new Perspective({ rotate: 1, scale: 2, perspective: 600 })];
212
+
213
+ // Sync plugins (need refs)
214
+ const syncCam0 = ref<InstanceType<typeof Flicking> | null>(null);
215
+ const syncCam1 = ref<InstanceType<typeof Flicking> | null>(null);
216
+ const syncCam2 = ref<InstanceType<typeof Flicking> | null>(null);
217
+ const syncCameraPlugins = ref<Sync[]>([]);
218
+
219
+ const syncMain = ref<InstanceType<typeof Flicking> | null>(null);
220
+ const syncThumb = ref<InstanceType<typeof Flicking> | null>(null);
221
+ const syncIndexPlugins = ref<Sync[]>([]);
222
+
223
+ onMounted(() => {
224
+ syncCameraPlugins.value = [
225
+ new Sync({
226
+ type: "camera",
227
+ synchronizedFlickingOptions: [
228
+ { flicking: syncCam0.value!, isClickable: false },
229
+ { flicking: syncCam1.value!, isClickable: false },
230
+ { flicking: syncCam2.value!, isClickable: false }
231
+ ]
232
+ })
233
+ ];
234
+
235
+ syncIndexPlugins.value = [
236
+ new Sync({
237
+ type: "index",
238
+ synchronizedFlickingOptions: [
239
+ { flicking: syncMain.value!, isSlidable: true },
240
+ { flicking: syncThumb.value!, isClickable: true, activeClass: "active" }
241
+ ]
242
+ })
243
+ ];
244
+ });
245
+ </script>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Plugin Check - Vue3 Flicking</title>
7
+ <style>
8
+ body { margin: 0; padding: 20px; font-family: sans-serif; }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div id="app"></div>
13
+ <script type="module" src="./main.ts"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Plugin Check - 플러그인 마이그레이션 검증용 (임시)
3
+ *
4
+ * http://localhost:3002/plugin-check/
5
+ *
6
+ * 이 파일은 수정하지 마세요.
7
+ */
8
+ import { createApp } from "vue";
9
+ import "@dev/flicking-css";
10
+ import "@dev/plugins-css";
11
+ import App from "./App.vue";
12
+
13
+ createApp(App).mount("#app");
@@ -0,0 +1,32 @@
1
+ <!--
2
+ 이슈 재현 템플릿
3
+
4
+ 이 파일을 덮어써서 이슈를 재현하세요.
5
+ -->
6
+ <template>
7
+ <div>
8
+ <h2>Scratch</h2>
9
+ <Flicking :options="{ align: 'prev', circular: true }">
10
+ <div v-for="n in 3" :key="n" :style="css.panel">{{ n }}</div>
11
+ </Flicking>
12
+ </div>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import Flicking from "@dev/vue3-flicking";
17
+
18
+ const css = {
19
+ panel: {
20
+ minWidth: "200px",
21
+ height: "200px",
22
+ margin: "0 5px",
23
+ background: "#f0f0f0",
24
+ borderRadius: "8px",
25
+ display: "flex",
26
+ alignItems: "center",
27
+ justifyContent: "center",
28
+ fontSize: "24px",
29
+ fontWeight: "bold"
30
+ }
31
+ };
32
+ </script>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Scratch - Vue3 Flicking</title>
7
+ <style>
8
+ body { margin: 0; padding: 20px; font-family: sans-serif; }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div id="app"></div>
13
+ <script type="module" src="./main.ts"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Scratch - 이슈 재현용 독립 페이지
3
+ *
4
+ * http://localhost:3002/scratch/
5
+ *
6
+ * 이 파일은 수정하지 마세요.
7
+ * 재현 코드는 App.vue에 작성합니다.
8
+ */
9
+ import { createApp } from "vue";
10
+ import "@dev/flicking-css";
11
+ import App from "./App.vue";
12
+
13
+ createApp(App).mount("#app");
@@ -0,0 +1,9 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare const __DEV__: boolean;
4
+
5
+ declare module "*.vue" {
6
+ import type { DefineComponent } from "vue";
7
+ const component: DefineComponent<{}, {}, any>;
8
+ export default component;
9
+ }