pinprompt 0.0.1-alpha.0 → 0.0.1-alpha.1

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.
Files changed (3) hide show
  1. package/README.md +17 -12
  2. package/dist/client.js +57 -15
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -1,8 +1,17 @@
1
1
  # pinprompt
2
2
 
3
- **Click your UI, type what you want, paste an exact prompt into your AI.**
3
+ [![npm](https://img.shields.io/npm/v/pinprompt)](https://www.npmjs.com/package/pinprompt)
4
+ [![downloads](https://img.shields.io/npm/dw/pinprompt)](https://www.npmjs.com/package/pinprompt)
5
+ [![CI](https://github.com/ueqeb/pinprompt/actions/workflows/ci.yml/badge.svg)](https://github.com/ueqeb/pinprompt/actions/workflows/ci.yml)
6
+ [![Socket](https://socket.dev/api/badge/npm/package/pinprompt)](https://socket.dev/npm/package/pinprompt)
7
+ ![dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)
8
+ [![license](https://img.shields.io/npm/l/pinprompt)](LICENSE)
4
9
 
5
- A dev-only Vite plugin for SvelteKit. Instead of describing elements in words, you click them, and pinprompt writes where they live in your code. Built for Claude Code; the output is plain text, so any AI can read it.
10
+ **Stop describing where to change, waiting for your AI to find it, and paying for the search.**
11
+
12
+ Click elements in your SvelteKit app; pinprompt puts their exact source location in your prompt.
13
+
14
+ ![pinprompt demo: open the bar, click two elements, press Enter, get a prompt with file:line references](docs/demo.gif)
6
15
 
7
16
  ```
8
17
  move [click] above [click]
@@ -22,15 +31,11 @@ move [1] above [2]
22
31
 
23
32
  ## Why
24
33
 
25
- **For you**
26
- - Point instead of describing. No hunting for file names and line numbers.
27
- - Pick the exact instance: which card, which loop item, which component usage.
28
- - Works where you already are: your running app, your AI tool, your clipboard.
29
-
30
- **For your AI**
31
- - Goes straight to `file:line` instead of searching the codebase.
32
- - Fewer turns, fewer tokens, fewer edits to the wrong element.
33
- - Compact on purpose: no framework internals, no whole files pulled into context.
34
+ | Pain | With pinprompt |
35
+ |---|---|
36
+ | Describing exactly where to change | Click it. The prompt gets `file:line`, the component and which loop item |
37
+ | Waiting while the AI searches | It goes straight to the line: **2.4× faster** |
38
+ | Paying for that search | Fewer turns and tokens: **39% cheaper** |
34
39
 
35
40
  ## Benchmark
36
41
 
@@ -65,7 +70,7 @@ Start your dev server, then:
65
70
  | **Alt+P** | open the prompt bar |
66
71
  | click | reference an element |
67
72
  | **↑ / ↓** | widen to the parent element / narrow back |
68
- | **Enter** | copy the prompt |
73
+ | **Enter** | copy the prompt (it stays shown: copy all again, or select just a part) |
69
74
  | **Esc** | close (your draft is kept) |
70
75
 
71
76
  ## Feedback wanted
package/dist/client.js CHANGED
@@ -2853,6 +2853,49 @@ var all_registered_events = /* @__PURE__ */ new Set();
2853
2853
  var root_event_handles = /* @__PURE__ */ new Set();
2854
2854
  /**
2855
2855
  * @param {string} event_name
2856
+ * @param {EventTarget} dom
2857
+ * @param {EventListener} [handler]
2858
+ * @param {AddEventListenerOptions} [options]
2859
+ */
2860
+ function create_event(event_name, dom, handler, options = {}) {
2861
+ /**
2862
+ * @this {EventTarget}
2863
+ */
2864
+ function target_handler(event) {
2865
+ if (!options.capture) handle_event_propagation.call(dom, event);
2866
+ if (!event.cancelBubble) return without_reactive_context(() => {
2867
+ return handler?.call(this, event);
2868
+ });
2869
+ }
2870
+ if (event_name.startsWith("pointer") || event_name.startsWith("touch") || event_name === "wheel") {
2871
+ target_handler.__removed = false;
2872
+ queue_micro_task(() => {
2873
+ if (!target_handler.__removed) dom.addEventListener(event_name, target_handler, options);
2874
+ });
2875
+ } else dom.addEventListener(event_name, target_handler, options);
2876
+ return target_handler;
2877
+ }
2878
+ /**
2879
+ * @param {string} event_name
2880
+ * @param {Element} dom
2881
+ * @param {EventListener} [handler]
2882
+ * @param {boolean} [capture]
2883
+ * @param {boolean} [passive]
2884
+ * @returns {void}
2885
+ */
2886
+ function event(event_name, dom, handler, capture, passive) {
2887
+ var options = {
2888
+ capture,
2889
+ passive
2890
+ };
2891
+ var target_handler = create_event(event_name, dom, handler, options);
2892
+ if (dom === document.body || dom === window || dom === document || dom instanceof HTMLMediaElement) teardown(() => {
2893
+ target_handler.__removed = true;
2894
+ dom.removeEventListener(event_name, target_handler, options);
2895
+ });
2896
+ }
2897
+ /**
2898
+ * @param {string} event_name
2856
2899
  * @param {Element} element
2857
2900
  * @param {EventListener} [handler]
2858
2901
  * @returns {void}
@@ -4662,13 +4705,13 @@ var root = /* @__PURE__ */ from_html(`<div class="box picked svelte-4537t3"><spa
4662
4705
  var root_1 = /* @__PURE__ */ from_html(`<div class="box hover svelte-4537t3"><span class="tag svelte-4537t3"> </span></div>`);
4663
4706
  var root_2 = /* @__PURE__ */ from_html(`<li class="svelte-4537t3"><b class="svelte-4537t3"> </b> </li>`);
4664
4707
  var root_3 = /* @__PURE__ */ from_html(`<ul class="refs svelte-4537t3"></ul>`);
4665
- var root_4 = /* @__PURE__ */ from_html(`<button class="output svelte-4537t3" title="Copy again"><pre class="svelte-4537t3"> </pre></button> <div class="hint svelte-4537t3"><span class="svelte-4537t3"><span> </span> · click to copy again · Esc dismiss</span> <button class="dismiss svelte-4537t3" title="Dismiss">✕</button></div>`, 1);
4708
+ var root_4 = /* @__PURE__ */ from_html(`<pre class="output svelte-4537t3" tabindex="-1"> </pre> <div class="hint svelte-4537t3"><span class="svelte-4537t3"><span> </span> · select to copy part · Esc dismiss</span> <span class="actions svelte-4537t3"><button class="copy svelte-4537t3">Copy all</button> <button class="dismiss svelte-4537t3" title="Dismiss">✕</button></span></div>`, 1);
4666
4709
  var root_5 = /* @__PURE__ */ from_html(`<textarea rows="2" placeholder="Type what you want, click elements to reference them…" class="svelte-4537t3"></textarea> <div class="hint svelte-4537t3"><span class="svelte-4537t3">Click to reference · ↑↓ parent/child · Enter copy · Esc close</span> <span class="svelte-4537t3"> </span></div>`, 1);
4667
4710
  var root_6 = /* @__PURE__ */ from_html(`<!> <!> <div class="bar svelte-4537t3"><!> <!></div>`, 1);
4668
4711
  var root_7 = /* @__PURE__ */ from_html(`<button class="launcher svelte-4537t3" title="pinprompt (Alt+P)">pinprompt</button>`);
4669
4712
  var $$css = {
4670
4713
  hash: "svelte-4537t3",
4671
- code: ".svelte-4537t3 {box-sizing:border-box;}.box.svelte-4537t3 {position:fixed;z-index:2147483646;pointer-events:none;border-radius:3px;}.hover.svelte-4537t3 {outline:2px dashed #3b82f6;background:rgb(59 130 246 / 0.08);}.picked.svelte-4537t3 {outline:2px solid var(--c);}.tag.svelte-4537t3 {position:absolute;left:-2px;bottom:100%;padding:1px 6px;border-radius:3px 3px 0 0;background:var(--c, #3b82f6);color:#fff;font:600 11px/1.5 ui-monospace, monospace;white-space:nowrap;}.bar.svelte-4537t3 {position:fixed;z-index:2147483647;left:50%;bottom:16px;width:min(640px, calc(100vw - 32px));transform:translateX(-50%);padding:8px;border-radius:10px;background:#18181b;color:#fafafa;box-shadow:0 8px 30px rgb(0 0 0 / 0.35);font:13px/1.4 system-ui, sans-serif;}.refs.svelte-4537t3 {display:flex;flex-wrap:wrap;gap:4px;margin:0 0 6px;padding:0;list-style:none;}.refs.svelte-4537t3 li:where(.svelte-4537t3) {padding:1px 6px;border-left:3px solid var(--c);border-radius:3px;background:#27272a;font-size:12px;}textarea.svelte-4537t3 {display:block;width:100%;resize:none;padding:6px 8px;border:1px solid #3f3f46;border-radius:6px;background:#09090b;color:inherit;font:14px/1.4 ui-monospace, monospace;outline:none;}textarea.svelte-4537t3:focus {border-color:#3b82f6;}.hint.svelte-4537t3 {display:flex;justify-content:space-between;margin-top:4px;color:#a1a1aa;font-size:11px;}.status.svelte-4537t3 {color:#4ade80;}.status.failed.svelte-4537t3 {color:#f87171;}.output.svelte-4537t3 {display:block;width:100%;max-height:40vh;overflow:auto;padding:6px 8px;border:1px solid #3f3f46;border-radius:6px;background:#09090b;color:inherit;text-align:left;cursor:copy;}.output.svelte-4537t3:hover,\n .output.svelte-4537t3:focus-visible {border-color:#3b82f6;outline:none;}.output.svelte-4537t3 pre:where(.svelte-4537t3) {margin:0;font:12px/1.45 ui-monospace, monospace;white-space:pre-wrap;word-break:break-word;}.dismiss.svelte-4537t3 {padding:0 4px;border:0;background:none;color:inherit;font:inherit;cursor:pointer;}.dismiss.svelte-4537t3:hover {color:#fafafa;}.launcher.svelte-4537t3 {position:fixed;z-index:2147483647;right:12px;bottom:12px;padding:4px 10px;border:0;border-radius:6px;background:#18181b;color:#fafafa;font:12px/1.4 system-ui, sans-serif;cursor:pointer;opacity:0.6;}.launcher.svelte-4537t3:hover {opacity:1;}"
4714
+ code: ".svelte-4537t3 {box-sizing:border-box;}.box.svelte-4537t3 {position:fixed;z-index:2147483646;pointer-events:none;border-radius:3px;}.hover.svelte-4537t3 {outline:2px dashed #3b82f6;background:rgb(59 130 246 / 0.08);}.picked.svelte-4537t3 {outline:2px solid var(--c);}.tag.svelte-4537t3 {position:absolute;left:-2px;bottom:100%;padding:1px 6px;border-radius:3px 3px 0 0;background:var(--c, #3b82f6);color:#fff;font:600 11px/1.5 ui-monospace, monospace;white-space:nowrap;}.bar.svelte-4537t3 {position:fixed;z-index:2147483647;left:50%;bottom:16px;width:min(640px, calc(100vw - 32px));transform:translateX(-50%);padding:8px;border-radius:10px;background:#18181b;color:#fafafa;box-shadow:0 8px 30px rgb(0 0 0 / 0.35);font:13px/1.4 system-ui, sans-serif;}.refs.svelte-4537t3 {display:flex;flex-wrap:wrap;gap:4px;margin:0 0 6px;padding:0;list-style:none;}.refs.svelte-4537t3 li:where(.svelte-4537t3) {padding:1px 6px;border-left:3px solid var(--c);border-radius:3px;background:#27272a;font-size:12px;}textarea.svelte-4537t3 {display:block;width:100%;resize:none;padding:6px 8px;border:1px solid #3f3f46;border-radius:6px;background:#09090b;color:inherit;font:14px/1.4 ui-monospace, monospace;outline:none;}textarea.svelte-4537t3:focus {border-color:#3b82f6;}.hint.svelte-4537t3 {display:flex;justify-content:space-between;margin-top:4px;color:#a1a1aa;font-size:11px;}.status.svelte-4537t3 {color:#4ade80;}.status.failed.svelte-4537t3 {color:#f87171;}.output.svelte-4537t3 {max-height:40vh;overflow:auto;margin:0;padding:6px 8px;border:1px solid #3f3f46;border-radius:6px;background:#09090b;font:12px/1.45 ui-monospace, monospace;white-space:pre-wrap;word-break:break-word;user-select:text;cursor:text;outline:none;}.actions.svelte-4537t3 {display:flex;gap:6px;align-items:center;}.copy.svelte-4537t3 {padding:1px 8px;border:1px solid #3f3f46;border-radius:4px;background:#27272a;color:#fafafa;font:inherit;cursor:pointer;}.copy.svelte-4537t3:hover,\n .copy.svelte-4537t3:focus-visible {border-color:#3b82f6;outline:none;}.dismiss.svelte-4537t3 {padding:0 4px;border:0;background:none;color:inherit;font:inherit;cursor:pointer;}.dismiss.svelte-4537t3:hover {color:#fafafa;}.launcher.svelte-4537t3 {position:fixed;z-index:2147483647;right:12px;bottom:12px;padding:4px 10px;border:0;border-radius:6px;background:#18181b;color:#fafafa;font:12px/1.4 system-ui, sans-serif;cursor:pointer;opacity:0.6;}.launcher.svelte-4537t3:hover {opacity:1;}"
4672
4715
  };
4673
4716
  function Overlay($$anchor, $$props) {
4674
4717
  push($$props, true);
@@ -4711,6 +4754,9 @@ function Overlay($$anchor, $$props) {
4711
4754
  if (e.altKey && !e.ctrlKey && !e.metaKey && e.code === "KeyP") {
4712
4755
  e.preventDefault();
4713
4756
  toggle();
4757
+ } else if (e.key === "Escape" && get(output) && e.composedPath().includes($$props.host)) {
4758
+ e.preventDefault();
4759
+ dismiss();
4714
4760
  }
4715
4761
  };
4716
4762
  window.addEventListener("keydown", onKey, true);
@@ -4789,12 +4835,6 @@ function Overlay($$anchor, $$props) {
4789
4835
  set(output, "");
4790
4836
  set(status, "");
4791
4837
  }
4792
- function onResultKeydown(e) {
4793
- if (e.key === "Escape") {
4794
- e.preventDefault();
4795
- dismiss();
4796
- }
4797
- }
4798
4838
  function onKeydown(e) {
4799
4839
  if (e.isComposing || e.keyCode === 229) return;
4800
4840
  if (e.key === "Enter" && !e.shiftKey) {
@@ -4890,26 +4930,28 @@ function Overlay($$anchor, $$props) {
4890
4930
  var node_5 = sibling(node_4, 2);
4891
4931
  var consequent_3 = ($$anchor) => {
4892
4932
  var fragment_3 = root_4();
4893
- var button = first_child(fragment_3);
4894
- var text_5 = only_child(child(button), true);
4895
- reset(button);
4896
- bind_this(button, ($$value) => set(result, $$value), () => get(result));
4897
- var div_3 = sibling(button, 2);
4933
+ var pre = first_child(fragment_3);
4934
+ var text_5 = only_child(pre, true);
4935
+ var div_3 = sibling(pre, 2);
4898
4936
  var span_2 = child(div_3);
4899
4937
  var span_3 = child(span_2);
4900
4938
  let classes;
4901
4939
  var text_6 = only_child(span_3, true);
4902
4940
  next();
4903
4941
  reset(span_2);
4904
- var button_1 = sibling(span_2, 2);
4942
+ var span_4 = sibling(span_2, 2);
4943
+ var button = child(span_4);
4944
+ bind_this(button, ($$value) => set(result, $$value), () => get(result));
4945
+ var button_1 = sibling(button, 2);
4946
+ reset(span_4);
4905
4947
  reset(div_3);
4906
4948
  template_effect(() => {
4907
4949
  set_text(text_5, get(output));
4908
4950
  classes = set_class(span_3, 1, "status svelte-4537t3", null, classes, { failed: get(failed) });
4909
4951
  set_text(text_6, get(status) || "Copied");
4910
4952
  });
4953
+ event("copy", pre, () => (set(status, "Copied selection"), set(failed, false)));
4911
4954
  delegated("click", button, copy);
4912
- delegated("keydown", button, onResultKeydown);
4913
4955
  delegated("click", button_1, dismiss);
4914
4956
  append($$anchor, fragment_3);
4915
4957
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pinprompt",
3
- "version": "0.0.1-alpha.0",
4
- "description": "Point at your app, say what you want, and paste a prompt that tells your AI exactly which code you mean.",
3
+ "version": "0.0.1-alpha.1",
4
+ "description": "Click your SvelteKit UI to tell your AI exactly where to change. Less describing, waiting and paying.",
5
5
  "keywords": [
6
6
  "svelte",
7
7
  "sveltekit",
@@ -27,6 +27,7 @@
27
27
  "engines": {
28
28
  "node": ">=18"
29
29
  },
30
+ "packageManager": "pnpm@12.9.1",
30
31
  "files": [
31
32
  "dist"
32
33
  ],