ghostfill 0.2.3 → 0.2.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/dist/index.mjs CHANGED
@@ -2,8 +2,9 @@ import {
2
2
  PROVIDERS,
3
3
  describeFields,
4
4
  detectFields,
5
+ findLabel,
5
6
  generateFillData
6
- } from "./chunk-VMCU3BNJ.mjs";
7
+ } from "./chunk-CKZ6PWBH.mjs";
7
8
 
8
9
  // src/faker.ts
9
10
  var FIRST_NAMES = ["James", "Sarah", "Michael", "Emma", "Robert", "Olivia", "David", "Sophia", "Daniel", "Isabella", "Ahmed", "Fatima", "Carlos", "Yuki", "Priya"];
@@ -55,8 +56,8 @@ function generateForField(field, context) {
55
56
  return `https://www.${context.company.toLowerCase().replace(/\s+/g, "")}.com`;
56
57
  }
57
58
  if (field.type === "number" || field.type === "range") {
58
- const min = field.min ? parseInt(field.min) : 1;
59
- const max = field.max ? parseInt(field.max) : 100;
59
+ const min = field.min ? parseInt(field.min, 10) || 1 : 1;
60
+ const max = field.max ? parseInt(field.max, 10) || 100 : 100;
60
61
  return String(randInt(min, max));
61
62
  }
62
63
  if (label.includes("first name") || label.includes("firstname")) return context.firstName;
@@ -116,14 +117,96 @@ function focusBlur(el) {
116
117
  }
117
118
  async function fillCustomSelect(button, value) {
118
119
  button.click();
119
- await new Promise((r) => setTimeout(r, 200));
120
+ let waited = 0;
121
+ const step = 50;
122
+ while (waited < 500) {
123
+ await new Promise((r) => setTimeout(r, step));
124
+ waited += step;
125
+ const lb = button.getAttribute("aria-controls") ? document.getElementById(button.getAttribute("aria-controls")) : button.parentElement?.querySelector("[role=listbox]") || document.querySelector("[role=listbox]");
126
+ if (lb) break;
127
+ const cont = button.closest("[class*='relative']") || button.parentElement;
128
+ if (cont) {
129
+ const divs = cont.querySelectorAll("div");
130
+ for (const d of divs) {
131
+ if (d === button || d.contains(button) || button.contains(d)) continue;
132
+ if (d.classList.toString().includes("absolute") || d.classList.toString().includes("z-50")) {
133
+ waited = 999;
134
+ break;
135
+ }
136
+ }
137
+ }
138
+ }
120
139
  const listboxId = button.getAttribute("aria-controls");
121
140
  let listbox = listboxId ? document.getElementById(listboxId) : null;
122
141
  if (!listbox) {
123
- listbox = button.parentElement?.querySelector("[role=listbox]") || document.querySelector("[role=listbox]");
142
+ listbox = button.parentElement?.querySelector("[role=listbox]") || null;
124
143
  }
125
- if (listbox) {
126
- const options = listbox.querySelectorAll("[role=option]");
144
+ if (!listbox) {
145
+ const all = document.querySelectorAll("[role=listbox]");
146
+ for (const lb of all) {
147
+ if (lb.offsetParent !== null || lb.offsetHeight > 0) {
148
+ listbox = lb;
149
+ break;
150
+ }
151
+ }
152
+ }
153
+ let options = listbox ? listbox.querySelectorAll("[role=option]") : [];
154
+ if (!listbox || options.length === 0) {
155
+ let panel = null;
156
+ const container = button.closest("[class*='relative']") || button.parentElement;
157
+ if (container) {
158
+ for (const child of Array.from(container.children)) {
159
+ if (child === button || child.contains(button)) continue;
160
+ if (child.tagName === "LABEL" || child.tagName === "P" || child.tagName === "SPAN") continue;
161
+ const el = child;
162
+ const style = window.getComputedStyle(el);
163
+ if (el.classList.contains("absolute") || el.classList.contains("z-50") || style.position === "absolute" || style.position === "fixed") {
164
+ panel = el;
165
+ break;
166
+ }
167
+ }
168
+ }
169
+ if (!panel) {
170
+ let sibling = button.nextElementSibling;
171
+ while (sibling) {
172
+ const tag = sibling.tagName;
173
+ if (tag !== "P" && tag !== "LABEL" && tag !== "SPAN" && tag === "DIV") {
174
+ panel = sibling;
175
+ break;
176
+ }
177
+ sibling = sibling.nextElementSibling;
178
+ }
179
+ }
180
+ if (panel && panel !== button) {
181
+ let contentWait = 0;
182
+ while (contentWait < 1e3) {
183
+ await new Promise((r) => setTimeout(r, 100));
184
+ contentWait += 100;
185
+ const btns = panel.querySelectorAll("button");
186
+ let realBtns = 0;
187
+ for (const b of btns) {
188
+ if (!b.querySelector("input")) realBtns++;
189
+ }
190
+ if (realBtns > 0) break;
191
+ }
192
+ const clickables = panel.querySelectorAll("button, [role=option], [data-value], li");
193
+ const filtered = [];
194
+ for (const c of clickables) {
195
+ const text = c.textContent?.trim() || "";
196
+ if (!text || text === "\xD7" || text === "\u2715") continue;
197
+ if (c.querySelector("input")) continue;
198
+ if (c === button) continue;
199
+ const hasInput = c.querySelector("input[type='text'], input[type='search']");
200
+ if (hasInput) continue;
201
+ filtered.push(c);
202
+ }
203
+ if (filtered.length > 0) {
204
+ options = filtered;
205
+ listbox = panel;
206
+ }
207
+ }
208
+ }
209
+ if (options.length > 0) {
127
210
  for (const opt of options) {
128
211
  const text = opt.textContent?.trim();
129
212
  if (text === value || text?.toLowerCase() === value.toLowerCase()) {
@@ -142,7 +225,7 @@ async function fillCustomSelect(button, value) {
142
225
  }
143
226
  for (const opt of options) {
144
227
  const text = (opt.textContent?.trim() || "").toLowerCase();
145
- const isPlaceholder = text.startsWith("select") || text === "" || text === "---" || text === "choose" || text.startsWith("choose");
228
+ const isPlaceholder = text.startsWith("select") || text === "" || text === "---" || text === "choose" || text.startsWith("choose") || text.startsWith("search");
146
229
  if (!isPlaceholder) {
147
230
  opt.click();
148
231
  await new Promise((r) => setTimeout(r, 50));
@@ -264,26 +347,11 @@ async function fillFields(fields, fillData) {
264
347
  }
265
348
  return { filled, errors };
266
349
  }
267
- function findLabel(el) {
268
- if (el.id) {
269
- const label = document.querySelector(
270
- `label[for="${CSS.escape(el.id)}"]`
271
- );
272
- if (label?.textContent?.trim()) return label.textContent.trim();
273
- }
274
- const parent = el.closest("label");
275
- if (parent) {
276
- const clone = parent.cloneNode(true);
277
- clone.querySelectorAll("input").forEach((c) => c.remove());
278
- return clone.textContent?.trim() || "";
279
- }
280
- return "";
281
- }
282
350
 
283
351
  // src/selector.ts
284
352
  var currentHighlight = null;
285
353
  var overlay = null;
286
- function createOverlay(color) {
354
+ function createSelectorOverlay(color) {
287
355
  const div = document.createElement("div");
288
356
  div.id = "ghostfill-selector-overlay";
289
357
  const r = parseInt(color.slice(1, 3), 16);
@@ -302,7 +370,7 @@ function createOverlay(color) {
302
370
  return div;
303
371
  }
304
372
  function positionOverlay(el, color) {
305
- if (!overlay) overlay = createOverlay(color);
373
+ if (!overlay) overlay = createSelectorOverlay(color);
306
374
  const rect = el.getBoundingClientRect();
307
375
  Object.assign(overlay.style, {
308
376
  top: `${rect.top}px`,
@@ -374,6 +442,9 @@ function startSelection(onSelect, onCancel, ghostfillRoot, highlightColor = "#63
374
442
  return cleanup;
375
443
  }
376
444
 
445
+ // package.json
446
+ var version = "0.2.4";
447
+
377
448
  // src/overlay.ts
378
449
  var STORAGE_KEY = "ghostfill_settings";
379
450
  var POS_KEY = "ghostfill_pos";
@@ -598,7 +669,7 @@ var CSS2 = `
598
669
  font-size: 13px; font-weight: 600; color: #fff;
599
670
  letter-spacing: -0.0094em;
600
671
  }
601
- .gf-pop-header .gf-slash { color: rgba(255,255,255,0.5); }
672
+ .gf-pop-header .gf-slash { color: #6366f1; }
602
673
  .gf-pop-header .gf-header-right {
603
674
  display: flex; align-items: center; gap: 6px;
604
675
  }
@@ -863,7 +934,7 @@ var CSS2 = `
863
934
  line-height: 1.5;
864
935
  }
865
936
  `;
866
- function createOverlay2(options) {
937
+ function createOverlay(options) {
867
938
  const aiConfig = options.ai || null;
868
939
  const saved = loadSettings(aiConfig?.provider || "openai");
869
940
  if (options.apiKey) {
@@ -884,9 +955,7 @@ function createOverlay2(options) {
884
955
  active: false,
885
956
  selecting: false,
886
957
  selectedBlock: null,
887
- fields: [],
888
- overlay: host,
889
- shadowRoot: shadow
958
+ fields: []
890
959
  };
891
960
  const bar = document.createElement("div");
892
961
  bar.className = "gf-bar";
@@ -1033,7 +1102,7 @@ function createOverlay2(options) {
1033
1102
  <div class="gf-pop-header">
1034
1103
  <h3><span class="gf-slash">/</span>ghostfill</h3>
1035
1104
  <div class="gf-header-right">
1036
- <span class="gf-version">v0.2.3</span>
1105
+ <span class="gf-version">v${version}</span>
1037
1106
  <button class="gf-theme-btn" id="gf-s-theme" title="Toggle theme">
1038
1107
  ${saved.theme === "dark" ? ICONS.sun : ICONS.moon}
1039
1108
  </button>
@@ -1875,7 +1944,7 @@ function init(options = {}) {
1875
1944
  instance.destroy();
1876
1945
  instance = null;
1877
1946
  }
1878
- const { state, destroy } = createOverlay2(options);
1947
+ const { state, destroy } = createOverlay(options);
1879
1948
  instance = { destroy };
1880
1949
  return { destroy };
1881
1950
  }