@websline/cms-view-utils 1.0.2 → 1.0.4

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": "@websline/cms-view-utils",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -13,13 +13,13 @@
13
13
  children,
14
14
  color = "#000fff",
15
15
  isValidBlock = true,
16
+ locale = "de",
16
17
  position,
17
18
  textColor = "#F1F1F2",
18
19
  } = $props();
19
20
 
20
21
  let calcBarPosition = $derived.by(() => {
21
22
  if (typeof barPosition === "string") return barPosition;
22
-
23
23
  if (position === 0) return "inside";
24
24
 
25
25
  return "outside";
@@ -40,7 +40,9 @@
40
40
  return debounced;
41
41
  };
42
42
 
43
- const handleClick = (action) => {
43
+ const handleClick = (event, action) => {
44
+ event.stopPropagation();
45
+
44
46
  switch (action) {
45
47
  case CMS_ACTIONS.add:
46
48
  notifyCMS(EVENTS.BLOCK_ADD, { position });
@@ -84,6 +86,20 @@
84
86
 
85
87
  let toolbarVisible = $derived(isHovered || isActive);
86
88
 
89
+ let activeTooltip = $state(null);
90
+ let tooltipLeaveTimer;
91
+
92
+ const showTooltip = (name) => {
93
+ clearTimeout(tooltipLeaveTimer);
94
+ activeTooltip = name;
95
+ };
96
+
97
+ const hideTooltip = () => {
98
+ tooltipLeaveTimer = setTimeout(() => {
99
+ activeTooltip = null;
100
+ }, 200);
101
+ };
102
+
87
103
  const handleLeave = () => {
88
104
  handleEnterDebounced.cancel();
89
105
  isHovered = false;
@@ -123,6 +139,33 @@
123
139
  : "before:top-0 before:-left-4 before:shadow-[6px_-6px_0_0_var(--block-color)] " +
124
140
  "after:top-0 after:-right-4 after:shadow-[-6px_-6px_0_0_var(--block-color)]",
125
141
  );
142
+
143
+ let tooltipClasses = `tooltip absolute -top-9 bg-[var(--block-color)] leading-none text-xs p-1.5 rounded-tl rounded-tr left-0 whitespace-nowrap transition-opacity duration-150`;
144
+
145
+ const labels = {
146
+ de: {
147
+ add: "Hinzufügen",
148
+ position: "Anordnen",
149
+ delete: "Löschen",
150
+ edit: "Bearbeiten",
151
+ addAria: "Block hinzufügen",
152
+ positionAria: "Block anordnen",
153
+ deleteAria: "Block löschen",
154
+ editAria: "Block bearbeiten",
155
+ },
156
+ en: {
157
+ add: "Add",
158
+ position: "Arrange",
159
+ delete: "Delete",
160
+ edit: "Edit",
161
+ addAria: "Add block",
162
+ positionAria: "Arrange block",
163
+ deleteAria: "Delete block",
164
+ editAria: "Edit block",
165
+ },
166
+ };
167
+
168
+ let t = $derived(labels[locale] ?? labels.de);
126
169
  </script>
127
170
 
128
171
  <div
@@ -132,23 +175,28 @@
132
175
  data-cms-editable-block
133
176
  onmouseenter={handleEnterDebounced}
134
177
  onmouseleave={handleLeave}
135
- role="group">
178
+ onclick={(event) => handleClick(event, CMS_ACTIONS.edit)}
179
+ onkeydown={(event) => event.key === "Enter" && handleClick(event, CMS_ACTIONS.edit)}
180
+ role="button"
181
+ tabindex="0">
136
182
  <div
137
- class="pointer-events-none absolute inset-0 z-[9998] border-6 transition-opacity duration-100"
183
+ class="pointer-events-none absolute inset-0 z-9998 border-6 transition-opacity duration-100"
138
184
  style="border-color: var(--block-color)"
139
185
  class:opacity-100={toolbarVisible}
140
186
  class:opacity-0={!toolbarVisible}>
141
187
  </div>
142
188
 
143
189
  <div
144
- class="absolute left-1/2 z-[9999] flex h-9 -translate-x-1/2 items-center justify-center gap-1.5 px-3 transition-opacity duration-100 before:absolute before:h-4 before:w-4 before:rounded-full before:bg-transparent before:content-[''] after:absolute after:h-4 after:w-4 after:rounded-full after:bg-transparent after:content-[''] {containerShape} {cornerEdges}"
190
+ class="absolute left-1/2 z-9999 flex h-9 -translate-x-1/2 items-center justify-center gap-1.5 px-3 transition-opacity duration-100 before:absolute before:h-4 before:w-4 before:rounded-full before:bg-transparent before:content-[''] after:absolute after:h-4 after:w-4 after:rounded-full after:bg-transparent after:content-[''] {containerShape} {cornerEdges}"
145
191
  style="background: var(--block-color); color: var(--block-text);"
146
192
  class:opacity-100={toolbarVisible}
147
193
  class:opacity-0={!toolbarVisible}>
148
194
  <button
149
- aria-label="add block"
150
- class="cursor-pointer"
151
- onclick={() => handleClick(CMS_ACTIONS.add)}>
195
+ aria-label={t.addAria}
196
+ class="relative cursor-pointer"
197
+ onmouseenter={() => showTooltip("add")}
198
+ onmouseleave={hideTooltip}
199
+ onclick={(event) => handleClick(event, CMS_ACTIONS.add)}>
152
200
  <svg
153
201
  width="24"
154
202
  height="24"
@@ -162,13 +210,20 @@
162
210
  stroke-linecap="round"
163
211
  stroke-linejoin="round" />
164
212
  </svg>
213
+ <div
214
+ class={tooltipClasses}
215
+ class:opacity-0={activeTooltip !== "add"}
216
+ class:opacity-100={activeTooltip === "add"}
217
+ class:pointer-events-none={activeTooltip !== "add"}>
218
+ {t.add}
219
+ </div>
165
220
  </button>
166
221
 
167
222
  <!-- {#if blockVisible}
168
223
  <button
169
224
  aria-label="hide block"
170
225
  class="cursor-pointer"
171
- onclick={() => handleClick(CMS_ACTIONS.hideBlock)}>
226
+ onclick={(event) => handleClick(event, CMS_ACTIONS.hideBlock)}>
172
227
  <svg
173
228
  width="24"
174
229
  height="24"
@@ -193,7 +248,7 @@
193
248
  <button
194
249
  aria-label="show block"
195
250
  class="cursor-pointer"
196
- onclick={() => handleClick(CMS_ACTIONS.showBlock)}>
251
+ onclick={(event) => handleClick(event, CMS_ACTIONS.showBlock)}>
197
252
  <svg
198
253
  width="24"
199
254
  height="24"
@@ -222,7 +277,7 @@
222
277
  <!-- <button
223
278
  aria-label="copy block"
224
279
  class="cursor-pointer"
225
- onclick={() => handleClick(CMS_ACTIONS.copy)}>
280
+ onclick={(event) => handleClick(event, CMS_ACTIONS.copy)}>
226
281
  <svg
227
282
  width="24"
228
283
  height="24"
@@ -239,9 +294,11 @@
239
294
  </button> -->
240
295
 
241
296
  <button
242
- aria-label="position block"
243
- class="cursor-pointer"
244
- onclick={() => handleClick(CMS_ACTIONS.position)}>
297
+ aria-label={t.positionAria}
298
+ class="relative cursor-pointer"
299
+ onmouseenter={() => showTooltip("position")}
300
+ onmouseleave={hideTooltip}
301
+ onclick={(event) => handleClick(event, CMS_ACTIONS.position)}>
245
302
  <svg
246
303
  width="24"
247
304
  height="24"
@@ -255,12 +312,21 @@
255
312
  stroke-linecap="round"
256
313
  stroke-linejoin="round" />
257
314
  </svg>
315
+ <div
316
+ class={tooltipClasses}
317
+ class:opacity-0={activeTooltip !== "position"}
318
+ class:opacity-100={activeTooltip === "position"}
319
+ class:pointer-events-none={activeTooltip !== "position"}>
320
+ {t.position}
321
+ </div>
258
322
  </button>
259
323
 
260
324
  <button
261
- aria-label="delete block"
262
- class="cursor-pointer"
263
- onclick={() => handleClick(CMS_ACTIONS.delete)}>
325
+ aria-label={t.deleteAria}
326
+ class="relative cursor-pointer"
327
+ onmouseenter={() => showTooltip("delete")}
328
+ onmouseleave={hideTooltip}
329
+ onclick={(event) => handleClick(event, CMS_ACTIONS.delete)}>
264
330
  <svg
265
331
  width="24"
266
332
  height="24"
@@ -274,12 +340,21 @@
274
340
  stroke-linecap="round"
275
341
  stroke-linejoin="round" />
276
342
  </svg>
343
+ <div
344
+ class={tooltipClasses}
345
+ class:opacity-0={activeTooltip !== "delete"}
346
+ class:opacity-100={activeTooltip === "delete"}
347
+ class:pointer-events-none={activeTooltip !== "delete"}>
348
+ {t.delete}
349
+ </div>
277
350
  </button>
278
351
 
279
352
  <button
280
- aria-label="edit block"
281
- class="cursor-pointer"
282
- onclick={() => handleClick(CMS_ACTIONS.edit)}>
353
+ aria-label={t.editAria}
354
+ class="relative cursor-pointer"
355
+ onmouseenter={() => showTooltip("edit")}
356
+ onmouseleave={hideTooltip}
357
+ onclick={(event) => handleClick(event, CMS_ACTIONS.edit)}>
283
358
  <svg
284
359
  width="24"
285
360
  height="24"
@@ -293,6 +368,13 @@
293
368
  stroke-linecap="round"
294
369
  stroke-linejoin="round" />
295
370
  </svg>
371
+ <div
372
+ class={tooltipClasses}
373
+ class:opacity-0={activeTooltip !== "edit"}
374
+ class:opacity-100={activeTooltip === "edit"}
375
+ class:pointer-events-none={activeTooltip !== "edit"}>
376
+ {t.edit}
377
+ </div>
296
378
  </button>
297
379
  </div>
298
380
 
@@ -310,3 +392,14 @@
310
392
  {/if}
311
393
  </div>
312
394
  </div>
395
+
396
+ <style>
397
+ .tooltip::after {
398
+ content: "";
399
+ bottom: -8px;
400
+ height: 8px;
401
+ left: 0;
402
+ position: absolute;
403
+ right: 0;
404
+ }
405
+ </style>
@@ -43,6 +43,7 @@ const fetchPage = async (context) => {
43
43
 
44
44
  if (isCMSPreviewRoute) {
45
45
  context.locals._preview = true;
46
+ context.locals._cmsLocale = url.searchParams.get("cmsLocale");
46
47
  }
47
48
  if (isCMSEditRoute) {
48
49
  context.locals._edit = true;