@guidelytech/guide-runtime 0.9.0 → 0.10.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.d.cts CHANGED
@@ -17,11 +17,32 @@ declare function normalizeText(text: string | null | undefined): string;
17
17
  declare function isVisible(el: Element): boolean;
18
18
  /** Elements that belong to Guidely's own UI are never valid targets. */
19
19
  declare function isGuidelyElement(el: Element | null): boolean;
20
- /** Resolves every element matching one strategy (visible or not). */
21
- declare function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot): Element[];
20
+ /** Separates the shadow-host steps of a CSS selector (`>>>` is not valid CSS, so it never clashes). */
21
+ declare const SHADOW_SEPARATOR = " >>> ";
22
+ /** The element's parent in the composed tree: its parent element, or its shadow host at the top of a shadow root. */
23
+ declare function composedParent(el: Element): Element | null;
24
+ /** Does `ancestor` contain `node`, looking through shadow boundaries? */
25
+ declare function containsComposed(ancestor: Element, node: Node | null): boolean;
26
+ /** The element an event really started on: inside a shadow root `e.target` is retargeted to the host. */
27
+ declare function composedTarget(e: Event): Element | null;
28
+ /**
29
+ * `Element.closest` across shadow boundaries: the nearest element, from `el` up through its shadow
30
+ * hosts, that matches `selector` (which may be a `>>>` chain). Throws on an invalid plain selector,
31
+ * like `closest` does.
32
+ */
33
+ declare function closestComposed(el: Element, selector: string): Element | null;
34
+ /** The innermost element at a point, looking inside open shadow roots (`elementFromPoint` stops at the host). */
35
+ declare function deepElementFromPoint(doc: Document, x: number, y: number): Element | null;
36
+ /**
37
+ * Resolves every element matching one strategy (visible or not). `deep` (the default) also searches
38
+ * open shadow roots; `>>>` chains are always followed. XPath cannot cross shadow boundaries.
39
+ */
40
+ declare function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot, deep?: boolean): Element[];
22
41
  /**
23
42
  * Resolves a step target by trying each strategy in order. A strategy wins only when it
24
- * resolves to exactly one *visible* element; otherwise the next strategy is tried.
43
+ * resolves to exactly one *visible* element; otherwise the next strategy is tried. Each strategy
44
+ * looks in the document first and only searches shadow roots when nothing there is visible, so a
45
+ * target that resolved before shadow-DOM support still resolves to the same element.
25
46
  */
26
47
  declare function resolveTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], root?: QueryRoot): Element | null;
27
48
  interface WaitForTargetOptions {
@@ -39,11 +60,17 @@ declare class TargetTimeoutError extends Error {
39
60
  }
40
61
  /**
41
62
  * Waits until `resolveTarget` finds an element. Uses a MutationObserver plus a polling fallback
42
- * (at most every 250ms) so visibility changes without DOM mutations are also detected.
63
+ * (at most every 250ms) so visibility changes without DOM mutations, and changes inside shadow
64
+ * roots (which the observer does not see), are also detected.
43
65
  */
44
66
  declare function waitForTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], options?: WaitForTargetOptions): Promise<Element>;
45
67
  /** Is this id stable enough to be used as a selector (not generated by a framework)? */
46
68
  declare function isStableId(id: string): boolean;
69
+ /**
70
+ * The `>>>` chain of shadow hosts above an element (`c-app >>> c-form`), or "" for an element in
71
+ * the document itself; null when some host has no unique path within its own root.
72
+ */
73
+ declare function shadowHostChain(el: Element): string | null;
47
74
  /** Short human-readable text for an element, trimmed to 200 characters. */
48
75
  declare function textSnapshotOf(el: Element): string;
49
76
  /**
@@ -62,7 +89,25 @@ interface ElementDescription {
62
89
  };
63
90
  tag: string;
64
91
  }
65
- /** Everything the authoring picker needs for one element. */
92
+ /**
93
+ * An element's on-screen box. For a shadow host that is its own box joined with its shadow content's:
94
+ * an `inline` host (the default for custom elements) is only a line tall around a taller button, and
95
+ * a `display: contents` host has no box at all.
96
+ */
97
+ declare function visualRect(el: Element): DOMRect;
98
+ /**
99
+ * The element a pick should target. Inside a component (a shadow host) that is little more than the
100
+ * picked control (`lightning-button` around its `<button>`, also when the pick is the button's icon;
101
+ * `lightning-input` around its label and field), that is the component itself: the app's markup around a component is the app's, while a
102
+ * design system can change a component's internals in any release. Repeats up nested components and
103
+ * stops at the first one that is clearly more (a list, a form, the whole app). Without layout (tests,
104
+ * hidden pages) the element is kept.
105
+ */
106
+ declare function componentAnchor(el: Element): Element;
107
+ /**
108
+ * Everything the authoring picker and how-to capture need for one element. Selectors and rect are
109
+ * for its `componentAnchor`; the text falls back to the element's own.
110
+ */
66
111
  declare function describeElement(el: Element): ElementDescription;
67
112
 
68
113
  /**
@@ -137,7 +182,7 @@ interface AnchorOptions {
137
182
  * Anchors `floating` next to `reference` using floating-ui (`flip`, `shift`, `offset`, `arrow`).
138
183
  * `placement: "auto"` uses `autoPlacement`. Returns a cleanup function that stops `autoUpdate`.
139
184
  */
140
- declare function anchor(reference: Element, floating: HTMLElement, options?: AnchorOptions): () => void;
185
+ declare function anchor(target: Element, floating: HTMLElement, options?: AnchorOptions): () => void;
141
186
  /** Tracks the bounding rect of an element and calls `cb` on scroll/resize/mutation. */
142
187
  declare function trackRect(el: Element, cb: (rect: DOMRect) => void): () => void;
143
188
 
@@ -405,4 +450,4 @@ declare function highlightSelectors(selectors: SelectorStrategy[], options?: {
405
450
  /** All runtime CSS, injected once into the Shadow DOM host. Tokens are CSS custom properties. */
406
451
  declare const STYLES = "\n:host{all:initial;position:static;display:block;contain:none}\n*,*::before,*::after{box-sizing:border-box}\n.g-scope [hidden]{display:none!important}\n.g-scope{\n --g-primary:#4f46e5;--g-bg:#ffffff;--g-text:#111827;--g-radius:12px;--g-font:Inter,system-ui,-apple-system,sans-serif;--g-z:2147483000;--g-overlay:.5;\n --g-muted:color-mix(in srgb,var(--g-text) 62%,transparent);--g-border:color-mix(in srgb,var(--g-text) 12%,transparent);\n --g-subtle:color-mix(in srgb,var(--g-text) 5%,transparent);--g-shadow:0 10px 40px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.08);\n --g-primary-text:#ffffff;\n font-family:var(--g-font);font-size:14px;line-height:1.5;color:var(--g-text);-webkit-font-smoothing:antialiased;\n}\n.g-scope[data-theme=\"dark\"]{--g-shadow:0 10px 40px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3)}\n.g-live{position:fixed;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n.g-layer{position:fixed;inset:0;z-index:var(--g-z);pointer-events:none}\n.g-overlay{position:fixed;inset:0;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-overlay.g-transparent{background:transparent}\n.g-spot-rect{position:fixed;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-spot-ring{position:fixed;z-index:calc(var(--g-z) + 3);pointer-events:none;border-radius:6px;box-shadow:0 0 0 2px var(--g-primary),0 0 0 6px color-mix(in srgb,var(--g-primary) 30%,transparent)}\n.g-card{\n position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);\n box-shadow:var(--g-shadow);border:1px solid var(--g-border);width:min(360px,calc(100vw - 32px));max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto;outline:none;\n}\n.g-card.g-modal{left:50%;top:50%;transform:translate(-50%,-50%);width:min(480px,calc(100vw - 32px))}\n.g-card.g-tooltip,.g-card.g-popover,.g-card.g-spotlight-card,.g-card.g-hotspot-card{top:0;left:0;width:min(320px,calc(100vw - 32px))}\n.g-card.g-slideout{width:min(360px,calc(100vw - 32px));margin:16px}\n.g-pos-bottom-right{right:0;bottom:0}.g-pos-bottom-left{left:0;bottom:0}.g-pos-top-right{right:0;top:0}.g-pos-top-left{left:0;top:0}\n.g-pos-center{left:50%;top:50%;transform:translate(-50%,-50%)}\n.g-pos-top{top:0;left:0;right:0}.g-pos-bottom{bottom:0;left:0;right:0}\n.g-banner{position:fixed;left:0;right:0;z-index:calc(var(--g-z) + 1);pointer-events:auto;background:var(--g-primary);color:var(--g-primary-text);padding:10px 48px 10px 16px;display:flex;align-items:center;gap:12px;font-size:14px;box-shadow:0 2px 10px rgba(0,0,0,.15);max-width:100vw}\n.g-banner .g-body{flex:1;min-width:0}\n.g-banner .g-body a{color:inherit;text-decoration:underline}\n.g-banner .g-close{color:inherit;right:8px;top:50%;transform:translateY(-50%)}\n.g-banner .g-btn{background:rgba(255,255,255,.18);color:inherit;border-color:transparent;min-height:36px}\n.g-banner.g-pos-top{top:0}.g-banner.g-pos-bottom{bottom:0}\n.g-inner{padding:20px}\n.g-close{position:absolute;top:8px;right:8px;width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--g-muted);border-radius:999px;cursor:pointer;font:inherit;font-size:20px;line-height:1}\n.g-close:hover,.g-close:focus-visible{background:var(--g-subtle);color:var(--g-text);outline:none}\n.g-close:focus-visible,.g-btn:focus-visible,.g-task:focus-visible,.g-choice:focus-visible,.g-scale button:focus-visible,.g-launcher:focus-visible,.g-input:focus-visible,.g-rc-item:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-image{display:block;width:100%;max-height:220px;object-fit:cover;border-radius:var(--g-radius) var(--g-radius) 0 0}\n.g-title{margin:0 28px 6px 0;font-size:16px;font-weight:600;line-height:1.3}\n.g-body{font-size:14px;color:var(--g-text)}\n.g-body p{margin:0 0 8px}.g-body p:last-child{margin-bottom:0}\n.g-body ul,.g-body ol{margin:6px 0;padding-left:20px}\n.g-body a{color:var(--g-primary)}\n.g-body img{max-width:100%;height:auto;border-radius:6px}\n.g-body video,.g-body iframe{display:block;width:100%;max-width:100%;border:0;border-radius:6px;margin:8px 0;background:#000}\n.g-body video{height:auto;max-height:60vh}\n.g-body iframe{aspect-ratio:16/9;height:auto}\n.g-body .gd-pdf{margin:10px 0;border:1px solid var(--g-border);border-radius:10px;background:var(--g-subtle);overflow:hidden}\n.g-body a.gd-file{display:flex;align-items:center;gap:8px;padding:8px 10px;color:var(--g-text);font-size:13px;font-weight:500;text-decoration:none;min-height:40px;overflow-wrap:anywhere}\n.g-body a.gd-file::before{content:\"PDF\";flex:none;font-size:9px;font-weight:700;letter-spacing:.04em;line-height:1;color:#fff;background:#e5484d;border-radius:4px;padding:4px 5px}\n.g-body a.gd-file::after{content:\"\u2922\";margin-left:auto;padding-left:8px;color:var(--g-muted);font-size:15px}\n.g-body a.gd-file:hover::after,.g-body a.gd-file:focus-visible::after{color:var(--g-primary)}\n.g-body a.gd-file:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px;border-radius:10px}\n.g-body > a.gd-file,.g-body p > a.gd-file{margin:10px 0;border:1px solid var(--g-border);border-radius:10px;background:var(--g-subtle)}\n.g-body > a.gd-file::after,.g-body p > a.gd-file::after,.g-body .gd-pdf:not([data-g-ready]) > a.gd-file::after{content:\"\u2197\"}\n.g-pdf-viewport{position:relative}\n.g-body .gd-pdf-pages{display:flex;gap:10px;overflow-x:auto;scroll-snap-type:x mandatory;overscroll-behavior-x:contain;scrollbar-width:none;padding:0 10px 10px;scroll-padding:0 10px}\n.g-body .gd-pdf-pages::-webkit-scrollbar{display:none}\n.g-body .gd-pdf-pages:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px}\n.g-body .gd-pdf-pages img{flex:0 0 100%;width:100%;height:auto;margin:0;scroll-snap-align:center;background:#fff;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.18);cursor:zoom-in}\n.g-pdf-viewport .gd-pdf-pages{padding:0;scroll-padding:0;margin:0 10px 10px}\n.g-pdf-count{position:absolute;right:18px;bottom:18px;padding:2px 8px;border-radius:999px;background:rgba(17,17,17,.72);color:#fff;font-size:11px;font-weight:500;pointer-events:none;font-variant-numeric:tabular-nums}\n.g-pdf-nav{position:absolute;top:calc(50% - 21px);width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:999px;background:rgba(17,17,17,.6);color:#fff;font:inherit;font-size:20px;line-height:1;cursor:pointer;opacity:0;transition:opacity .15s}\n.g-pdf-prev{left:16px}.g-pdf-next{right:16px}\n.g-pdf-viewport:hover .g-pdf-nav,.g-pdf-nav:focus-visible{opacity:1}\n.g-pdf-nav:disabled,.g-pdf-single .g-pdf-nav,.g-pdf-single .g-pdf-count{display:none}\n.g-pdf-nav:focus-visible{outline:2px solid #fff;outline-offset:1px}\n@media (hover:none){.g-pdf-nav{display:none}}\n.g-pdf-reader{position:fixed;inset:0;z-index:calc(var(--g-z) + 10);display:flex;flex-direction:column;background:#0b0b0d;pointer-events:auto;color:#fff}\n.g-pdf-bar{display:flex;align-items:center;gap:10px;padding:8px 8px 8px 16px;min-height:56px}\n.g-pdf-title{flex:1;min-width:0;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.g-pdf-bar .g-btn{min-height:36px;color:#fff;background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.18)}\n.g-pdf-close{position:static;color:#fff}\n.g-pdf-close:hover,.g-pdf-close:focus-visible{background:rgba(255,255,255,.14);color:#fff}\n.g-pdf-scroll{position:relative;flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 24px;display:flex;flex-direction:column;align-items:center;gap:12px;outline:none}\n.g-pdf-scroll img{display:block;width:100%;max-width:900px;height:auto;background:#fff;border-radius:2px;box-shadow:0 2px 12px rgba(0,0,0,.4)}\n.g-body code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;background:var(--g-subtle);padding:1px 4px;border-radius:4px}\n.g-body pre{background:var(--g-subtle);padding:10px;border-radius:6px;overflow:auto}\n.g-body blockquote{margin:6px 0;padding-left:10px;border-left:3px solid var(--g-border);color:var(--g-muted)}\n.g-footer{display:flex;align-items:center;gap:8px;margin-top:14px;flex-wrap:wrap}\n.g-progress{font-size:12px;color:var(--g-muted);margin-right:auto}\n.g-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px;padding:8px 14px;border-radius:calc(var(--g-radius) * .66);border:1px solid transparent;font:inherit;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;transition:background .15s,color .15s,border-color .15s}\n.g-btn-primary{background:var(--g-primary);color:var(--g-primary-text)}\n.g-btn-primary:hover{filter:brightness(1.08)}\n.g-btn-secondary{background:var(--g-subtle);color:var(--g-text);border-color:var(--g-border)}\n.g-btn-secondary:hover{background:color-mix(in srgb,var(--g-text) 10%,transparent)}\n.g-btn-ghost{background:transparent;color:var(--g-muted)}\n.g-btn-ghost:hover{background:var(--g-subtle);color:var(--g-text)}\n.g-btn-link{background:transparent;color:var(--g-primary);padding-left:4px;padding-right:4px}\n.g-btn-link:hover{text-decoration:underline}\n.g-btn:disabled{opacity:.5;cursor:not-allowed}\n.g-arrow{position:absolute;width:12px;height:12px;background:var(--g-bg);transform:rotate(45deg);border:1px solid var(--g-border);z-index:-1}\n.g-hotspot{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;border-radius:999px;background:var(--g-primary);border:2px solid #fff;box-shadow:0 0 0 2px color-mix(in srgb,var(--g-primary) 40%,transparent);cursor:pointer;padding:0;margin:0}\n.g-hotspot::after{content:\"\";position:absolute;inset:-4px;border-radius:999px;border:2px solid var(--g-primary);opacity:0}\n.g-hotspot.g-pulse::after{animation:g-pulse 1.8s ease-out infinite}\n.g-hotspot-hit{position:absolute;inset:-14px}\n.g-custom{position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;left:50%;top:50%;transform:translate(-50%,-50%);max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto}\n/* animations */\n.g-scope[data-anim=\"fade\"] .g-card,.g-scope[data-anim=\"fade\"] .g-banner,.g-scope[data-anim=\"fade\"] .g-panel{animation:g-fade .18s ease-out}\n.g-scope[data-anim=\"slide\"] .g-card,.g-scope[data-anim=\"slide\"] .g-panel{animation:g-slide .22s ease-out}\n.g-scope[data-anim=\"none\"] *{animation:none!important;transition:none!important}\n@keyframes g-fade{from{opacity:0}to{opacity:1}}\n@keyframes g-slide{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}\n@keyframes g-pulse{0%{transform:scale(.6);opacity:.9}100%{transform:scale(2.2);opacity:0}}\n@media (prefers-reduced-motion:reduce){.g-scope *{animation:none!important;transition:none!important}}\n/* launcher + panel (checklist / resource center) */\n.g-launcher{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);font:inherit;font-size:14px;font-weight:600;cursor:pointer;box-shadow:var(--g-shadow);margin:16px}\n.g-launcher .g-ring{width:22px;height:22px;border-radius:999px;background:conic-gradient(#fff var(--g-pct,0%),rgba(255,255,255,.3) 0);display:inline-flex;align-items:center;justify-content:center;font-size:10px;position:relative}\n.g-launcher .g-ring::after{content:\"\";position:absolute;inset:3px;border-radius:999px;background:var(--g-primary)}\n.g-launcher .g-count{position:relative;z-index:1}\n.g-panel{position:fixed;z-index:calc(var(--g-z) + 2);pointer-events:auto;width:min(380px,calc(100vw - 32px));max-height:min(620px,calc(100vh - 100px));display:flex;flex-direction:column;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);box-shadow:var(--g-shadow);border:1px solid var(--g-border);margin:16px;bottom:60px;overflow:hidden}\n.g-panel-head{padding:16px 48px 12px 20px;border-bottom:1px solid var(--g-border);position:relative}\n.g-panel-title{margin:0;font-size:16px;font-weight:600}\n.g-panel-sub{margin:4px 0 0;font-size:12px;color:var(--g-muted)}\n.g-panel-body{overflow:auto;padding:8px 0;flex:1}\n.g-help{display:flex;flex-direction:column;min-height:0;flex:1}\n.g-bar{height:6px;border-radius:999px;background:var(--g-subtle);overflow:hidden;margin-top:10px}\n.g-bar > span{display:block;height:100%;background:var(--g-primary);transition:width .3s}\n.g-task{display:flex;gap:12px;align-items:flex-start;width:100%;padding:12px 20px;border:0;background:transparent;text-align:left;font:inherit;color:inherit;cursor:pointer;min-height:44px}\n.g-task:hover{background:var(--g-subtle)}\n.g-task[disabled]{cursor:not-allowed;opacity:.55}\n.g-task .g-check{flex:none;width:22px;height:22px;border-radius:999px;border:2px solid var(--g-border);display:inline-flex;align-items:center;justify-content:center;font-size:13px;margin-top:1px;color:#fff}\n.g-task.g-done .g-check{background:var(--g-primary);border-color:var(--g-primary)}\n.g-task.g-done .g-task-title{text-decoration:line-through;color:var(--g-muted)}\n.g-task-title{font-weight:500}\n.g-task-desc{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-panel-foot{padding:10px 20px;border-top:1px solid var(--g-border);display:flex;justify-content:flex-end;gap:8px}\n.g-complete{padding:28px 20px;text-align:center}\n.g-complete .g-title{margin-right:0;font-size:18px}\n/* survey */\n.g-question{margin-bottom:16px}\n.g-q-title{font-weight:600;margin:0 0 4px}\n.g-q-desc{font-size:12px;color:var(--g-muted);margin:0 0 8px}\n.g-scale{display:flex;gap:4px;flex-wrap:wrap}\n.g-scale button{min-width:34px;height:40px;flex:1;padding:0 4px;border-radius:6px;border:1px solid var(--g-border);background:var(--g-subtle);color:var(--g-text);font:inherit;cursor:pointer}\n.g-scale button[aria-pressed=\"true\"],.g-scale button:hover{background:var(--g-primary);color:var(--g-primary-text);border-color:var(--g-primary)}\n.g-scale-labels{display:flex;justify-content:space-between;font-size:11px;color:var(--g-muted);margin-top:4px}\n.g-stars button,.g-thumbs button{font-size:22px;background:transparent;border:0;cursor:pointer;color:var(--g-muted);min-width:40px;height:40px;font:inherit}\n.g-stars button[aria-pressed=\"true\"],.g-stars button.g-on{color:#f59e0b}\n.g-thumbs button[aria-pressed=\"true\"]{color:var(--g-primary)}\n.g-choice{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;margin-bottom:6px;cursor:pointer;min-height:40px;font:inherit;background:transparent;color:inherit;width:100%;text-align:left}\n.g-choice[aria-checked=\"true\"]{border-color:var(--g-primary);background:color-mix(in srgb,var(--g-primary) 8%,transparent)}\n.g-choice .g-dot{width:16px;height:16px;border-radius:999px;border:2px solid var(--g-border);flex:none}\n.g-choice.g-multi .g-dot{border-radius:4px}\n.g-choice[aria-checked=\"true\"] .g-dot{background:var(--g-primary);border-color:var(--g-primary)}\n.g-input{width:100%;min-height:40px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;background:var(--g-bg);color:var(--g-text);font:inherit;resize:vertical}\n.g-error{color:#dc2626;font-size:12px;margin-top:4px}\n/* resource center */\n.g-rc-search{padding:12px 20px 4px}\n.g-rc-section{padding:8px 20px 4px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--g-muted);font-weight:600}\n.g-rc-section[data-depth]{text-transform:none;letter-spacing:0;font-size:12px}\n.g-rc-item{display:flex;align-items:flex-start;gap:10px;width:100%;padding:10px 20px;border:0;background:transparent;font:inherit;color:inherit;text-align:left;cursor:pointer;min-height:44px;text-decoration:none}\n.g-rc-item:hover{background:var(--g-subtle)}\n.g-rc-item .g-rc-title{font-weight:500}\n.g-rc-item .g-rc-sum{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-rc-item .g-rc-icon{flex:none;width:20px;text-align:center;color:var(--g-primary)}\n.g-rc-row{display:flex;align-items:center;gap:6px;padding-right:16px}\n.g-rc-row>.g-rc-item{flex:1;min-width:0;padding-right:4px}\n.g-rc-row:hover{background:var(--g-subtle)}\n.g-rc-row:hover>.g-rc-item{background:transparent}\n.g-rc-showme{flex:none;min-height:32px;padding:4px 10px;font-size:12px;white-space:nowrap}\n.g-help-showme{margin:4px 0 12px}\n.g-rc-article{padding:16px 20px}\n.g-resource-center .g-panel{transition:width .2s ease,max-height .2s ease}\n.g-resource-center .g-panel.g-panel-reading{width:min(720px,calc(100vw - 32px));max-height:calc(100vh - 100px)}\n.g-rc-back{margin-bottom:8px}\n.g-rc-empty{padding:24px 20px;color:var(--g-muted);text-align:center}\n.g-faq-a{padding:0 20px 12px 50px;font-size:13px;color:var(--g-muted)}\n.g-faq-a[hidden]{display:none}\n/* authoring */\n.g-auth-bar{position:fixed;top:0;left:0;right:0;z-index:calc(var(--g-z) + 10);pointer-events:auto;display:flex;align-items:center;gap:12px;padding:8px 16px;background:#111827;color:#fff;font:500 13px/1.4 var(--g-font);box-shadow:0 2px 10px rgba(0,0,0,.3)}\n.g-auth-bar .g-dot-live{width:8px;height:8px;border-radius:999px;background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.3)}\n.g-auth-bar .g-spacer{flex:1}\n.g-auth-bar .g-btn{min-height:32px;padding:4px 12px;font-size:13px}\n.g-auth-bar .g-btn-secondary{background:rgba(255,255,255,.12);color:#fff;border-color:transparent}\n.g-auth-outline{position:fixed;z-index:calc(var(--g-z) + 9);pointer-events:none;border:2px solid var(--g-primary);background:color-mix(in srgb,var(--g-primary) 12%,transparent);border-radius:4px;transition:all .06s linear}\n.g-auth-label{position:absolute;left:-2px;top:-24px;background:var(--g-primary);color:#fff;font:600 11px/1 var(--g-font);padding:5px 7px;border-radius:4px;white-space:nowrap;max-width:320px;overflow:hidden;text-overflow:ellipsis}\n.g-auth-outline.g-picked{border-style:dashed;border-color:#22c55e;background:rgba(34,197,94,.12)}\n.g-auth-outline.g-picked .g-auth-label{background:#16a34a}\n.g-highlight{position:fixed;z-index:calc(var(--g-z) + 8);pointer-events:none;border:2px dashed #f59e0b;background:rgba(245,158,11,.12);border-radius:4px}\n@media (max-width:480px){.g-card.g-modal,.g-panel{width:calc(100vw - 32px)}.g-inner{padding:16px}}\n";
407
452
 
408
- export { type AnchorOptions, type AuthoringOptions, type AuthoringSession, type ChecklistProgress, type ChecklistWidget, type ChecklistWidgetOptions, DEFAULT_THEME, type ElementDescription, type GuideController, type GuideEndReason, type GuideStatus, HOST_ID, type HighlightHandle, type HostHandle, type PreviewHandle, type QueryRoot, type RenderStepOptions, type ResolvedThemeMode, type ResourceCenterGuideRef, type ResourceCenterOptions, type ResourceCenterWidget, type RunGuideOptions, type RunnableGuide, type RuntimeEvent, STYLES, type StepView, type SurveyWidget, type SurveyWidgetOptions, TargetTimeoutError, type ThemeVars, type WaitForTargetOptions, anchor, applyTheme, buildCard, createScope, describeElement, destroyHost, enhancePdfViewers, ensureHost, generateSelectors, highlightSelectors, isAnchoredStep, isGuidelyElement, isStableId, isVisible, normalizeText, prefersReducedMotion, previewStep, querySelectorStrategy, renderBanner, renderChecklist, renderCustom, renderHotspot, renderModal, renderResourceCenter, renderSlideout, renderSpotlight, renderStep, renderSurvey, renderTooltip, resolveTarget, resolveTheme, runGuide, sanitizeHtml, sanitizeToFragment, setSanitizedHtml, startAuthoring, textSnapshotOf, trackRect, urlMatches, waitForTarget };
453
+ export { type AnchorOptions, type AuthoringOptions, type AuthoringSession, type ChecklistProgress, type ChecklistWidget, type ChecklistWidgetOptions, DEFAULT_THEME, type ElementDescription, type GuideController, type GuideEndReason, type GuideStatus, HOST_ID, type HighlightHandle, type HostHandle, type PreviewHandle, type QueryRoot, type RenderStepOptions, type ResolvedThemeMode, type ResourceCenterGuideRef, type ResourceCenterOptions, type ResourceCenterWidget, type RunGuideOptions, type RunnableGuide, type RuntimeEvent, SHADOW_SEPARATOR, STYLES, type StepView, type SurveyWidget, type SurveyWidgetOptions, TargetTimeoutError, type ThemeVars, type WaitForTargetOptions, anchor, applyTheme, buildCard, closestComposed, componentAnchor, composedParent, composedTarget, containsComposed, createScope, deepElementFromPoint, describeElement, destroyHost, enhancePdfViewers, ensureHost, generateSelectors, highlightSelectors, isAnchoredStep, isGuidelyElement, isStableId, isVisible, normalizeText, prefersReducedMotion, previewStep, querySelectorStrategy, renderBanner, renderChecklist, renderCustom, renderHotspot, renderModal, renderResourceCenter, renderSlideout, renderSpotlight, renderStep, renderSurvey, renderTooltip, resolveTarget, resolveTheme, runGuide, sanitizeHtml, sanitizeToFragment, setSanitizedHtml, shadowHostChain, startAuthoring, textSnapshotOf, trackRect, urlMatches, visualRect, waitForTarget };
package/dist/index.d.ts CHANGED
@@ -17,11 +17,32 @@ declare function normalizeText(text: string | null | undefined): string;
17
17
  declare function isVisible(el: Element): boolean;
18
18
  /** Elements that belong to Guidely's own UI are never valid targets. */
19
19
  declare function isGuidelyElement(el: Element | null): boolean;
20
- /** Resolves every element matching one strategy (visible or not). */
21
- declare function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot): Element[];
20
+ /** Separates the shadow-host steps of a CSS selector (`>>>` is not valid CSS, so it never clashes). */
21
+ declare const SHADOW_SEPARATOR = " >>> ";
22
+ /** The element's parent in the composed tree: its parent element, or its shadow host at the top of a shadow root. */
23
+ declare function composedParent(el: Element): Element | null;
24
+ /** Does `ancestor` contain `node`, looking through shadow boundaries? */
25
+ declare function containsComposed(ancestor: Element, node: Node | null): boolean;
26
+ /** The element an event really started on: inside a shadow root `e.target` is retargeted to the host. */
27
+ declare function composedTarget(e: Event): Element | null;
28
+ /**
29
+ * `Element.closest` across shadow boundaries: the nearest element, from `el` up through its shadow
30
+ * hosts, that matches `selector` (which may be a `>>>` chain). Throws on an invalid plain selector,
31
+ * like `closest` does.
32
+ */
33
+ declare function closestComposed(el: Element, selector: string): Element | null;
34
+ /** The innermost element at a point, looking inside open shadow roots (`elementFromPoint` stops at the host). */
35
+ declare function deepElementFromPoint(doc: Document, x: number, y: number): Element | null;
36
+ /**
37
+ * Resolves every element matching one strategy (visible or not). `deep` (the default) also searches
38
+ * open shadow roots; `>>>` chains are always followed. XPath cannot cross shadow boundaries.
39
+ */
40
+ declare function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot, deep?: boolean): Element[];
22
41
  /**
23
42
  * Resolves a step target by trying each strategy in order. A strategy wins only when it
24
- * resolves to exactly one *visible* element; otherwise the next strategy is tried.
43
+ * resolves to exactly one *visible* element; otherwise the next strategy is tried. Each strategy
44
+ * looks in the document first and only searches shadow roots when nothing there is visible, so a
45
+ * target that resolved before shadow-DOM support still resolves to the same element.
25
46
  */
26
47
  declare function resolveTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], root?: QueryRoot): Element | null;
27
48
  interface WaitForTargetOptions {
@@ -39,11 +60,17 @@ declare class TargetTimeoutError extends Error {
39
60
  }
40
61
  /**
41
62
  * Waits until `resolveTarget` finds an element. Uses a MutationObserver plus a polling fallback
42
- * (at most every 250ms) so visibility changes without DOM mutations are also detected.
63
+ * (at most every 250ms) so visibility changes without DOM mutations, and changes inside shadow
64
+ * roots (which the observer does not see), are also detected.
43
65
  */
44
66
  declare function waitForTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], options?: WaitForTargetOptions): Promise<Element>;
45
67
  /** Is this id stable enough to be used as a selector (not generated by a framework)? */
46
68
  declare function isStableId(id: string): boolean;
69
+ /**
70
+ * The `>>>` chain of shadow hosts above an element (`c-app >>> c-form`), or "" for an element in
71
+ * the document itself; null when some host has no unique path within its own root.
72
+ */
73
+ declare function shadowHostChain(el: Element): string | null;
47
74
  /** Short human-readable text for an element, trimmed to 200 characters. */
48
75
  declare function textSnapshotOf(el: Element): string;
49
76
  /**
@@ -62,7 +89,25 @@ interface ElementDescription {
62
89
  };
63
90
  tag: string;
64
91
  }
65
- /** Everything the authoring picker needs for one element. */
92
+ /**
93
+ * An element's on-screen box. For a shadow host that is its own box joined with its shadow content's:
94
+ * an `inline` host (the default for custom elements) is only a line tall around a taller button, and
95
+ * a `display: contents` host has no box at all.
96
+ */
97
+ declare function visualRect(el: Element): DOMRect;
98
+ /**
99
+ * The element a pick should target. Inside a component (a shadow host) that is little more than the
100
+ * picked control (`lightning-button` around its `<button>`, also when the pick is the button's icon;
101
+ * `lightning-input` around its label and field), that is the component itself: the app's markup around a component is the app's, while a
102
+ * design system can change a component's internals in any release. Repeats up nested components and
103
+ * stops at the first one that is clearly more (a list, a form, the whole app). Without layout (tests,
104
+ * hidden pages) the element is kept.
105
+ */
106
+ declare function componentAnchor(el: Element): Element;
107
+ /**
108
+ * Everything the authoring picker and how-to capture need for one element. Selectors and rect are
109
+ * for its `componentAnchor`; the text falls back to the element's own.
110
+ */
66
111
  declare function describeElement(el: Element): ElementDescription;
67
112
 
68
113
  /**
@@ -137,7 +182,7 @@ interface AnchorOptions {
137
182
  * Anchors `floating` next to `reference` using floating-ui (`flip`, `shift`, `offset`, `arrow`).
138
183
  * `placement: "auto"` uses `autoPlacement`. Returns a cleanup function that stops `autoUpdate`.
139
184
  */
140
- declare function anchor(reference: Element, floating: HTMLElement, options?: AnchorOptions): () => void;
185
+ declare function anchor(target: Element, floating: HTMLElement, options?: AnchorOptions): () => void;
141
186
  /** Tracks the bounding rect of an element and calls `cb` on scroll/resize/mutation. */
142
187
  declare function trackRect(el: Element, cb: (rect: DOMRect) => void): () => void;
143
188
 
@@ -405,4 +450,4 @@ declare function highlightSelectors(selectors: SelectorStrategy[], options?: {
405
450
  /** All runtime CSS, injected once into the Shadow DOM host. Tokens are CSS custom properties. */
406
451
  declare const STYLES = "\n:host{all:initial;position:static;display:block;contain:none}\n*,*::before,*::after{box-sizing:border-box}\n.g-scope [hidden]{display:none!important}\n.g-scope{\n --g-primary:#4f46e5;--g-bg:#ffffff;--g-text:#111827;--g-radius:12px;--g-font:Inter,system-ui,-apple-system,sans-serif;--g-z:2147483000;--g-overlay:.5;\n --g-muted:color-mix(in srgb,var(--g-text) 62%,transparent);--g-border:color-mix(in srgb,var(--g-text) 12%,transparent);\n --g-subtle:color-mix(in srgb,var(--g-text) 5%,transparent);--g-shadow:0 10px 40px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.08);\n --g-primary-text:#ffffff;\n font-family:var(--g-font);font-size:14px;line-height:1.5;color:var(--g-text);-webkit-font-smoothing:antialiased;\n}\n.g-scope[data-theme=\"dark\"]{--g-shadow:0 10px 40px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3)}\n.g-live{position:fixed;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n.g-layer{position:fixed;inset:0;z-index:var(--g-z);pointer-events:none}\n.g-overlay{position:fixed;inset:0;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-overlay.g-transparent{background:transparent}\n.g-spot-rect{position:fixed;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-spot-ring{position:fixed;z-index:calc(var(--g-z) + 3);pointer-events:none;border-radius:6px;box-shadow:0 0 0 2px var(--g-primary),0 0 0 6px color-mix(in srgb,var(--g-primary) 30%,transparent)}\n.g-card{\n position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);\n box-shadow:var(--g-shadow);border:1px solid var(--g-border);width:min(360px,calc(100vw - 32px));max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto;outline:none;\n}\n.g-card.g-modal{left:50%;top:50%;transform:translate(-50%,-50%);width:min(480px,calc(100vw - 32px))}\n.g-card.g-tooltip,.g-card.g-popover,.g-card.g-spotlight-card,.g-card.g-hotspot-card{top:0;left:0;width:min(320px,calc(100vw - 32px))}\n.g-card.g-slideout{width:min(360px,calc(100vw - 32px));margin:16px}\n.g-pos-bottom-right{right:0;bottom:0}.g-pos-bottom-left{left:0;bottom:0}.g-pos-top-right{right:0;top:0}.g-pos-top-left{left:0;top:0}\n.g-pos-center{left:50%;top:50%;transform:translate(-50%,-50%)}\n.g-pos-top{top:0;left:0;right:0}.g-pos-bottom{bottom:0;left:0;right:0}\n.g-banner{position:fixed;left:0;right:0;z-index:calc(var(--g-z) + 1);pointer-events:auto;background:var(--g-primary);color:var(--g-primary-text);padding:10px 48px 10px 16px;display:flex;align-items:center;gap:12px;font-size:14px;box-shadow:0 2px 10px rgba(0,0,0,.15);max-width:100vw}\n.g-banner .g-body{flex:1;min-width:0}\n.g-banner .g-body a{color:inherit;text-decoration:underline}\n.g-banner .g-close{color:inherit;right:8px;top:50%;transform:translateY(-50%)}\n.g-banner .g-btn{background:rgba(255,255,255,.18);color:inherit;border-color:transparent;min-height:36px}\n.g-banner.g-pos-top{top:0}.g-banner.g-pos-bottom{bottom:0}\n.g-inner{padding:20px}\n.g-close{position:absolute;top:8px;right:8px;width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--g-muted);border-radius:999px;cursor:pointer;font:inherit;font-size:20px;line-height:1}\n.g-close:hover,.g-close:focus-visible{background:var(--g-subtle);color:var(--g-text);outline:none}\n.g-close:focus-visible,.g-btn:focus-visible,.g-task:focus-visible,.g-choice:focus-visible,.g-scale button:focus-visible,.g-launcher:focus-visible,.g-input:focus-visible,.g-rc-item:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-image{display:block;width:100%;max-height:220px;object-fit:cover;border-radius:var(--g-radius) var(--g-radius) 0 0}\n.g-title{margin:0 28px 6px 0;font-size:16px;font-weight:600;line-height:1.3}\n.g-body{font-size:14px;color:var(--g-text)}\n.g-body p{margin:0 0 8px}.g-body p:last-child{margin-bottom:0}\n.g-body ul,.g-body ol{margin:6px 0;padding-left:20px}\n.g-body a{color:var(--g-primary)}\n.g-body img{max-width:100%;height:auto;border-radius:6px}\n.g-body video,.g-body iframe{display:block;width:100%;max-width:100%;border:0;border-radius:6px;margin:8px 0;background:#000}\n.g-body video{height:auto;max-height:60vh}\n.g-body iframe{aspect-ratio:16/9;height:auto}\n.g-body .gd-pdf{margin:10px 0;border:1px solid var(--g-border);border-radius:10px;background:var(--g-subtle);overflow:hidden}\n.g-body a.gd-file{display:flex;align-items:center;gap:8px;padding:8px 10px;color:var(--g-text);font-size:13px;font-weight:500;text-decoration:none;min-height:40px;overflow-wrap:anywhere}\n.g-body a.gd-file::before{content:\"PDF\";flex:none;font-size:9px;font-weight:700;letter-spacing:.04em;line-height:1;color:#fff;background:#e5484d;border-radius:4px;padding:4px 5px}\n.g-body a.gd-file::after{content:\"\u2922\";margin-left:auto;padding-left:8px;color:var(--g-muted);font-size:15px}\n.g-body a.gd-file:hover::after,.g-body a.gd-file:focus-visible::after{color:var(--g-primary)}\n.g-body a.gd-file:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px;border-radius:10px}\n.g-body > a.gd-file,.g-body p > a.gd-file{margin:10px 0;border:1px solid var(--g-border);border-radius:10px;background:var(--g-subtle)}\n.g-body > a.gd-file::after,.g-body p > a.gd-file::after,.g-body .gd-pdf:not([data-g-ready]) > a.gd-file::after{content:\"\u2197\"}\n.g-pdf-viewport{position:relative}\n.g-body .gd-pdf-pages{display:flex;gap:10px;overflow-x:auto;scroll-snap-type:x mandatory;overscroll-behavior-x:contain;scrollbar-width:none;padding:0 10px 10px;scroll-padding:0 10px}\n.g-body .gd-pdf-pages::-webkit-scrollbar{display:none}\n.g-body .gd-pdf-pages:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px}\n.g-body .gd-pdf-pages img{flex:0 0 100%;width:100%;height:auto;margin:0;scroll-snap-align:center;background:#fff;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.18);cursor:zoom-in}\n.g-pdf-viewport .gd-pdf-pages{padding:0;scroll-padding:0;margin:0 10px 10px}\n.g-pdf-count{position:absolute;right:18px;bottom:18px;padding:2px 8px;border-radius:999px;background:rgba(17,17,17,.72);color:#fff;font-size:11px;font-weight:500;pointer-events:none;font-variant-numeric:tabular-nums}\n.g-pdf-nav{position:absolute;top:calc(50% - 21px);width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:999px;background:rgba(17,17,17,.6);color:#fff;font:inherit;font-size:20px;line-height:1;cursor:pointer;opacity:0;transition:opacity .15s}\n.g-pdf-prev{left:16px}.g-pdf-next{right:16px}\n.g-pdf-viewport:hover .g-pdf-nav,.g-pdf-nav:focus-visible{opacity:1}\n.g-pdf-nav:disabled,.g-pdf-single .g-pdf-nav,.g-pdf-single .g-pdf-count{display:none}\n.g-pdf-nav:focus-visible{outline:2px solid #fff;outline-offset:1px}\n@media (hover:none){.g-pdf-nav{display:none}}\n.g-pdf-reader{position:fixed;inset:0;z-index:calc(var(--g-z) + 10);display:flex;flex-direction:column;background:#0b0b0d;pointer-events:auto;color:#fff}\n.g-pdf-bar{display:flex;align-items:center;gap:10px;padding:8px 8px 8px 16px;min-height:56px}\n.g-pdf-title{flex:1;min-width:0;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.g-pdf-bar .g-btn{min-height:36px;color:#fff;background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.18)}\n.g-pdf-close{position:static;color:#fff}\n.g-pdf-close:hover,.g-pdf-close:focus-visible{background:rgba(255,255,255,.14);color:#fff}\n.g-pdf-scroll{position:relative;flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 24px;display:flex;flex-direction:column;align-items:center;gap:12px;outline:none}\n.g-pdf-scroll img{display:block;width:100%;max-width:900px;height:auto;background:#fff;border-radius:2px;box-shadow:0 2px 12px rgba(0,0,0,.4)}\n.g-body code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;background:var(--g-subtle);padding:1px 4px;border-radius:4px}\n.g-body pre{background:var(--g-subtle);padding:10px;border-radius:6px;overflow:auto}\n.g-body blockquote{margin:6px 0;padding-left:10px;border-left:3px solid var(--g-border);color:var(--g-muted)}\n.g-footer{display:flex;align-items:center;gap:8px;margin-top:14px;flex-wrap:wrap}\n.g-progress{font-size:12px;color:var(--g-muted);margin-right:auto}\n.g-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px;padding:8px 14px;border-radius:calc(var(--g-radius) * .66);border:1px solid transparent;font:inherit;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;transition:background .15s,color .15s,border-color .15s}\n.g-btn-primary{background:var(--g-primary);color:var(--g-primary-text)}\n.g-btn-primary:hover{filter:brightness(1.08)}\n.g-btn-secondary{background:var(--g-subtle);color:var(--g-text);border-color:var(--g-border)}\n.g-btn-secondary:hover{background:color-mix(in srgb,var(--g-text) 10%,transparent)}\n.g-btn-ghost{background:transparent;color:var(--g-muted)}\n.g-btn-ghost:hover{background:var(--g-subtle);color:var(--g-text)}\n.g-btn-link{background:transparent;color:var(--g-primary);padding-left:4px;padding-right:4px}\n.g-btn-link:hover{text-decoration:underline}\n.g-btn:disabled{opacity:.5;cursor:not-allowed}\n.g-arrow{position:absolute;width:12px;height:12px;background:var(--g-bg);transform:rotate(45deg);border:1px solid var(--g-border);z-index:-1}\n.g-hotspot{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;border-radius:999px;background:var(--g-primary);border:2px solid #fff;box-shadow:0 0 0 2px color-mix(in srgb,var(--g-primary) 40%,transparent);cursor:pointer;padding:0;margin:0}\n.g-hotspot::after{content:\"\";position:absolute;inset:-4px;border-radius:999px;border:2px solid var(--g-primary);opacity:0}\n.g-hotspot.g-pulse::after{animation:g-pulse 1.8s ease-out infinite}\n.g-hotspot-hit{position:absolute;inset:-14px}\n.g-custom{position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;left:50%;top:50%;transform:translate(-50%,-50%);max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto}\n/* animations */\n.g-scope[data-anim=\"fade\"] .g-card,.g-scope[data-anim=\"fade\"] .g-banner,.g-scope[data-anim=\"fade\"] .g-panel{animation:g-fade .18s ease-out}\n.g-scope[data-anim=\"slide\"] .g-card,.g-scope[data-anim=\"slide\"] .g-panel{animation:g-slide .22s ease-out}\n.g-scope[data-anim=\"none\"] *{animation:none!important;transition:none!important}\n@keyframes g-fade{from{opacity:0}to{opacity:1}}\n@keyframes g-slide{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}\n@keyframes g-pulse{0%{transform:scale(.6);opacity:.9}100%{transform:scale(2.2);opacity:0}}\n@media (prefers-reduced-motion:reduce){.g-scope *{animation:none!important;transition:none!important}}\n/* launcher + panel (checklist / resource center) */\n.g-launcher{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);font:inherit;font-size:14px;font-weight:600;cursor:pointer;box-shadow:var(--g-shadow);margin:16px}\n.g-launcher .g-ring{width:22px;height:22px;border-radius:999px;background:conic-gradient(#fff var(--g-pct,0%),rgba(255,255,255,.3) 0);display:inline-flex;align-items:center;justify-content:center;font-size:10px;position:relative}\n.g-launcher .g-ring::after{content:\"\";position:absolute;inset:3px;border-radius:999px;background:var(--g-primary)}\n.g-launcher .g-count{position:relative;z-index:1}\n.g-panel{position:fixed;z-index:calc(var(--g-z) + 2);pointer-events:auto;width:min(380px,calc(100vw - 32px));max-height:min(620px,calc(100vh - 100px));display:flex;flex-direction:column;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);box-shadow:var(--g-shadow);border:1px solid var(--g-border);margin:16px;bottom:60px;overflow:hidden}\n.g-panel-head{padding:16px 48px 12px 20px;border-bottom:1px solid var(--g-border);position:relative}\n.g-panel-title{margin:0;font-size:16px;font-weight:600}\n.g-panel-sub{margin:4px 0 0;font-size:12px;color:var(--g-muted)}\n.g-panel-body{overflow:auto;padding:8px 0;flex:1}\n.g-help{display:flex;flex-direction:column;min-height:0;flex:1}\n.g-bar{height:6px;border-radius:999px;background:var(--g-subtle);overflow:hidden;margin-top:10px}\n.g-bar > span{display:block;height:100%;background:var(--g-primary);transition:width .3s}\n.g-task{display:flex;gap:12px;align-items:flex-start;width:100%;padding:12px 20px;border:0;background:transparent;text-align:left;font:inherit;color:inherit;cursor:pointer;min-height:44px}\n.g-task:hover{background:var(--g-subtle)}\n.g-task[disabled]{cursor:not-allowed;opacity:.55}\n.g-task .g-check{flex:none;width:22px;height:22px;border-radius:999px;border:2px solid var(--g-border);display:inline-flex;align-items:center;justify-content:center;font-size:13px;margin-top:1px;color:#fff}\n.g-task.g-done .g-check{background:var(--g-primary);border-color:var(--g-primary)}\n.g-task.g-done .g-task-title{text-decoration:line-through;color:var(--g-muted)}\n.g-task-title{font-weight:500}\n.g-task-desc{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-panel-foot{padding:10px 20px;border-top:1px solid var(--g-border);display:flex;justify-content:flex-end;gap:8px}\n.g-complete{padding:28px 20px;text-align:center}\n.g-complete .g-title{margin-right:0;font-size:18px}\n/* survey */\n.g-question{margin-bottom:16px}\n.g-q-title{font-weight:600;margin:0 0 4px}\n.g-q-desc{font-size:12px;color:var(--g-muted);margin:0 0 8px}\n.g-scale{display:flex;gap:4px;flex-wrap:wrap}\n.g-scale button{min-width:34px;height:40px;flex:1;padding:0 4px;border-radius:6px;border:1px solid var(--g-border);background:var(--g-subtle);color:var(--g-text);font:inherit;cursor:pointer}\n.g-scale button[aria-pressed=\"true\"],.g-scale button:hover{background:var(--g-primary);color:var(--g-primary-text);border-color:var(--g-primary)}\n.g-scale-labels{display:flex;justify-content:space-between;font-size:11px;color:var(--g-muted);margin-top:4px}\n.g-stars button,.g-thumbs button{font-size:22px;background:transparent;border:0;cursor:pointer;color:var(--g-muted);min-width:40px;height:40px;font:inherit}\n.g-stars button[aria-pressed=\"true\"],.g-stars button.g-on{color:#f59e0b}\n.g-thumbs button[aria-pressed=\"true\"]{color:var(--g-primary)}\n.g-choice{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;margin-bottom:6px;cursor:pointer;min-height:40px;font:inherit;background:transparent;color:inherit;width:100%;text-align:left}\n.g-choice[aria-checked=\"true\"]{border-color:var(--g-primary);background:color-mix(in srgb,var(--g-primary) 8%,transparent)}\n.g-choice .g-dot{width:16px;height:16px;border-radius:999px;border:2px solid var(--g-border);flex:none}\n.g-choice.g-multi .g-dot{border-radius:4px}\n.g-choice[aria-checked=\"true\"] .g-dot{background:var(--g-primary);border-color:var(--g-primary)}\n.g-input{width:100%;min-height:40px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;background:var(--g-bg);color:var(--g-text);font:inherit;resize:vertical}\n.g-error{color:#dc2626;font-size:12px;margin-top:4px}\n/* resource center */\n.g-rc-search{padding:12px 20px 4px}\n.g-rc-section{padding:8px 20px 4px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--g-muted);font-weight:600}\n.g-rc-section[data-depth]{text-transform:none;letter-spacing:0;font-size:12px}\n.g-rc-item{display:flex;align-items:flex-start;gap:10px;width:100%;padding:10px 20px;border:0;background:transparent;font:inherit;color:inherit;text-align:left;cursor:pointer;min-height:44px;text-decoration:none}\n.g-rc-item:hover{background:var(--g-subtle)}\n.g-rc-item .g-rc-title{font-weight:500}\n.g-rc-item .g-rc-sum{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-rc-item .g-rc-icon{flex:none;width:20px;text-align:center;color:var(--g-primary)}\n.g-rc-row{display:flex;align-items:center;gap:6px;padding-right:16px}\n.g-rc-row>.g-rc-item{flex:1;min-width:0;padding-right:4px}\n.g-rc-row:hover{background:var(--g-subtle)}\n.g-rc-row:hover>.g-rc-item{background:transparent}\n.g-rc-showme{flex:none;min-height:32px;padding:4px 10px;font-size:12px;white-space:nowrap}\n.g-help-showme{margin:4px 0 12px}\n.g-rc-article{padding:16px 20px}\n.g-resource-center .g-panel{transition:width .2s ease,max-height .2s ease}\n.g-resource-center .g-panel.g-panel-reading{width:min(720px,calc(100vw - 32px));max-height:calc(100vh - 100px)}\n.g-rc-back{margin-bottom:8px}\n.g-rc-empty{padding:24px 20px;color:var(--g-muted);text-align:center}\n.g-faq-a{padding:0 20px 12px 50px;font-size:13px;color:var(--g-muted)}\n.g-faq-a[hidden]{display:none}\n/* authoring */\n.g-auth-bar{position:fixed;top:0;left:0;right:0;z-index:calc(var(--g-z) + 10);pointer-events:auto;display:flex;align-items:center;gap:12px;padding:8px 16px;background:#111827;color:#fff;font:500 13px/1.4 var(--g-font);box-shadow:0 2px 10px rgba(0,0,0,.3)}\n.g-auth-bar .g-dot-live{width:8px;height:8px;border-radius:999px;background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.3)}\n.g-auth-bar .g-spacer{flex:1}\n.g-auth-bar .g-btn{min-height:32px;padding:4px 12px;font-size:13px}\n.g-auth-bar .g-btn-secondary{background:rgba(255,255,255,.12);color:#fff;border-color:transparent}\n.g-auth-outline{position:fixed;z-index:calc(var(--g-z) + 9);pointer-events:none;border:2px solid var(--g-primary);background:color-mix(in srgb,var(--g-primary) 12%,transparent);border-radius:4px;transition:all .06s linear}\n.g-auth-label{position:absolute;left:-2px;top:-24px;background:var(--g-primary);color:#fff;font:600 11px/1 var(--g-font);padding:5px 7px;border-radius:4px;white-space:nowrap;max-width:320px;overflow:hidden;text-overflow:ellipsis}\n.g-auth-outline.g-picked{border-style:dashed;border-color:#22c55e;background:rgba(34,197,94,.12)}\n.g-auth-outline.g-picked .g-auth-label{background:#16a34a}\n.g-highlight{position:fixed;z-index:calc(var(--g-z) + 8);pointer-events:none;border:2px dashed #f59e0b;background:rgba(245,158,11,.12);border-radius:4px}\n@media (max-width:480px){.g-card.g-modal,.g-panel{width:calc(100vw - 32px)}.g-inner{padding:16px}}\n";
407
452
 
408
- export { type AnchorOptions, type AuthoringOptions, type AuthoringSession, type ChecklistProgress, type ChecklistWidget, type ChecklistWidgetOptions, DEFAULT_THEME, type ElementDescription, type GuideController, type GuideEndReason, type GuideStatus, HOST_ID, type HighlightHandle, type HostHandle, type PreviewHandle, type QueryRoot, type RenderStepOptions, type ResolvedThemeMode, type ResourceCenterGuideRef, type ResourceCenterOptions, type ResourceCenterWidget, type RunGuideOptions, type RunnableGuide, type RuntimeEvent, STYLES, type StepView, type SurveyWidget, type SurveyWidgetOptions, TargetTimeoutError, type ThemeVars, type WaitForTargetOptions, anchor, applyTheme, buildCard, createScope, describeElement, destroyHost, enhancePdfViewers, ensureHost, generateSelectors, highlightSelectors, isAnchoredStep, isGuidelyElement, isStableId, isVisible, normalizeText, prefersReducedMotion, previewStep, querySelectorStrategy, renderBanner, renderChecklist, renderCustom, renderHotspot, renderModal, renderResourceCenter, renderSlideout, renderSpotlight, renderStep, renderSurvey, renderTooltip, resolveTarget, resolveTheme, runGuide, sanitizeHtml, sanitizeToFragment, setSanitizedHtml, startAuthoring, textSnapshotOf, trackRect, urlMatches, waitForTarget };
453
+ export { type AnchorOptions, type AuthoringOptions, type AuthoringSession, type ChecklistProgress, type ChecklistWidget, type ChecklistWidgetOptions, DEFAULT_THEME, type ElementDescription, type GuideController, type GuideEndReason, type GuideStatus, HOST_ID, type HighlightHandle, type HostHandle, type PreviewHandle, type QueryRoot, type RenderStepOptions, type ResolvedThemeMode, type ResourceCenterGuideRef, type ResourceCenterOptions, type ResourceCenterWidget, type RunGuideOptions, type RunnableGuide, type RuntimeEvent, SHADOW_SEPARATOR, STYLES, type StepView, type SurveyWidget, type SurveyWidgetOptions, TargetTimeoutError, type ThemeVars, type WaitForTargetOptions, anchor, applyTheme, buildCard, closestComposed, componentAnchor, composedParent, composedTarget, containsComposed, createScope, deepElementFromPoint, describeElement, destroyHost, enhancePdfViewers, ensureHost, generateSelectors, highlightSelectors, isAnchoredStep, isGuidelyElement, isStableId, isVisible, normalizeText, prefersReducedMotion, previewStep, querySelectorStrategy, renderBanner, renderChecklist, renderCustom, renderHotspot, renderModal, renderResourceCenter, renderSlideout, renderSpotlight, renderStep, renderSurvey, renderTooltip, resolveTarget, resolveTheme, runGuide, sanitizeHtml, sanitizeToFragment, setSanitizedHtml, shadowHostChain, startAuthoring, textSnapshotOf, trackRect, urlMatches, visualRect, waitForTarget };
package/dist/index.js CHANGED
@@ -7,7 +7,14 @@ import {
7
7
  setSanitizedHtml
8
8
  } from "./chunk-KJRXCITD.js";
9
9
  import {
10
+ SHADOW_SEPARATOR,
10
11
  TargetTimeoutError,
12
+ closestComposed,
13
+ componentAnchor,
14
+ composedParent,
15
+ composedTarget,
16
+ containsComposed,
17
+ deepElementFromPoint,
11
18
  describeElement,
12
19
  generateSelectors,
13
20
  isGuidelyElement,
@@ -16,10 +23,12 @@ import {
16
23
  normalizeText,
17
24
  querySelectorStrategy,
18
25
  resolveTarget,
26
+ shadowHostChain,
19
27
  textSnapshotOf,
20
28
  urlMatches,
29
+ visualRect,
21
30
  waitForTarget
22
- } from "./chunk-VNJPNGZ4.js";
31
+ } from "./chunk-GUH2PQJ7.js";
23
32
  import {
24
33
  DEFAULT_THEME,
25
34
  HOST_ID,
@@ -34,7 +43,8 @@ import {
34
43
 
35
44
  // src/position.ts
36
45
  import { arrow, autoPlacement, autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
37
- function anchor(reference, floating, options = {}) {
46
+ function anchor(target, floating, options = {}) {
47
+ const reference = target.shadowRoot ? { getBoundingClientRect: () => visualRect(target), contextElement: target } : target;
38
48
  const placement = options.placement ?? "auto";
39
49
  const gap = options.offset ?? 10;
40
50
  const middleware = [offset(gap + (options.arrowEl ? 4 : 0))];
@@ -87,7 +97,7 @@ function trackRect(el2, cb) {
87
97
  let stopped = false;
88
98
  const run = () => {
89
99
  if (stopped) return;
90
- cb(el2.getBoundingClientRect());
100
+ cb(visualRect(el2));
91
101
  };
92
102
  const schedule = () => {
93
103
  if (stopped) return;
@@ -100,6 +110,9 @@ function trackRect(el2, cb) {
100
110
  const win = el2.ownerDocument.defaultView;
101
111
  win?.addEventListener("scroll", schedule, true);
102
112
  win?.addEventListener("resize", schedule);
113
+ const shadowRoots = [];
114
+ for (let root = el2.getRootNode(); root.nodeType === 11 && root.host; root = root.host.getRootNode()) shadowRoots.push(root);
115
+ for (const root of shadowRoots) root.addEventListener("scroll", schedule, true);
103
116
  let ro = null;
104
117
  if (typeof ResizeObserver !== "undefined") {
105
118
  try {
@@ -115,6 +128,7 @@ function trackRect(el2, cb) {
115
128
  stopped = true;
116
129
  win?.removeEventListener("scroll", schedule, true);
117
130
  win?.removeEventListener("resize", schedule);
131
+ for (const root of shadowRoots) root.removeEventListener("scroll", schedule, true);
118
132
  ro?.disconnect();
119
133
  clearInterval(interval);
120
134
  if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(raf);
@@ -662,9 +676,9 @@ function runGuide(guide, options = {}) {
662
676
  if (mode === "element_click" && (step.advanceValue || target)) {
663
677
  const selector = step.advanceValue;
664
678
  const handler = (e) => {
665
- const t = e.target;
679
+ const t = composedTarget(e);
666
680
  try {
667
- if (selector ? t && typeof t.closest === "function" && t.closest(selector) : t && target?.contains(t)) advance();
681
+ if (selector ? t && closestComposed(t, selector) : t && target && containsComposed(target, t)) advance();
668
682
  } catch {
669
683
  }
670
684
  };
@@ -1429,7 +1443,7 @@ function startAuthoring(options) {
1429
1443
  outline.hidden = true;
1430
1444
  return;
1431
1445
  }
1432
- const r = el2.getBoundingClientRect();
1446
+ const r = visualRect(el2);
1433
1447
  outline.hidden = false;
1434
1448
  outline.classList.toggle("g-picked", picked);
1435
1449
  Object.assign(outline.style, { left: `${r.left}px`, top: `${r.top}px`, width: `${r.width}px`, height: `${r.height}px` });
@@ -1437,9 +1451,9 @@ function startAuthoring(options) {
1437
1451
  label.style.top = r.top < 30 ? "100%" : "-24px";
1438
1452
  };
1439
1453
  const elementAt = (x, y) => {
1440
- const el2 = doc.elementFromPoint(x, y);
1454
+ const el2 = deepElementFromPoint(doc, x, y);
1441
1455
  if (!el2 || isGuidelyElement(el2) || el2 === doc.documentElement || el2 === doc.body) return null;
1442
- return el2;
1456
+ return componentAnchor(el2);
1443
1457
  };
1444
1458
  const onMove = (e) => {
1445
1459
  if (!picking || stopped) return;
@@ -1454,7 +1468,7 @@ function startAuthoring(options) {
1454
1468
  };
1455
1469
  const onClick = (e) => {
1456
1470
  if (!picking || stopped) return;
1457
- if (e.target && isGuidelyElement(e.target)) return;
1471
+ if (isGuidelyElement(composedTarget(e))) return;
1458
1472
  const el2 = elementAt(e.clientX, e.clientY) ?? hovered;
1459
1473
  if (!el2) return;
1460
1474
  e.preventDefault();
@@ -1467,8 +1481,7 @@ function startAuthoring(options) {
1467
1481
  };
1468
1482
  const swallow = (e) => {
1469
1483
  if (!picking || stopped) return;
1470
- const t = e.target;
1471
- if (t && isGuidelyElement(t)) return;
1484
+ if (isGuidelyElement(composedTarget(e))) return;
1472
1485
  e.preventDefault();
1473
1486
  e.stopPropagation();
1474
1487
  };
@@ -1539,17 +1552,15 @@ function highlightSelectors(selectors, options = {}) {
1539
1552
  const scope = createScope(null, { theme: "light", animation: "none" }, doc);
1540
1553
  const boxes = [];
1541
1554
  const counts = [];
1542
- let resolved = null;
1555
+ const resolved = resolveTarget(selectors, doc);
1543
1556
  const matched = /* @__PURE__ */ new Set();
1544
1557
  selectors.forEach((s) => {
1545
1558
  const els = querySelectorStrategy(s, doc).filter((el2) => !isGuidelyElement(el2));
1546
- const visible = els.filter(isVisible);
1547
1559
  counts.push(els.length);
1548
- if (!resolved && visible.length === 1) resolved = visible[0];
1549
1560
  els.forEach((el2) => matched.add(el2));
1550
1561
  });
1551
1562
  matched.forEach((el2) => {
1552
- const r = el2.getBoundingClientRect();
1563
+ const r = visualRect(el2);
1553
1564
  const box = doc.createElement("div");
1554
1565
  box.className = "g-highlight";
1555
1566
  Object.assign(box.style, { left: `${r.left}px`, top: `${r.top}px`, width: `${r.width}px`, height: `${r.height}px` });
@@ -1569,12 +1580,19 @@ function highlightSelectors(selectors, options = {}) {
1569
1580
  export {
1570
1581
  DEFAULT_THEME,
1571
1582
  HOST_ID,
1583
+ SHADOW_SEPARATOR,
1572
1584
  STYLES,
1573
1585
  TargetTimeoutError,
1574
1586
  anchor,
1575
1587
  applyTheme,
1576
1588
  buildCard,
1589
+ closestComposed,
1590
+ componentAnchor,
1591
+ composedParent,
1592
+ composedTarget,
1593
+ containsComposed,
1577
1594
  createScope,
1595
+ deepElementFromPoint,
1578
1596
  describeElement,
1579
1597
  destroyHost,
1580
1598
  enhancePdfViewers,
@@ -1608,10 +1626,12 @@ export {
1608
1626
  sanitizeHtml,
1609
1627
  sanitizeToFragment,
1610
1628
  setSanitizedHtml,
1629
+ shadowHostChain,
1611
1630
  startAuthoring,
1612
1631
  textSnapshotOf,
1613
1632
  trackRect,
1614
1633
  urlMatches,
1634
+ visualRect,
1615
1635
  waitForTarget
1616
1636
  };
1617
1637
  //# sourceMappingURL=index.js.map