Skip to content

Commit 4c88abc

Browse files
authored
feat: Implement action update (#18)
1 parent e05bd0e commit 4c88abc

File tree

5 files changed

+254
-97
lines changed

5 files changed

+254
-97
lines changed

dev/src/App.svelte

Lines changed: 168 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,50 @@
11
<script>
22
import { useDropOutside } from '../../src'
33
4-
const colors = [
5-
'#865C54',
6-
'#8F5447',
7-
'#A65846',
8-
'#A9715E',
9-
'#AD8C72',
10-
'#C2B091',
11-
'#172B41',
12-
'#32465C',
13-
'#617899',
14-
'#9BA2BC',
15-
'#847999',
16-
'#50526A',
17-
'#8B8C6B',
18-
'#97A847',
19-
'#5B652C',
20-
'#6A6A40',
21-
'#F2D9BF',
22-
'#F5BAAE',
23-
'#F1A191',
24-
]
4+
import SettingsIcon from './SettingsIcon.svelte'
5+
import CloseIcon from './CloseIcon.svelte'
6+
7+
const colors = [
8+
'#865C54',
9+
'#8F5447',
10+
'#A65846',
11+
'#A9715E',
12+
'#AD8C72',
13+
'#C2B091',
14+
'#172B41',
15+
'#32465C',
16+
'#617899',
17+
'#9BA2BC',
18+
'#847999',
19+
'#50526A',
20+
'#8B8C6B',
21+
'#97A847',
22+
'#5B652C',
23+
'#6A6A40',
24+
'#F2D9BF',
25+
'#F5BAAE',
26+
'#F1A191',
27+
]
28+
29+
let showSettings = false
30+
31+
let animate = false
32+
let useDragCustomClass = false
33+
let dragImage = null
2534
2635
const _onDropOutside = (node, area) => {
2736
node.remove()
2837
}
2938
3039
const _onDropInside = () => {
31-
console.log('Dropped inside!')
40+
console.log('Dropped inside!')
3241
}
3342
34-
const _onDragCancel = () => {
35-
console.log('Drag cancelled!')
36-
}
43+
const _onDragCancel = () => {
44+
console.log('Drag cancelled!')
45+
}
3746
</script>
3847

39-
<main>
40-
<div class="container">
41-
<p class="instruction">Drop the color slots outside the white area to delete them</p>
42-
<div id="area" class="area">
43-
<ul class="slot-list">
44-
{#each colors as color, index}
45-
<li use:useDropOutside={{
46-
areaSelector: '.area',
47-
animate: true,
48-
animateOptions: {
49-
timingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)'
50-
},
51-
onDropOutside: _onDropOutside,
52-
onDropInside: _onDropInside,
53-
onDragCancel: _onDragCancel,
54-
}} style={`background-color: ${color}`} class="slot"></li>
55-
{/each}
56-
</ul>
57-
</div>
58-
</div>
59-
</main>
60-
6148
<style>
6249
main {
6350
display: flex;
@@ -72,18 +59,10 @@
7259
max-width: 640px;
7360
display: flex;
7461
flex-direction: column;
75-
align-items: center;
62+
align-items: flex-end;
7663
row-gap: 0.5rem;
7764
}
7865
79-
.instruction {
80-
margin: 0;
81-
padding: 0;
82-
color: white;
83-
font-family: Georgia,serif;
84-
width: 300px;
85-
}
86-
8766
.area {
8867
width: 300px;
8968
height: 300px;
@@ -94,28 +73,138 @@
9473
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.5);
9574
}
9675
97-
.slot-list {
98-
list-style: none;
99-
margin: 0;
100-
padding: 0;
101-
display: grid;
102-
grid-template-columns: repeat(4, 1fr);
103-
grid-gap: 1rem;
76+
.slot-list {
77+
list-style: none;
78+
margin: 0;
79+
padding: 0;
80+
display: grid;
81+
grid-template-columns: repeat(4, 1fr);
82+
grid-gap: 1rem;
83+
align-items: center;
84+
justify-items: center;
85+
}
86+
87+
.slot {
88+
width: 24px;
89+
height: 24px;
90+
margin: 0;
91+
padding: 0;
92+
border: 1px solid rgba(0, 0, 0, 0.2);
93+
border-radius: 50%;
94+
}
95+
96+
:global(.drag) {
97+
opacity: 0.5;
98+
background-color: deeppink;
99+
border-radius: 0;
100+
}
101+
102+
.toggle__button {
103+
background: none;
104+
border: none;
105+
color: white;
106+
cursor: pointer;
107+
width: 36px;
108+
}
109+
110+
.settings__container {
111+
overflow: hidden auto;
112+
position: absolute;
113+
z-index: 9999;
114+
width: 100vw;
115+
max-width: 320px;
116+
display: flex;
117+
flex-direction: column;
118+
align-items: flex-end;
119+
}
120+
121+
.settings__form {
122+
width: 100%;
123+
height: 400px;
124+
display: flex;
125+
flex-direction: column;
126+
justify-content: center;
127+
align-items: center;
128+
padding: 1rem;
129+
background-color: #fafafa;
130+
border-radius: 1rem;
131+
}
132+
133+
.settings__form fieldset {
134+
width: 100%;
135+
border: none;
136+
display: flex;
137+
}
138+
139+
.settings__form fieldset.horizontal {
104140
align-items: center;
105-
justify-items: center;
106-
}
107-
108-
.slot {
109-
width: 24px;
110-
height: 24px;
111-
margin: 0;
112-
padding: 0;
113-
border: 1px solid rgba(0, 0, 0, 0.2);
114-
border-radius: 50%;
115-
}
116-
117-
:global(.drag) {
118-
opacity: .5;
119-
background-color: deeppink;
120-
}
141+
justify-content: space-between;
142+
column-gap: 1rem;
143+
}
144+
145+
.settings__form fieldset.vertical {
146+
flex-direction: column;
147+
justify-content: center;
148+
row-gap: 1rem;
149+
}
150+
151+
.settings__form input {
152+
margin: 0;
153+
}
154+
155+
.settings__form input[type='checkbox'] {
156+
padding: 0;
157+
}
121158
</style>
159+
160+
<main>
161+
{#if showSettings}
162+
<div class="settings__container">
163+
<button type="button" class="toggle__button" on:click={() => (showSettings = !showSettings)}>
164+
<CloseIcon />
165+
</button>
166+
<form class="settings__form">
167+
<h1>Settings</h1>
168+
<fieldset class="horizontal">
169+
<label for="animate"> Animate Drag Back: </label>
170+
<input id="animate" type="checkbox" bind:checked={animate} />
171+
</fieldset>
172+
<fieldset class="horizontal">
173+
<label for="useDragCustomClass"> Use Drag Custom Class: </label>
174+
<input id="useDragCustomClass" type="checkbox" bind:checked={useDragCustomClass} />
175+
</fieldset>
176+
<fieldset class="vertical">
177+
<label for="dragImage"> Drag Image URL: </label>
178+
<input id="dragImage" type="text" bind:value={dragImage} />
179+
</fieldset>
180+
</form>
181+
</div>
182+
{/if}
183+
184+
<div class="container">
185+
<button type="button" class="toggle__button" on:click={() => (showSettings = !showSettings)}>
186+
<SettingsIcon />
187+
</button>
188+
<div id="area" class="area">
189+
<ul class="slot-list">
190+
{#each colors as color, index}
191+
<li
192+
use:useDropOutside={{
193+
areaSelector: '.area',
194+
animate,
195+
animateOptions: {
196+
timingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
197+
},
198+
dragImage,
199+
dragClassName: useDragCustomClass ? 'drag' : null,
200+
onDropOutside: _onDropOutside,
201+
onDropInside: _onDropInside,
202+
onDragCancel: _onDragCancel,
203+
}}
204+
style={`background-color: ${color}`}
205+
class="slot" />
206+
{/each}
207+
</ul>
208+
</div>
209+
</div>
210+
</main>

dev/src/CloseIcon.svelte

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
export let color = '#FFF'
3+
</script>
4+
5+
<svg viewBox="0 0 24 24" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
6+
<g transform="matrix(0.04898, 0, 0, 0.04898, 0, 0)">
7+
<path
8+
d="M207,182.8c-6.7-6.7-17.6-6.7-24.3,0s-6.7,17.6,0,24.3l38,38l-38,38c-6.7,6.7-6.7,17.6,0,24.3c3.3,3.3,7.7,5,12.1,5 c4.4,0,8.8-1.7,12.1-5l38-38l38,38c3.3,3.3,7.7,5,12.1,5s8.8-1.7,12.1-5c6.7-6.7,6.7-17.6,0-24.3l-38-38l38-38 c6.7-6.7,6.7-17.6,0-24.3s-17.6-6.7-24.3,0l-38,38L207,182.8z"
9+
fill={color} />
10+
<path
11+
d="M0,245c0,135.1,109.9,245,245,245s245-109.9,245-245S380.1,0,245,0S0,109.9,0,245z M455.7,245 c0,116.2-94.5,210.7-210.7,210.7S34.3,361.2,34.3,245S128.8,34.3,245,34.3S455.7,128.8,455.7,245z"
12+
fill={color} />
13+
</g>
14+
</svg>

dev/src/SettingsIcon.svelte

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
export let color = '#FFF'
3+
</script>
4+
5+
<svg viewBox="0 0 24 24" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
6+
<g transform="matrix(0.049005, 0, 0, 0.049005, 0, 0)">
7+
<path
8+
d="M343.45,71.8c-14.4-8.2-29.7-14.6-45.7-19V36.5c0-20.1-16.4-36.5-36.5-36.5h-32.5c-20.1,0-36.5,16.4-36.5,36.5v16.3 c-16,4.4-31.3,10.7-45.7,19l-11.6-11.5c-6.9-6.9-16.1-10.7-25.8-10.7s-18.9,3.8-25.8,10.7l-23,23c-6.9,6.9-10.7,16.1-10.7,25.8 s3.8,18.9,10.7,25.8l11.5,11.5c-8.2,14.4-14.6,29.7-19,45.7h-16.3c-20.1,0-36.5,16.4-36.5,36.5v32.5c0,20.1,16.4,36.5,36.5,36.5 h16.3c4.4,16,10.7,31.3,19,45.7l-11.5,11.6c-14.2,14.2-14.2,37.4,0,51.6l23,23c6.9,6.9,16.1,10.7,25.8,10.7s18.9-3.8,25.8-10.7 l11.5-11.5c14.4,8.2,29.7,14.6,45.7,19v16.3c0,20.1,16.4,36.5,36.5,36.5h32.5c20.1,0,36.5-16.4,36.5-36.5V437 c16-4.4,31.3-10.7,45.7-19l11.5,11.5c6.9,6.9,16.1,10.7,25.8,10.7s18.9-3.8,25.8-10.7l23-23c14.2-14.2,14.2-37.4,0-51.6 l-11.5-11.5c8.2-14.4,14.6-29.7,19-45.7h16.3c20.1,0,36.5-16.4,36.5-36.5v-32.5c0-20.1-16.4-36.5-36.5-36.5h-16.3 c-4.4-16-10.7-31.3-19-45.7l11.5-11.5c14.2-14.2,14.2-37.4,0-51.6l-23-23c-6.9-6.9-16.1-10.7-25.8-10.7s-18.9,3.8-25.8,10.7 L343.45,71.8z M379.25,84.5c0.9-0.9,2.2-0.9,3.1,0l23,23c0.9,0.9,0.9,2.2,0,3.1l-21.1,21.1c-5.8,5.8-6.7,14.9-2.1,21.7 c12.1,18,20.3,38,24.5,59.2c1.6,8,8.6,13.8,16.8,13.8h29.9c1.2,0,2.2,1,2.2,2.2v32.5c0,1.2-1,2.2-2.2,2.2h-29.9 c-8.2,0-15.2,5.8-16.8,13.8c-4.2,21.3-12.5,41.2-24.5,59.2c-4.6,6.8-3.7,15.9,2.1,21.7l21.1,21.1c0.9,0.9,0.9,2.2,0,3.1l-23,23 c-0.8,0.9-2.2,0.8-3.1,0l-21.1-21.1c-5.8-5.8-14.9-6.7-21.7-2.1c-18.1,12.1-38,20.3-59.2,24.5c-8,1.6-13.8,8.6-13.8,16.8v29.9 c0,1.2-1,2.2-2.2,2.2h-32.5c-1.2,0-2.2-1-2.2-2.2v-29.9c0-8.2-5.8-15.2-13.8-16.8c-21.2-4.2-41.2-12.5-59.2-24.5 c-2.9-1.9-6.2-2.9-9.5-2.9c-4.4,0-8.8,1.7-12.1,5l-21.1,21.1c-0.9,0.9-2.2,0.9-3.1,0l-23-23c-0.9-0.9-0.9-2.2,0-3.1l21.1-21.1 c5.8-5.8,6.7-14.9,2.1-21.7c-12.1-18.1-20.3-38-24.5-59.2c-1.6-8-8.6-13.8-16.8-13.8h-30.1c-1.2,0-2.2-1-2.2-2.2v-32.5 c0-1.2,1-2.2,2.2-2.2h29.9c8.2,0,15.2-5.8,16.8-13.8c4.2-21.2,12.5-41.2,24.5-59.2c4.5-6.8,3.7-15.9-2.1-21.7l-21.1-21.1 c-0.4-0.4-0.6-0.9-0.6-1.6c0-0.6,0.2-1.1,0.6-1.5l23-23c0.9-0.9,2.2-0.9,3.1,0l21.1,21.1c5.8,5.8,14.9,6.7,21.7,2.1 c18.1-12.1,38-20.3,59.2-24.5c8-1.6,13.8-8.6,13.8-16.8V36.5c0-1.2,1-2.2,2.2-2.2h32.5c1.2,0,2.2,1,2.2,2.2v29.9 c0,8.2,5.8,15.2,13.8,16.8c21.2,4.2,41.2,12.5,59.2,24.5c6.8,4.5,15.9,3.7,21.7-2.1L379.25,84.5z"
9+
fill={color} />
10+
<path
11+
d="M244.95,145.3c-54.9,0-99.6,44.7-99.6,99.6s44.7,99.6,99.6,99.6s99.6-44.7,99.6-99.6S299.85,145.3,244.95,145.3z M244.95,310.2c-36,0-65.3-29.3-65.3-65.3s29.3-65.3,65.3-65.3s65.3,29.3,65.3,65.3S280.95,310.2,244.95,310.2z"
12+
fill={color} />
13+
</g>
14+
</svg>

src/DragAndDrop.js

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,7 @@ class DragAndDrop {
6161

6262
this.#area = document.querySelector(areaSelector)
6363

64-
this.#drag = this.#dragImage ? resolveDragImage(this.#dragImage) : this.#target.cloneNode(true)
65-
this.#drag.setAttribute('draggable', false)
66-
this.#drag.setAttribute('id', 'drag')
67-
this.#drag.setAttribute('role', 'presentation')
68-
this.#drag.classList.add('__drag')
69-
if (!!this.#dragClassName) {
70-
const cssText = getCSSDeclaration(this.#dragClassName, true)
71-
if (!!cssText) {
72-
this.#drag.style.cssText = cssText
73-
}
74-
}
75-
76-
this.#observer = new DOMObserver()
77-
this.#observer.wait(this.#drag, null, { events: [DOMObserver.ADD] }).then(() => {
78-
const { width, height } = this.#drag.getBoundingClientRect()
79-
this.#dragWidth = width
80-
this.#dragHeight = height
81-
})
64+
this.#drag = this.#createDrag()
8265

8366
this.#boundMouseOverHandler = this.#onMouseOver.bind(this)
8467
this.#boundMouseOutHandler = this.#onMouseOut.bind(this)
@@ -92,6 +75,20 @@ class DragAndDrop {
9275
DragAndDrop.instances.push(this)
9376
}
9477

78+
update(areaSelector, dragImage, dragClassName, animate, animateOptions, onDropOutside, onDropInside, onDragCancel) {
79+
this.#dragImage = dragImage
80+
this.#dragClassName = dragClassName
81+
this.#animate = animate || false
82+
this.#animateOptions = { duration: 0.2, timingFunction: 'ease', ...(animateOptions || {}) }
83+
this.#onDropOutside = onDropOutside
84+
this.#onDropInside = onDropInside
85+
this.#onDragCancel = onDragCancel
86+
87+
this.#area = document.querySelector(areaSelector)
88+
89+
this.#drag = this.#createDrag()
90+
}
91+
9592
destroy() {
9693
this.#target.removeEventListener('mouseover', this.#boundMouseOverHandler)
9794
this.#target.removeEventListener('mouseout', this.#boundMouseOutHandler)
@@ -106,6 +103,29 @@ class DragAndDrop {
106103
this.#observer = null
107104
}
108105

106+
#createDrag() {
107+
const drag = this.#dragImage ? resolveDragImage(this.#dragImage) : this.#target.cloneNode(true)
108+
drag.setAttribute('draggable', false)
109+
drag.setAttribute('id', 'drag')
110+
drag.setAttribute('role', 'presentation')
111+
drag.classList.add('__drag')
112+
if (!!this.#dragClassName) {
113+
const cssText = getCSSDeclaration(this.#dragClassName, true)
114+
if (!!cssText) {
115+
drag.style.cssText = cssText
116+
}
117+
}
118+
119+
this.#observer = new DOMObserver()
120+
this.#observer.wait(drag, null, { events: [DOMObserver.ADD] }).then(() => {
121+
const { width, height } = drag.getBoundingClientRect()
122+
this.#dragWidth = width
123+
this.#dragHeight = height
124+
})
125+
126+
return drag
127+
}
128+
109129
#animateBack(callback) {
110130
if (this.#animate) {
111131
this.#drag.style.setProperty('--origin-x', this.#target.getBoundingClientRect().left + 'px')

0 commit comments

Comments
 (0)