@aw-webflow/pricing_page_js 1.1.0 → 1.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.
@@ -20,7 +20,10 @@
20
20
  "Bash(curl -sL \"https://atomicwork.webflow.io/pricing-new?cb=$\\(date +%s\\)\" -o live.html)",
21
21
  "Bash(curl -sL \"https://cdn.prod.website-files.com/64f08da4e7effe6dcb06d456/css/atomicwork.6a195ea2d503d973ad3d9f0b.6d732586d.opt.min.css\" -o page.css)",
22
22
  "Bash(gh release create v1.0.1 --title v1.0.1 --notes ' *)",
23
- "Bash(gh release create v1.1.0 --title v1.1.0 --notes ' *)"
23
+ "Bash(gh release create v1.1.0 --title v1.1.0 --notes ' *)",
24
+ "Bash(npm view *)",
25
+ "mcp__chrome-devtools__evaluate_script",
26
+ "Bash(git commit -m ' *)"
24
27
  ]
25
28
  }
26
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aw-webflow/pricing_page_js",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "start": "parcel script.js",
package/script.js CHANGED
@@ -249,6 +249,9 @@
249
249
  var VISIBLE_CLASS = 'is-visible';
250
250
  var OPEN_CLASS = 'is-open';
251
251
  var INIT_FLAG = 'awTooltipBound';
252
+ // grace period (ms) for the cursor to travel from the trigger across any
253
+ // gap onto the bubble before it closes — lets users reach links inside.
254
+ var HIDE_DELAY = 250;
252
255
 
253
256
  // Hover devices use mouseenter/leave; touch devices use tap-to-toggle.
254
257
  var hoverCapable = !(
@@ -316,6 +319,22 @@
316
319
  else hide(wrap);
317
320
  }
318
321
 
322
+ // delayed-close helpers so the cursor can cross the gap onto the bubble
323
+ function cancelHide(wrap) {
324
+ if (wrap.awHideTimer) {
325
+ window.clearTimeout(wrap.awHideTimer);
326
+ wrap.awHideTimer = null;
327
+ }
328
+ }
329
+
330
+ function scheduleHide(wrap) {
331
+ cancelHide(wrap);
332
+ wrap.awHideTimer = window.setTimeout(function () {
333
+ wrap.awHideTimer = null;
334
+ hide(wrap);
335
+ }, HIDE_DELAY);
336
+ }
337
+
319
338
  function bind(wrap) {
320
339
  if (wrap[INIT_FLAG]) return;
321
340
  var trigger = wrap.querySelector(TRIGGER_SELECTOR);
@@ -335,11 +354,14 @@
335
354
  }
336
355
 
337
356
  if (hoverCapable) {
357
+ // mouseenter/leave on the wrap treat the trigger + bubble (a descendant)
358
+ // as one region; the delayed hide bridges any visual gap between them.
338
359
  wrap.addEventListener('mouseenter', function () {
360
+ cancelHide(wrap);
339
361
  show(wrap);
340
362
  });
341
363
  wrap.addEventListener('mouseleave', function () {
342
- hide(wrap);
364
+ scheduleHide(wrap);
343
365
  });
344
366
  } else {
345
367
  trigger.addEventListener('click', function (e) {
@@ -401,3 +423,109 @@
401
423
  init();
402
424
  }
403
425
  })();
426
+
427
+ /* FAQ deep-link opener
428
+ *
429
+ * Some hash links (CTAs etc.) scroll the page down to the FAQ section. To stop
430
+ * the fixed navbar from covering the targeted question, the scroll target is
431
+ * set in Webflow to the FAQ *above* the one we actually want to read (Webflow
432
+ * scroll-spy interactions can't add a scroll offset). So when one of those
433
+ * links is clicked, we open the NEXT FAQ dropdown after the scroll target.
434
+ *
435
+ * FAQs are Webflow native dropdowns:
436
+ * .faq_dd (.w-dropdown)
437
+ * .faq_dd_toggle (.w-dropdown-toggle) <- the clickable bar
438
+ * .faq_dd_list (.w-dropdown-list) <- the answer
439
+ *
440
+ * We open one by replaying mousedown/mouseup/click on the toggle so Webflow's
441
+ * own dropdown handler runs and keeps its internal open/closed state in sync —
442
+ * the user can then still collapse it with a single click. Simply forcing the
443
+ * `w--open` class would desync that state.
444
+ *
445
+ * ES5 only (var / no arrow functions) for browser compatibility.
446
+ */
447
+ (function () {
448
+ 'use strict';
449
+
450
+ var FAQ_SELECTOR = '.faq_dd';
451
+ var TOGGLE_SELECTOR = '.faq_dd_toggle';
452
+ var SECTION_SELECTOR = '.faq-section';
453
+ var OPEN_CLASS = 'w--open';
454
+ // let the link's own click finish first — Webflow closes any open dropdown on
455
+ // an outside click, so opening on the next tick avoids being closed instantly.
456
+ var OPEN_DELAY = 80; // ms
457
+
458
+ function matches(el, selector) {
459
+ if (!el || el.nodeType !== 1) return false;
460
+ var fn =
461
+ el.matches ||
462
+ el.webkitMatchesSelector ||
463
+ el.msMatchesSelector ||
464
+ el.mozMatchesSelector;
465
+ return fn ? fn.call(el, selector) : false;
466
+ }
467
+
468
+ function closest(el, selector) {
469
+ while (el && el.nodeType === 1) {
470
+ if (matches(el, selector)) return el;
471
+ el = el.parentNode;
472
+ }
473
+ return null;
474
+ }
475
+
476
+ // First FAQ dropdown that appears AFTER the scroll target in document order.
477
+ // If the target is itself a FAQ, this returns the one below it; if the target
478
+ // is inside a FAQ, the FAQ containing it is skipped (it "contains", doesn't
479
+ // "follow"), so we still land on the next one.
480
+ function firstFollowingFaq(target) {
481
+ var faqs = document.querySelectorAll(FAQ_SELECTOR);
482
+ for (var i = 0; i < faqs.length; i++) {
483
+ // 4 = Node.DOCUMENT_POSITION_FOLLOWING
484
+ if (target.compareDocumentPosition(faqs[i]) & 4) return faqs[i];
485
+ }
486
+ return null;
487
+ }
488
+
489
+ function fire(el, type) {
490
+ var ev;
491
+ try {
492
+ ev = new MouseEvent(type, { bubbles: true, cancelable: true, view: window });
493
+ } catch (e) {
494
+ ev = document.createEvent('MouseEvents');
495
+ ev.initEvent(type, true, true);
496
+ }
497
+ el.dispatchEvent(ev);
498
+ }
499
+
500
+ function openFaq(faq) {
501
+ if (!faq) return;
502
+ var toggle = faq.querySelector(TOGGLE_SELECTOR);
503
+ if (!toggle) return;
504
+ if (toggle.className.indexOf(OPEN_CLASS) !== -1) return; // already open
505
+ fire(toggle, 'mousedown');
506
+ fire(toggle, 'mouseup');
507
+ fire(toggle, 'click');
508
+ }
509
+
510
+ function resolveTarget(hash) {
511
+ if (!hash || hash.charAt(0) !== '#' || hash === '#') return null;
512
+ var id = hash.slice(1);
513
+ return document.getElementById(id);
514
+ }
515
+
516
+ function onClick(e) {
517
+ var link = closest(e.target, 'a[href^="#"]');
518
+ if (!link) return;
519
+ var target = resolveTarget(link.getAttribute('href'));
520
+ if (!target) return;
521
+ // only react to links that scroll into the FAQ area
522
+ if (!matches(target, FAQ_SELECTOR) && !closest(target, SECTION_SELECTOR)) return;
523
+ var faq = firstFollowingFaq(target);
524
+ if (!faq) return;
525
+ window.setTimeout(function () {
526
+ openFaq(faq);
527
+ }, OPEN_DELAY);
528
+ }
529
+
530
+ document.addEventListener('click', onClick, false);
531
+ })();