|
1 | 1 | <script> |
2 | 2 | import { onMount, createEventDispatcher } from "svelte"; |
| 3 | + import Toolbar from "./Toolbar.svelte"; |
3 | 4 | import { pannable } from "./utils/pannable.js"; |
| 5 | + import { tapout } from "./utils/tapout.js"; |
4 | 6 | import { timeout } from "./utils/helper.js"; |
5 | 7 | export let size; |
6 | 8 | export let text; |
|
45 | 47 | operation = "edit"; |
46 | 48 | } |
47 | 49 | async function onBlur() { |
| 50 | + if (operation !== "edit" || operation === "tool") return; |
48 | 51 | sanitize(); |
49 | 52 | dispatch("update", { |
50 | 53 | lines: extractLines() |
51 | 54 | }); |
52 | | - // Give toolbar a chance to focus |
53 | | - operation = "edited"; |
54 | | - await timeout(); |
55 | | - if (operation === "edited") { |
56 | | - operation = ""; |
57 | | - } |
| 55 | + operation = ""; |
58 | 56 | } |
59 | 57 | async function onPaste(e) { |
60 | 58 | // get text only |
|
99 | 97 | } |
100 | 98 | } |
101 | 99 | function onFocusTool() { |
102 | | - operation = "edit"; |
| 100 | + operation = "tool"; |
103 | 101 | } |
104 | 102 | async function onBlurTool() { |
| 103 | + if (operation !== "tool" || operation === "edit") return; |
105 | 104 | dispatch("update", { |
106 | 105 | lines: extractLines(), |
107 | 106 | lineHeight: _lineHeight, |
108 | 107 | size: _size |
109 | 108 | }); |
110 | | - operation = "edited"; |
111 | | - // Give text field a chance to focus |
112 | | - await timeout(); |
113 | | - if (operation === "edited") { |
114 | | - operation = ""; |
115 | | - } |
| 109 | + operation = ""; |
116 | 110 | } |
117 | 111 | function sanitize() { |
118 | 112 | let weirdNode; |
|
144 | 138 | lines.push(lineText); |
145 | 139 | return lines; |
146 | 140 | } |
147 | | - // image version text generator |
148 | | - // function drawText() { |
149 | | - // const height = editable.offsetHeight; |
150 | | - // const width = editable.offsetWidth; |
151 | | - // const fontHeight = _size * _lineHeight; |
152 | | - // // prevent crop of last line |
153 | | - // canvas.height = height + 10; |
154 | | - // canvas.width = width; |
155 | | - // const ctx = canvas.getContext("2d"); |
156 | | - // ctx.font = `${_size}px "${_fontFamily}"`; |
157 | | - // const nodes = editable.childNodes; |
158 | | - // // FIXME: This fix should rely on ascender and descender of the font instead. |
159 | | - // let dy = fontHeight - (fontHeight - _size) / 2 - _size / 5; |
160 | | - // let lineText = ""; |
161 | | - // for (let index = 0; index < nodes.length; index++) { |
162 | | - // const node = nodes[index]; |
163 | | - // if (node.nodeName === "BR") { |
164 | | - // ctx.fillText(lineText, 0, dy); |
165 | | - // dy += fontHeight; |
166 | | - // lineText = ""; |
167 | | - // } else { |
168 | | - // // use textContext to trim strings like &npsp; |
169 | | - // lineText += node.textContent; |
170 | | - // } |
171 | | - // } |
172 | | - // if (lineText) { |
173 | | - // ctx.fillText(lineText, 0, dy); |
174 | | - // } |
175 | | - // } |
176 | 141 | onMount(render); |
177 | 142 | </script> |
178 | 143 |
|
| 144 | +<style> |
| 145 | + .editing { |
| 146 | + @apply pointer-events-none border-gray-800 border-dashed; |
| 147 | + } |
| 148 | +</style> |
| 149 | + |
179 | 150 | <svelte:options immutable={true} /> |
| 151 | +{#if operation} |
| 152 | + <Toolbar> |
| 153 | + <div |
| 154 | + use:tapout |
| 155 | + on:tapout={onBlurTool} |
| 156 | + on:mousedown={onFocusTool} |
| 157 | + on:touchstart={onFocusTool} |
| 158 | + class=" h-full flex justify-center items-center bg-gray-200 border-b |
| 159 | + border-gray-300"> |
| 160 | + <div class="mr-1 flex items-center"> |
| 161 | + <img src="/line_height.svg" class="w-4 mr-1" alt="Line height" /> |
| 162 | + <input |
| 163 | + type="number" |
| 164 | + min="1" |
| 165 | + step="0.1" |
| 166 | + class="text-sm w-10 text-center flex-shrink-0" |
| 167 | + bind:value={_lineHeight} /> |
| 168 | + </div> |
| 169 | + <div class="flex"> |
| 170 | + <img src="/text.svg" class="w-4 mr-1" alt="Font size" /> |
| 171 | + <input |
| 172 | + type="number" |
| 173 | + min="12" |
| 174 | + step="1" |
| 175 | + class="text-sm w-10 text-center" |
| 176 | + bind:value={_size} /> |
| 177 | + </div> |
| 178 | + </div> |
| 179 | + </Toolbar> |
| 180 | +{/if} |
180 | 181 | <div |
| 182 | + use:tapout |
| 183 | + on:tapout={onBlur} |
181 | 184 | class="absolute left-0 top-0 select-none" |
182 | 185 | style="transform: translate({x + dx}px, {y + dy}px);"> |
183 | 186 | <div |
184 | 187 | use:pannable |
185 | 188 | on:panstart={handlePanStart} |
186 | 189 | on:panmove={handlePanMove} |
187 | 190 | on:panend={handlePanEnd} |
188 | | - class="absolute w-full h-full cursor-grab border {operation === 'edit' ? 'border-dotted' : 'border-dashed'} |
189 | | - border-gray-600" |
| 191 | + class="absolute w-full h-full cursor-grab border border-dotted |
| 192 | + border-gray-500" |
190 | 193 | class:cursor-grab={!operation} |
191 | 194 | class:cursor-grabbing={operation === 'move'} |
192 | | - class:pointer-events-none={['edit', 'edited'].includes(operation)} /> |
193 | | - <!-- 4.25rem: When text is short and container is short, this element shrink. The number adjustment elements don't take space in no reason. --> |
194 | | - <div |
195 | | - class="absolute top-0 p-1 transform -translate-x-full bg-gray-400 rounded-sm" |
196 | | - class:hidden={!['edit', 'edited'].includes(operation)} |
197 | | - style="left: -10px; min-width: 4.25rem;"> |
198 | | - <div class="mb-1 flex items-center"> |
199 | | - <img src="/line_height.svg" class="w-4 mr-1" alt="Line height" /> |
200 | | - <input |
201 | | - type="number" |
202 | | - min="1" |
203 | | - step="0.1" |
204 | | - on:focus={onFocusTool} |
205 | | - on:blur={onBlurTool} |
206 | | - class="text-sm w-10 text-center flex-shrink-0" |
207 | | - bind:value={_lineHeight} /> |
208 | | - </div> |
209 | | - <div class="flex"> |
210 | | - <img src="/text.svg" class="w-4 mr-1" alt="Font size" /> |
211 | | - <input |
212 | | - type="number" |
213 | | - min="9" |
214 | | - on:focus={onFocusTool} |
215 | | - on:blur={onBlurTool} |
216 | | - class="text-sm w-10 text-center" |
217 | | - bind:value={_size} /> |
218 | | - </div> |
219 | | - </div> |
| 195 | + class:editing={['edit', 'tool'].includes(operation)} /> |
220 | 196 | <div |
221 | 197 | bind:this={editable} |
222 | 198 | on:focus={onFocus} |
223 | | - on:blur={onBlur} |
224 | 199 | on:keydown={onKeydown} |
225 | 200 | on:paste|preventDefault={onPaste} |
226 | 201 | contenteditable="true" |
|
0 commit comments