@egjs/vue3-flicking 4.16.0-beta.1 → 4.16.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egjs/vue3-flicking",
3
- "version": "4.16.0-beta.1",
3
+ "version": "4.16.0",
4
4
  "description": "Everyday 30 million people experience. It's reliable, flexible and extendable carousel.",
5
5
  "main": "dist/flicking.cjs.js",
6
6
  "module": "dist/flicking.esm.js",
@@ -26,7 +26,7 @@
26
26
  "@egjs/component": "^3.0.2",
27
27
  "@egjs/list-differ": "^1.0.1",
28
28
  "vue-router": "^4.5.1",
29
- "@egjs/flicking": "~4.16.0-beta.1"
29
+ "@egjs/flicking": "~4.16.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "vue": "^3.0.0"
@@ -39,7 +39,7 @@
39
39
  "typescript": "4.8.4",
40
40
  "vite": "^7.2.6",
41
41
  "vue": "^3.2.22",
42
- "@egjs/flicking-plugins": "~4.7.1"
42
+ "@egjs/flicking-plugins": "~4.8.0"
43
43
  },
44
44
  "scripts": {
45
45
  "dev": "vite --config vite.dev.config.ts",
@@ -1,156 +0,0 @@
1
- <template>
2
- <article class="demo-container">
3
- <h1>Default Rendering</h1>
4
- <Flicking>
5
- <div class="panel">0</div>
6
- <div class="panel">1</div>
7
- <div class="panel">2</div>
8
- </Flicking>
9
- <h1>Bound</h1>
10
- <Flicking :options="{ bound: true }">
11
- <div class="panel">0</div>
12
- <div class="panel">1</div>
13
- <div class="panel">2</div>
14
- <div class="panel">3</div>
15
- <div class="panel">4</div>
16
- <div class="panel">5</div>
17
- <div class="panel">6</div>
18
- </Flicking>
19
- <h1>FreeScroll</h1>
20
- <Flicking :options="{ moveType: 'freeScroll' }">
21
- <div class="panel">0</div>
22
- <div class="panel">1</div>
23
- <div class="panel">2</div>
24
- </Flicking>
25
- <h1>List Rendering</h1>
26
- <Flicking>
27
- <Test v-for="item in list0" :key="item" />
28
- </Flicking>
29
- <h1>Adding panels</h1>
30
- <Flicking :options="{ circular: true, renderOnlyVisible: true }">
31
- <div class="panel" v-for="panel in panels" :key="panel">{{ panel }}</div>
32
- <Test />
33
- </Flicking>
34
- <div>
35
- <span class="button" @click="() => {
36
- prepend();
37
- }">Prepend</span>
38
- <span class="button" @click="() => {
39
- append();
40
- }">Append</span>
41
- </div>
42
- <h1>Method call</h1>
43
- <Flicking ref="flick" :options="{ circular: true }">
44
- <div class="panel">0</div>
45
- <div class="panel">1</div>
46
- <div class="panel">2</div>
47
- <div class="panel">3</div>
48
- <div class="panel">4</div>
49
- <div class="panel">5</div>
50
- <div class="panel">6</div>
51
- <div class="panel">7</div>
52
- <div class="panel">8</div>
53
- </Flicking>
54
- <div>
55
- <span class="button" @click="() => {
56
- prev();
57
- }">Prev</span>
58
- <span class="button" @click="() => {
59
- next();
60
- }">Next</span>
61
- </div>
62
- <Flicking :plugins="arrow">
63
- <div class="panel">0</div>
64
- <div class="panel">1</div>
65
- <div class="panel">2</div>
66
- <div class="panel">3</div>
67
- <div class="panel">4</div>
68
- <template #viewport>
69
- <span class="flicking-arrow-prev"></span>
70
- <span class="flicking-arrow-next"></span>
71
- </template>
72
- </Flicking>
73
- <Flicking :plugins="fade" :options="{ renderOnlyVisible: true }">
74
- <div class="panel">0</div>
75
- <div class="panel">1</div>
76
- <div class="panel">2</div>
77
- <div class="panel">3</div>
78
- <div class="panel">4</div>
79
- </Flicking>
80
- <Flicking class="flicking flicking0" ref="vFlick" :options="{
81
- panelsPerView: 5,
82
- circular: true,
83
- virtual: {
84
- panelClass: 'panel',
85
- renderPanel: (panel) => `Panel ${panel.index}`,
86
- initialPanelCount: 100
87
- }
88
- }"></Flicking>
89
- <button @click="this.vPrepend">Prepend</button>
90
- <button @click="this.vAppend">Append</button>
91
- <Flicking :options="{ panelsPerView: this.panelsPerView }">
92
- <div class="panel">0</div>
93
- <div class="panel">1</div>
94
- <div class="panel">2</div>
95
- <div class="panel">3</div>
96
- <div class="panel">4</div>
97
- </Flicking>
98
- <button @click="this.changeProp">Change</button>
99
- </article>
100
- </template>
101
-
102
- <script>
103
- import { Arrow, Fade } from "@dev/plugins";
104
- import Flicking from "@dev/vue3-flicking";
105
- import Test from "./components/Test.vue";
106
- import Test2 from "./components/Test2.vue";
107
-
108
- export default {
109
- components: {
110
- Flicking,
111
- Test,
112
- Test2
113
- },
114
- data() {
115
- return {
116
- panels: [0, 1, 2, 3, 4, 5, 6],
117
- list0: [0, 1, 2],
118
- arrow: [new Arrow()],
119
- fade: [new Fade()],
120
- panelsPerView: 5
121
- };
122
- },
123
- methods: {
124
- prepend() {
125
- this.panels.splice(0, 0, this.panels[0] - 2, this.panels[0] - 1);
126
- },
127
- append() {
128
- const lastEl = this.panels[this.panels.length - 1];
129
- this.panels.push(lastEl + 1, lastEl + 2);
130
- },
131
- prev() {
132
- this.$refs.flick.prev();
133
- },
134
- next() {
135
- this.$refs.flick.next();
136
- },
137
- vPrepend() {
138
- this.$refs.vFlick.virtual.prepend(100);
139
- },
140
- vAppend() {
141
- this.$refs.vFlick.virtual.append(100);
142
- },
143
- changeProp() {
144
- this.panelsPerView -= 1;
145
- }
146
- }
147
- };
148
- </script>
149
-
150
- <style>
151
- @import './demo-common.css';
152
- </style>
153
-
154
- <style scoped>
155
- /* App.vue 전용 스타일 (필요시 추가) */
156
- </style>
@@ -1,171 +0,0 @@
1
- <template>
2
- <div class="demo-container">
3
- <h2>Vue3 Composition API Flicking Demo</h2>
4
-
5
- <!-- 기본 Flicking -->
6
- <div class="section">
7
- <h3>기본 Flicking</h3>
8
- <Flicking ref="flickingRef" :options="flickingOptions">
9
- <div
10
- v-for="item in panels"
11
- :key="item.id"
12
- class="panel"
13
- :style="{ backgroundColor: item.color }"
14
- >
15
- {{ item.text }}
16
- </div>
17
- </Flicking>
18
- </div>
19
-
20
- <!-- 컨트롤 버튼들 -->
21
- <div class="controls">
22
- <button @click="addPanel" class="btn">패널 추가</button>
23
- <button @click="removePanel" class="btn">패널 제거</button>
24
- <button @click="prev" class="btn">이전</button>
25
- <button @click="next" class="btn">다음</button>
26
- <button @click="moveTo(2)" class="btn">3번 패널로 이동</button>
27
- </div>
28
-
29
- <!-- 현재 상태 표시 -->
30
- <div class="status">
31
- <p>총 패널 수: {{ panelCount }}</p>
32
- <p>현재 인덱스: {{ currentIndex }}</p>
33
- </div>
34
-
35
- <!-- 동적 옵션 변경 -->
36
- <div class="section">
37
- <h3>옵션 변경</h3>
38
- <label>
39
- <input
40
- type="checkbox"
41
- v-model="isCircular"
42
- @change="updateOptions"
43
- />
44
- circular
45
- </label>
46
- <label>
47
- <input
48
- type="checkbox"
49
- v-model="isBound"
50
- @change="updateOptions"
51
- />
52
- bound
53
- </label>
54
- </div>
55
- </div>
56
- </template>
57
-
58
- <script setup>
59
- import Flicking from "@dev/vue3-flicking";
60
- import { computed, onMounted, reactive, ref, watch } from "vue";
61
-
62
- // Flicking 인스턴스 참조
63
- const flickingRef = ref(null);
64
-
65
- // 반응형 데이터
66
- const panels = reactive([
67
- { id: 1, text: "패널 1", color: "#ff6b6b" },
68
- { id: 2, text: "패널 2", color: "#4ecdc4" },
69
- { id: 3, text: "패널 3", color: "#45b7d1" },
70
- { id: 4, text: "패널 4", color: "#96ceb4" },
71
- { id: 5, text: "패널 5", color: "#feca57" }
72
- ]);
73
-
74
- // Flicking 옵션
75
- const flickingOptions = reactive({
76
- circular: false,
77
- bound: false,
78
- duration: 500,
79
- defaultIndex: 0
80
- });
81
-
82
- // 상태 변수들
83
- const isCircular = ref(false);
84
- const isBound = ref(false);
85
- const currentIndex = ref(0);
86
-
87
- // 계산된 속성
88
- const panelCount = computed(() => panels.length);
89
-
90
- // 메서드들
91
- const addPanel = () => {
92
- const newId = Math.max(...panels.map(p => p.id)) + 1;
93
- const colors = ["#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#feca57", "#ff9ff3", "#54a0ff"];
94
- const randomColor = colors[Math.floor(Math.random() * colors.length)];
95
-
96
- panels.push({
97
- id: newId,
98
- text: `패널 ${newId}`,
99
- color: randomColor
100
- });
101
- };
102
-
103
- const removePanel = () => {
104
- if (panels.length > 1) {
105
- panels.pop();
106
- }
107
- };
108
-
109
- const prev = () => {
110
- if (flickingRef.value) {
111
- flickingRef.value.prev();
112
- }
113
- };
114
-
115
- const next = () => {
116
- if (flickingRef.value) {
117
- flickingRef.value.next();
118
- }
119
- };
120
-
121
- const moveTo = index => {
122
- if (flickingRef.value) {
123
- flickingRef.value.moveTo(index);
124
- }
125
- };
126
-
127
- const updateOptions = () => {
128
- flickingOptions.circular = isCircular.value;
129
- flickingOptions.bound = isBound.value;
130
- };
131
-
132
- // 이벤트 리스너
133
- const onChanged = e => {
134
- currentIndex.value = flickingRef.value.index;
135
- };
136
-
137
- // 라이프사이클 훅
138
- onMounted(() => {
139
- if (flickingRef.value) {
140
- // 이벤트 리스너 등록
141
- flickingRef.value.on("changed", onChanged);
142
- }
143
- });
144
-
145
- // 감시자
146
- watch(
147
- panels,
148
- newPanels => {
149
- console.log("패널이 변경되었습니다:", newPanels.length);
150
- },
151
- { deep: true }
152
- );
153
- </script>
154
-
155
- <style>
156
- @import './demo-common.css';
157
- </style>
158
-
159
- <style scoped>
160
- /* BasicDemo 전용 스타일 */
161
- .demo-container {
162
- max-width: 800px;
163
- }
164
-
165
- .panel {
166
- width: 200px;
167
- height: 150px;
168
- margin-right: 10px;
169
- font-size: 18px;
170
- }
171
- </style>
@@ -1,73 +0,0 @@
1
- <template>
2
- <div class="main-app">
3
- <header class="header">
4
- <h1>Vue3 Flicking Demo</h1>
5
- <nav class="navigation">
6
- <router-link to="/" class="nav-link">Home</router-link>
7
- <router-link to="/basic" class="nav-link">BasicDemo</router-link>
8
- <router-link to="/reactive" class="nav-link">ReactiveDemo</router-link>
9
- </nav>
10
- </header>
11
-
12
- <main class="content">
13
- <router-view></router-view>
14
- </main>
15
- </div>
16
- </template>
17
-
18
- <script setup>
19
- // Composition API setup
20
- </script>
21
-
22
- <style scoped>
23
- .main-app {
24
- font-family: Avenir, Helvetica, Arial, sans-serif;
25
- -webkit-font-smoothing: antialiased;
26
- -moz-osx-font-smoothing: grayscale;
27
- color: #2c3e50;
28
- max-width: 1200px;
29
- margin: 0 auto;
30
- padding: 20px;
31
- }
32
-
33
- .header {
34
- text-align: center;
35
- margin-bottom: 40px;
36
- padding-bottom: 20px;
37
- border-bottom: 2px solid #eee;
38
- }
39
-
40
- .header h1 {
41
- margin-bottom: 20px;
42
- color: #333;
43
- }
44
-
45
- .navigation {
46
- display: flex;
47
- justify-content: center;
48
- gap: 20px;
49
- flex-wrap: wrap;
50
- }
51
-
52
- .nav-link {
53
- padding: 10px 20px;
54
- background-color: #007bff;
55
- color: white;
56
- text-decoration: none;
57
- border-radius: 5px;
58
- transition: background-color 0.3s;
59
- font-weight: bold;
60
- }
61
-
62
- .nav-link:hover {
63
- background-color: #0056b3;
64
- }
65
-
66
- .nav-link.router-link-active {
67
- background-color: #28a745;
68
- }
69
-
70
- .content {
71
- min-height: 500px;
72
- }
73
- </style>
@@ -1,120 +0,0 @@
1
- <template>
2
- <div class="demo-container">
3
- <h2>Reactive API - Pagination Demo</h2>
4
-
5
- <div class="section">
6
- <h3>Pagination with Reactive API</h3>
7
- <Flicking ref="flickingRef" :options="flickingOptions">
8
- <div
9
- v-for="item in panels"
10
- :key="item.id"
11
- class="panel"
12
- :style="{ backgroundColor: item.color }"
13
- >
14
- {{ item.text }}
15
- </div>
16
- </Flicking>
17
- </div>
18
-
19
- <div class="progress-container">
20
- <div class="progress-bar" :style="{ width: progress + '%' }"></div>
21
- <div class="progress-text">Progress: {{ progress.toFixed(1) }}%</div>
22
- </div>
23
-
24
- <div class="controls">
25
- <button @click="handlePrev" :disabled="isReachStart" class="btn">
26
- 이전
27
- </button>
28
- <button @click="handleNext" :disabled="isReachEnd" class="btn">
29
- 다음
30
- </button>
31
- </div>
32
-
33
- <div class="pagination">
34
- <button
35
- v-for="page in totalPanelCount"
36
- :key="page"
37
- :class="{ active: currentPanelIndex + 1 === page }"
38
- @click="moveTo(page - 1)"
39
- class="pagination-btn"
40
- >
41
- {{ page }}
42
- </button>
43
- </div>
44
-
45
- <div class="status">
46
- <p>총 패널 수: {{ totalPanelCount }}</p>
47
- <p>현재 인덱스: {{ currentPanelIndex }}</p>
48
- <p>진행률: {{ progress.toFixed(1) }}%</p>
49
- <p>첫 번째 패널: {{ isReachStart ? '도달' : '미도달' }}</p>
50
- <p>마지막 패널: {{ isReachEnd ? '도달' : '미도달' }}</p>
51
- </div>
52
- </div>
53
- </template>
54
-
55
- <script setup>
56
- import Flicking, { useFlickingReactiveAPI } from "@dev/vue3-flicking";
57
- import { onMounted, reactive, ref } from "vue";
58
-
59
- // Flicking 인스턴스 참조
60
- const flickingRef = ref(null);
61
-
62
- // 반응형 데이터
63
- const panels = reactive([
64
- { id: 1, text: "패널 1", color: "#ff6b6b" },
65
- { id: 2, text: "패널 2", color: "#4ecdc4" },
66
- { id: 3, text: "패널 3", color: "#45b7d1" },
67
- { id: 4, text: "패널 4", color: "#96ceb4" },
68
- { id: 5, text: "패널 5", color: "#feca57" }
69
- ]);
70
-
71
- // Flicking 옵션
72
- const flickingOptions = reactive({
73
- circular: false,
74
- bound: false,
75
- duration: 500,
76
- defaultIndex: 0
77
- });
78
-
79
- // Reactive API 훅 사용
80
- const { currentPanelIndex, totalPanelCount, isReachStart, isReachEnd, progress, moveTo } =
81
- useFlickingReactiveAPI(flickingRef);
82
-
83
- // 메서드들
84
- const handlePrev = () => {
85
- if (!isReachStart.value) {
86
- moveTo(currentPanelIndex.value - 1);
87
- }
88
- };
89
-
90
- const handleNext = () => {
91
- if (!isReachEnd.value) {
92
- moveTo(currentPanelIndex.value + 1);
93
- }
94
- };
95
-
96
- // 라이프사이클 훅
97
- onMounted(() => {
98
- if (flickingRef.value) {
99
- console.log("Flicking 인스턴스가 마운트되었습니다");
100
- }
101
- });
102
- </script>
103
-
104
- <style>
105
- @import './demo-common.css';
106
- </style>
107
-
108
- <style scoped>
109
- /* ReactiveDemo 전용 스타일 */
110
- .demo-container {
111
- max-width: 800px;
112
- }
113
-
114
- .panel {
115
- width: 200px;
116
- height: 150px;
117
- margin-right: 10px;
118
- font-size: 18px;
119
- }
120
- </style>
@@ -1,3 +0,0 @@
1
- <template>
2
- <div class="panel">TEST Component</div>
3
- </template>
@@ -1,3 +0,0 @@
1
- <template>
2
- <div class="panel">TEST-2</div>
3
- </template>
@@ -1,208 +0,0 @@
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
- }
@@ -1,15 +0,0 @@
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");
@@ -1,29 +0,0 @@
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;
@@ -1,32 +0,0 @@
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>
@@ -1,15 +0,0 @@
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>
@@ -1,13 +0,0 @@
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 DELETED
@@ -1,18 +0,0 @@
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>
@@ -1,245 +0,0 @@
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>
@@ -1,15 +0,0 @@
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>
@@ -1,13 +0,0 @@
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");
@@ -1,32 +0,0 @@
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>
@@ -1,15 +0,0 @@
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>
@@ -1,13 +0,0 @@
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");
package/dev/vite-env.d.ts DELETED
@@ -1,9 +0,0 @@
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
- }
package/vite.config.ts DELETED
@@ -1,34 +0,0 @@
1
- import { createViteConfig } from "../../config/vite-build-helper";
2
- // @ts-expect-error: resolveJsonModule issue in build environment
3
- import pkg from "./package.json";
4
-
5
- const name = "VueFlicking";
6
- const external = {
7
- vue: "Vue",
8
- "vue-class-component": "VueClassComponent",
9
- "@egjs/flicking": "Flicking",
10
- "@egjs/list-differ": "eg.ListDiffer",
11
- "@egjs/axes": "eg.Axes",
12
- "@egjs/component": "eg.Component"
13
- };
14
-
15
- // Determine build target based on environment variable
16
- // usage: VITE_BUILD_FORMAT=cjs vite build
17
- const buildFormat = process.env.VITE_BUILD_FORMAT || "esm";
18
-
19
- let input = "src/index.ts";
20
- let formats: any[] = ["es"];
21
-
22
- if (buildFormat === "cjs") {
23
- input = "src/index.umd.ts";
24
- formats = ["cjs"];
25
- }
26
-
27
- export default createViteConfig({
28
- input,
29
- name,
30
- packageJson: pkg,
31
- external,
32
- formats,
33
- output: "dist/flicking"
34
- });
@@ -1,49 +0,0 @@
1
- import path from "node:path";
2
- import vue from "@vitejs/plugin-vue";
3
- import { defineConfig } from "vite";
4
-
5
- export default defineConfig(({ mode }) => {
6
- const useBuild = mode === "production";
7
-
8
- return {
9
- plugins: [vue()],
10
- root: path.resolve(__dirname, "dev"),
11
- server: {
12
- port: 3002,
13
- open: true,
14
- fs: {
15
- allow: [".."]
16
- }
17
- },
18
- resolve: {
19
- alias: useBuild
20
- ? {
21
- // 빌드 검증 모드 - 빌드 결과물 사용
22
- "@dev/flicking": path.resolve(__dirname, "../flicking/dist/flicking.esm.js"),
23
- "@dev/vue3-flicking": path.resolve(__dirname, "dist/flicking.esm.js"),
24
- "@dev/plugins": path.resolve(__dirname, "../flicking-plugins/dist/plugins.esm.js"),
25
- "@dev/flicking-css": path.resolve(__dirname, "../flicking/dist/flicking.css"),
26
- "@dev/plugins-css": path.resolve(__dirname, "../flicking-plugins/dist/flicking-plugins.css"),
27
- // 소스코드 내부의 @egjs/flicking 참조용
28
- "@egjs/flicking": path.resolve(__dirname, "../flicking/dist/flicking.esm.js")
29
- }
30
- : {
31
- // 개발 모드 - 모든 소스 직접 참조 (HMR!)
32
- "@dev/flicking": path.resolve(__dirname, "../flicking/src/index.ts"),
33
- "@dev/vue3-flicking": path.resolve(__dirname, "src/index.ts"),
34
- "@dev/plugins": path.resolve(__dirname, "../flicking-plugins/src/index.ts"),
35
- "@dev/flicking-css": path.resolve(__dirname, "../flicking/sass/flicking.sass"),
36
- "@dev/plugins-css": path.resolve(__dirname, "../flicking-plugins/css/all.css"),
37
- // 소스코드 내부의 @egjs/flicking 참조용
38
- "@egjs/flicking": path.resolve(__dirname, "../flicking/src/index.ts")
39
- },
40
- extensions: [".ts", ".js", ".vue", ".json"]
41
- },
42
- optimizeDeps: {
43
- include: ["vue", "@egjs/axes", "@egjs/component", "@egjs/imready", "@egjs/list-differ"]
44
- },
45
- define: {
46
- __DEV__: JSON.stringify(!useBuild)
47
- }
48
- };
49
- });