ghostfill 0.2.3 → 0.3.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/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;
143
+ }
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
+ }
124
208
  }
125
- if (listbox) {
126
- const options = listbox.querySelectorAll("[role=option]");
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`,
@@ -598,7 +666,7 @@ var CSS2 = `
598
666
  font-size: 13px; font-weight: 600; color: #fff;
599
667
  letter-spacing: -0.0094em;
600
668
  }
601
- .gf-pop-header .gf-slash { color: rgba(255,255,255,0.5); }
669
+ .gf-pop-header .gf-slash { color: #6366f1; }
602
670
  .gf-pop-header .gf-header-right {
603
671
  display: flex; align-items: center; gap: 6px;
604
672
  }
@@ -863,7 +931,7 @@ var CSS2 = `
863
931
  line-height: 1.5;
864
932
  }
865
933
  `;
866
- function createOverlay2(options) {
934
+ function createOverlay(options) {
867
935
  const aiConfig = options.ai || null;
868
936
  const saved = loadSettings(aiConfig?.provider || "openai");
869
937
  if (options.apiKey) {
@@ -884,9 +952,7 @@ function createOverlay2(options) {
884
952
  active: false,
885
953
  selecting: false,
886
954
  selectedBlock: null,
887
- fields: [],
888
- overlay: host,
889
- shadowRoot: shadow
955
+ fields: []
890
956
  };
891
957
  const bar = document.createElement("div");
892
958
  bar.className = "gf-bar";
@@ -1875,7 +1941,7 @@ function init(options = {}) {
1875
1941
  instance.destroy();
1876
1942
  instance = null;
1877
1943
  }
1878
- const { state, destroy } = createOverlay2(options);
1944
+ const { state, destroy } = createOverlay(options);
1879
1945
  instance = { destroy };
1880
1946
  return { destroy };
1881
1947
  }