@sveltejs/vite-plugin-svelte 7.1.3 → 7.2.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/README.md CHANGED
@@ -12,7 +12,7 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
12
12
  export default defineConfig({
13
13
  plugins: [
14
14
  svelte({
15
- /* plugin options */
15
+ // plugin options
16
16
  })
17
17
  ]
18
18
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/vite-plugin-svelte",
3
- "version": "7.1.3",
3
+ "version": "7.2.0",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "src",
@@ -11,6 +11,7 @@ export const defaultInspectorOptions = {
11
11
  navKeys: { parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' },
12
12
  escapeKeys: ['Backspace', 'Escape'],
13
13
  openKey: 'Enter',
14
+ openMenuKey: ' ',
14
15
  holdMode: true,
15
16
  showToggleButton: 'active',
16
17
  toggleButtonPos: 'top-right',
@@ -9,6 +9,7 @@
9
9
  const escape_keys = options.escapeKeys?.map((k) => k.toLowerCase());
10
10
  const nav_keys = Object.values(options.navKeys).map((k) => k?.toLowerCase());
11
11
  const open_key = options.openKey?.toLowerCase();
12
+ const open_menu_key = options.openMenuKey?.toLowerCase();
12
13
 
13
14
  let enabled = $state(false);
14
15
  let has_opened = $state(false);
@@ -25,15 +26,16 @@
25
26
  .trim()
26
27
  )}`;
27
28
 
28
- // location of code in file
29
- let file_loc = $state();
30
- // cursor pos and width for file_loc overlay positioning
29
+ // overlay positioning
31
30
  let x = $state(),
32
31
  y = $state(),
33
- w = $state();
32
+ w = $state(),
33
+ h = $state();
34
34
 
35
35
  let active_el = $state();
36
36
 
37
+ let menu = $state(null);
38
+
37
39
  let hold_start_ts = $state();
38
40
 
39
41
  let show_toggle = $derived(
@@ -41,6 +43,7 @@
41
43
  );
42
44
 
43
45
  function mousemove(e) {
46
+ if (menu) return;
44
47
  x = e.x;
45
48
  y = e.y;
46
49
  }
@@ -102,6 +105,7 @@
102
105
  }
103
106
 
104
107
  function mouseover({ target }) {
108
+ if (menu) return;
105
109
  const el = find_selectable_parent(target, true);
106
110
  activate(el, false);
107
111
  }
@@ -115,12 +119,7 @@
115
119
  el.classList.add('svelte-inspector-active-target');
116
120
  }
117
121
  }
118
- if (el) {
119
- const { file, line, column } = el.__svelte_meta.loc;
120
- file_loc = `${file}:${line + 1}:${column + 1}`;
121
- } else {
122
- file_loc = null;
123
- }
122
+
124
123
  active_el = el;
125
124
  if (set_bubble_pos) {
126
125
  const pos = el.getBoundingClientRect();
@@ -130,13 +129,63 @@
130
129
  }
131
130
 
132
131
  function open_editor(e) {
133
- if (file_loc) {
132
+ if (menu) return;
133
+
134
+ if (active_el) {
134
135
  stop(e);
135
- fetch(`${options.__internal.base}/__open-in-editor?file=${encodeURIComponent(file_loc)}`);
136
- has_opened = true;
137
- if (options.holdMode && is_holding()) {
138
- disable();
136
+ send(active_el.__svelte_meta.loc);
137
+ }
138
+ }
139
+
140
+ function get_stack(target) {
141
+ const el = find_selectable_parent(target, true);
142
+ const meta = el?.__svelte_meta;
143
+
144
+ const stack = [
145
+ {
146
+ file: meta.loc.file,
147
+ line: meta.loc.line,
148
+ column: meta.loc.column,
149
+ tag: el.tagName.toLowerCase()
139
150
  }
151
+ ];
152
+
153
+ let entry = meta;
154
+ while ((entry = entry.parent)) {
155
+ if (entry.type !== 'component') continue;
156
+ if (/(^|\/)(node_modules|\.svelte-kit)\//.test(entry.file)) continue;
157
+
158
+ stack.push({
159
+ file: entry.file,
160
+ line: entry.line,
161
+ column: entry.column,
162
+ tag: entry.componentTag
163
+ });
164
+ }
165
+
166
+ return stack;
167
+ }
168
+
169
+ function on_contextmenu(e) {
170
+ e.preventDefault();
171
+
172
+ active_el ??= find_selectable_parent(e.target);
173
+ if (!active_el) return;
174
+
175
+ stop(e);
176
+ menu = { x: e.clientX, y: e.clientY, stack: get_stack(active_el) };
177
+ }
178
+
179
+ function send(loc) {
180
+ fetch(
181
+ `${options.__internal.base}/__open-in-editor?file=${encodeURIComponent(
182
+ `${loc.file}:${loc.line}:${loc.column + 1}`
183
+ )}`
184
+ );
185
+ has_opened = true;
186
+ menu = null;
187
+ if (options.holdMode && is_holding()) {
188
+ disable();
140
189
  }
141
190
  }
142
191
 
@@ -172,6 +221,10 @@
172
221
  return open_key && is_active(open_key, e);
173
222
  }
174
223
 
224
+ function is_open_menu(e) {
225
+ return open_menu_key && is_active(open_menu_key, e);
226
+ }
227
+
175
228
  function is_holding() {
176
229
  return hold_start_ts && Date.now() - hold_start_ts > 250;
177
230
  }
@@ -200,6 +253,8 @@
200
253
  }
201
254
  } else if (is_open(e)) {
202
255
  open_editor(e);
256
+ } else if (is_open_menu(e)) {
257
+ on_contextmenu(e);
203
258
  } else if (is_holding() || is_escape(e)) {
204
259
  // is_holding() checks for unhandled additional key pressed
205
260
  // while holding the toggle keys, which is possibly another
@@ -236,6 +291,7 @@
236
291
  l('mousemove', mousemove);
237
292
  l('mouseover', mouseover);
238
293
  l('click', open_editor, true);
294
+ l('contextmenu', on_contextmenu, true);
239
295
  }
240
296
 
241
297
  function enable() {
@@ -277,6 +333,7 @@
277
333
  enabled = false;
278
334
  has_opened = false;
279
335
  hold_start_ts = null;
336
+ menu = null;
280
337
  const b = document.body;
281
338
  listeners(b, enabled);
282
339
  if (options.customStyles) {
@@ -332,6 +389,15 @@
332
389
  });
333
390
  </script>
334
391
 
392
+ <svelte:window
393
+ onclick={disable}
394
+ onkeydown={(e) => {
395
+ if (e.key === 'Escape') {
396
+ disable();
397
+ }
398
+ }}
399
+ />
400
+
335
401
  {#if show_toggle}
336
402
  <button
337
403
  id="svelte-inspector-toggle"
@@ -344,18 +410,57 @@
344
410
  aria-label={`${enabled ? 'disable' : 'enable'} svelte-inspector`}
345
411
  ></button>
346
412
  {/if}
347
- {#if enabled && active_el && file_loc}
348
- {@const loc = active_el.__svelte_meta.loc}
413
+
414
+ {#if enabled && (menu || active_el)}
349
415
  <div
350
416
  id="svelte-inspector-overlay"
351
417
  style:left="{Math.min(x + 3, document.documentElement.clientWidth - w - 10)}px"
352
- style:top="{document.documentElement.clientHeight < y + 50 ? y - 30 : y + 30}px"
418
+ style:top="{document.documentElement.clientHeight < y + h + 40 ? y - h - 10 : y + 30}px"
353
419
  bind:offsetWidth={w}
420
+ bind:offsetHeight={h}
354
421
  >
355
- &lt;{active_el.tagName.toLowerCase()}&gt;&nbsp;{file_loc}
356
- </div>
357
- <div id="svelte-inspector-announcer" aria-live="assertive" aria-atomic="true">
358
- {active_el.tagName.toLowerCase()} in file {loc.file} on line {loc.line} column {loc.column}
422
+ {#if menu}
423
+ <button aria-label="close" class="svelte-inspector-button" {@attach (node) => node.focus()}>
424
+ <span>close</span>
425
+ <svg
426
+ xmlns="http://www.w3.org/2000/svg"
427
+ role="img"
428
+ width="1em"
429
+ height="1em"
430
+ viewBox="0 0 24 24"
431
+ stroke-width="2"
432
+ stroke-linecap="round"
433
+ stroke-linejoin="round"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg
434
+ >
435
+ </button>
436
+
437
+ <hr />
438
+
439
+ <ul class="svelte-inspector-grid">
440
+ {#each menu.stack as item, i (item.file + item.line + i)}
441
+ <li>
442
+ <button type="button" class="svelte-inspector-menu-row" onclick={() => send(item)}>
443
+ <span class="svelte-inspector-tag">&lt;{item.tag}&gt;</span>
444
+ <span class="svelte-inspector-file">{item.file}:{item.line}</span>
445
+ </button>
446
+ </li>
447
+ {/each}
448
+ </ul>
449
+ {:else}
450
+ {@const loc = active_el.__svelte_meta.loc}
451
+
452
+ <div class="svelte-inspector-grid">
453
+ <div class="svelte-inspector-menu-row">
454
+ <span class="svelte-inspector-tag">&lt;{active_el.tagName.toLowerCase()}&gt;</span>
455
+ <span class="svelte-inspector-file">{loc.file}:{loc.line}</span>
456
+ </div>
457
+ </div>
458
+
459
+ <div id="svelte-inspector-announcer" aria-live="assertive" aria-atomic="true">
460
+ {active_el.tagName.toLowerCase()} in file {loc.file} on line {loc.line} column {loc.column +
461
+ 1}
462
+ </div>
463
+ {/if}
359
464
  </div>
360
465
  {/if}
361
466
 
@@ -366,19 +471,39 @@
366
471
  :global(.svelte-inspector-active-target) {
367
472
  outline: 2px dashed #ff3e00 !important;
368
473
  }
474
+ :global(#svelte-inspector-host) {
475
+ direction: ltr;
476
+ }
477
+
478
+ *:not(svg *) {
479
+ all: unset;
480
+ box-sizing: border-box;
481
+ }
369
482
 
370
483
  #svelte-inspector-overlay {
371
484
  position: fixed;
372
- background-color: rgba(0, 0, 0, 0.8);
373
- color: #fff;
374
- padding: 2px 4px;
375
- border-radius: 5px;
485
+ padding: 2px;
486
+ margin: 0;
487
+ border-radius: 2px;
488
+ filter: drop-shadow(2px 2px 4px rgb(0 0 0 / 0.1));
489
+ font-family: ui-monospace, 'SF Mono', Menlo, monospace;
490
+ font-size: 12px;
491
+ line-height: 1.4;
376
492
  z-index: 999999;
377
- pointer-events: none;
493
+ background-color: #fff;
494
+ color: #222;
495
+ cursor: auto;
496
+ user-select: none;
497
+ }
498
+
499
+ .svelte-inspector-grid {
500
+ display: grid;
501
+ grid-template-columns: max-content 1fr;
502
+ column-gap: 8px;
503
+ /* row-gap: 4px; */
378
504
  }
379
505
 
380
506
  #svelte-inspector-toggle {
381
- all: unset;
382
507
  border: 1px solid #ff3e00;
383
508
  border-radius: 8px;
384
509
  position: fixed;
@@ -408,4 +533,83 @@
408
533
  #svelte-inspector-toggle:hover {
409
534
  background-color: #facece;
410
535
  }
536
+
537
+ .svelte-inspector-tag {
538
+ white-space: nowrap;
539
+ font-weight: 600;
540
+ }
541
+
542
+ .svelte-inspector-file {
543
+ overflow: hidden;
544
+ text-overflow: ellipsis;
545
+ white-space: nowrap;
546
+ color: #444;
547
+ }
548
+
549
+ ul {
550
+ max-width: 480px;
551
+ list-style: none;
552
+ margin: 0;
553
+ padding: 0;
554
+ display: contents;
555
+
556
+ li {
557
+ display: contents;
558
+ }
559
+ }
560
+
561
+ button {
562
+ background: transparent;
563
+ border: none;
564
+ color: inherit;
565
+ pointer-events: all;
566
+ font: inherit;
567
+ align-items: center;
568
+ cursor: pointer;
569
+
570
+ &:focus-visible {
571
+ outline: 2px solid #ff3e00;
572
+ }
573
+
574
+ &:hover,
575
+ &:focus-visible {
576
+ background-color: rgb(0 0 0 / 0.05);
577
+ }
578
+ }
579
+
580
+ hr {
581
+ margin: 2px;
582
+ background: rgb(0 0 0 / 0.05);
583
+ border: none;
584
+ height: 1px;
585
+ width: 100%;
586
+ display: block;
587
+ }
588
+
589
+ svg path {
590
+ stroke: currentColor;
591
+ }
592
+
593
+ .svelte-inspector-button {
594
+ display: flex;
595
+ justify-content: space-between;
596
+ width: 100%;
597
+ padding: 4px 8px;
598
+ }
599
+
600
+ .svelte-inspector-menu-row {
601
+ display: grid;
602
+ grid-column: 1 / 3;
603
+ grid-template-columns: subgrid;
604
+ box-sizing: border-box;
605
+ align-items: baseline;
606
+ width: 100%;
607
+ padding: 4px 8px;
608
+ cursor: pointer;
609
+
610
+ &:hover,
611
+ &:focus-visible {
612
+ background-color: rgb(0 0 0 / 0.05);
613
+ }
614
+ }
411
615
  </style>
package/src/public.d.ts CHANGED
@@ -228,6 +228,13 @@ export interface InspectorOptions {
228
228
  */
229
229
  openKey?: string;
230
230
 
231
+ /**
232
+ * define key to open the context menu for the currently selected dom node
233
+ *
234
+ * @default ' '
235
+ */
236
+ openMenuKey?: string;
237
+
231
238
  /**
232
239
  * define keys to close the inspector
233
240
  * @default ['Backspace', 'Escape']
package/types/index.d.ts CHANGED
@@ -228,6 +228,13 @@ declare module '@sveltejs/vite-plugin-svelte' {
228
228
  */
229
229
  openKey?: string;
230
230
 
231
+ /**
232
+ * define key to open the context menu for the currently selected dom node
233
+ *
234
+ * @default ' '
235
+ */
236
+ openMenuKey?: string;
237
+
231
238
  /**
232
239
  * define keys to close the inspector
233
240
  * @default ['Backspace', 'Escape']
@@ -27,6 +27,6 @@
27
27
  null,
28
28
  null
29
29
  ],
30
- "mappings": ";;;aAGYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgFbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;WAgBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;;kBAcrBC,gBAAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzKjBC,MAAMA;iBCGNC,cAAcA;iBCARC,gBAAgBA",
30
+ "mappings": ";;;aAGYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgFbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;WAgBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;;kBAcrBC,gBAAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzKjBC,MAAMA;iBCGNC,cAAcA;iBCARC,gBAAgBA",
31
31
  "ignoreList": []
32
32
  }