@flowsterix/react 0.1.0 → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Kevin Graf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useTanStackRouterTourAdapter
3
- } from "./chunk-RCASLQRS.mjs";
3
+ } from "./chunk-LQFOZS4Y.mjs";
4
4
 
5
5
  // src/router/tanstackRouterSync.tsx
6
6
  import * as TanStackRouter from "@tanstack/react-router";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "./chunk-RPA2S5UP.mjs";
4
+ } from "./chunk-WTGQUDPT.mjs";
5
5
 
6
6
  // src/router/tanstackRouterAdapter.tsx
7
7
  import { useRouterState } from "@tanstack/react-router";
@@ -37,15 +37,17 @@ var getViewportRect = () => {
37
37
  var expandRect = (rect, padding) => {
38
38
  if (!isBrowser) return rect;
39
39
  const viewport = getViewportRect();
40
- const top = Math.max(0, rect.top - padding);
41
- const left = Math.max(0, rect.left - padding);
42
- const width = Math.min(viewport.width - left, rect.width + padding * 2);
43
- const height = Math.min(viewport.height - top, rect.height + padding * 2);
40
+ const spaceTop = rect.top;
41
+ const spaceBottom = viewport.height - rect.bottom;
42
+ const spaceLeft = rect.left;
43
+ const spaceRight = viewport.width - rect.right;
44
+ const verticalPadding = Math.min(padding, spaceTop, spaceBottom);
45
+ const horizontalPadding = Math.min(padding, spaceLeft, spaceRight);
44
46
  return createRect({
45
- top,
46
- left,
47
- width: Math.max(0, width),
48
- height: Math.max(0, height)
47
+ top: rect.top - verticalPadding,
48
+ left: rect.left - horizontalPadding,
49
+ width: rect.width + horizontalPadding * 2,
50
+ height: rect.height + verticalPadding * 2
49
51
  });
50
52
  };
51
53
  var getClientRect = (element) => toClientRect(element.getBoundingClientRect());
@@ -5,7 +5,9 @@ export interface TourFocusManagerProps {
5
5
  target: TourTargetInfo;
6
6
  popoverNode: HTMLElement | null;
7
7
  highlightRect?: TourOverlayRect | null;
8
- targetRingOffset?: number;
8
+ guardElementFocusRing?: {
9
+ boxShadow: string;
10
+ };
9
11
  }
10
- export declare const TourFocusManager: ({ active, target, popoverNode, highlightRect, targetRingOffset, }: TourFocusManagerProps) => import("react").ReactPortal | null;
12
+ export declare const TourFocusManager: ({ active, target, popoverNode, highlightRect, guardElementFocusRing, }: TourFocusManagerProps) => import("react").ReactPortal | null;
11
13
  //# sourceMappingURL=TourFocusManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TourFocusManager.d.ts","sourceRoot":"","sources":["../../src/components/TourFocusManager.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAgB5D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,aAAa,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,eAAO,MAAM,gBAAgB,GAAI,mEAM9B,qBAAqB,uCAkVvB,CAAA"}
1
+ {"version":3,"file":"TourFocusManager.d.ts","sourceRoot":"","sources":["../../src/components/TourFocusManager.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAgB5D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,aAAa,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACtC,qBAAqB,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAKD,eAAO,MAAM,gBAAgB,GAAI,wEAM9B,qBAAqB,uCA0VvB,CAAA"}
@@ -45,6 +45,9 @@ export interface TourHudFocusManagerState {
45
45
  target: TourTargetInfo;
46
46
  popoverNode: HTMLElement | null;
47
47
  setPopoverNode: (node: HTMLElement | null) => void;
48
+ guardElementFocusRing?: {
49
+ boxShadow: string;
50
+ };
48
51
  }
49
52
  export interface UseTourHudResult {
50
53
  hudState: UseHudStateResult;
@@ -1 +1 @@
1
- {"version":3,"file":"useTourHud.d.ts","sourceRoot":"","sources":["../../src/hooks/useTourHud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAA;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,uBAAuB,CAAA;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IACjE;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,YAAY,EAAE,wBAAwB,CAAA;IACtC,WAAW,EAAE,uBAAuB,CAAA;IACpC,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAKD,eAAO,MAAM,UAAU,GACrB,UAAS,iBAAsB,KAC9B,gBAwFF,CAAA"}
1
+ {"version":3,"file":"useTourHud.d.ts","sourceRoot":"","sources":["../../src/hooks/useTourHud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAA;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,uBAAuB,CAAA;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IACjE;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAClD,qBAAqB,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,YAAY,EAAE,wBAAwB,CAAA;IACtC,WAAW,EAAE,uBAAuB,CAAA;IACpC,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAKD,eAAO,MAAM,UAAU,GACrB,UAAS,iBAAsB,KAC9B,gBA+FF,CAAA"}
package/dist/index.cjs CHANGED
@@ -250,15 +250,17 @@ var getViewportRect = () => {
250
250
  var expandRect = (rect, padding) => {
251
251
  if (!isBrowser) return rect;
252
252
  const viewport = getViewportRect();
253
- const top = Math.max(0, rect.top - padding);
254
- const left = Math.max(0, rect.left - padding);
255
- const width = Math.min(viewport.width - left, rect.width + padding * 2);
256
- const height = Math.min(viewport.height - top, rect.height + padding * 2);
253
+ const spaceTop = rect.top;
254
+ const spaceBottom = viewport.height - rect.bottom;
255
+ const spaceLeft = rect.left;
256
+ const spaceRight = viewport.width - rect.right;
257
+ const verticalPadding = Math.min(padding, spaceTop, spaceBottom);
258
+ const horizontalPadding = Math.min(padding, spaceLeft, spaceRight);
257
259
  return createRect({
258
- top,
259
- left,
260
- width: Math.max(0, width),
261
- height: Math.max(0, height)
260
+ top: rect.top - verticalPadding,
261
+ left: rect.left - horizontalPadding,
262
+ width: rect.width + horizontalPadding * 2,
263
+ height: rect.height + verticalPadding * 2
262
264
  });
263
265
  };
264
266
  var getClientRect = (element) => toClientRect(element.getBoundingClientRect());
@@ -2403,9 +2405,16 @@ var useTourHud = (options = {}) => {
2403
2405
  active: hudState.focusTrapActive,
2404
2406
  target: hudState.hudTarget,
2405
2407
  popoverNode,
2406
- setPopoverNode
2408
+ setPopoverNode,
2409
+ guardElementFocusRing: hudState.flowHudOptions?.guardElementFocusRing
2407
2410
  }),
2408
- [hudState.focusTrapActive, hudState.hudTarget, popoverNode, setPopoverNode]
2411
+ [
2412
+ hudState.focusTrapActive,
2413
+ hudState.hudTarget,
2414
+ popoverNode,
2415
+ setPopoverNode,
2416
+ hudState.flowHudOptions?.guardElementFocusRing
2417
+ ]
2409
2418
  );
2410
2419
  return {
2411
2420
  hudState,
@@ -3736,12 +3745,13 @@ var runMicrotask = (callback) => {
3736
3745
  setTimeout(callback, 0);
3737
3746
  }
3738
3747
  };
3748
+ var DEFAULT_BOX_SHADOW = "0 0 0 2px var(--primary), 0 0 8px 2px color-mix(in srgb, var(--primary) 40%, transparent)";
3739
3749
  var TourFocusManager = ({
3740
3750
  active,
3741
3751
  target,
3742
3752
  popoverNode,
3743
3753
  highlightRect,
3744
- targetRingOffset = -2
3754
+ guardElementFocusRing
3745
3755
  }) => {
3746
3756
  const previousFocusRef = (0, import_react21.useRef)(null);
3747
3757
  const guardNodesRef = (0, import_react21.useRef)({
@@ -3752,10 +3762,9 @@ var TourFocusManager = ({
3752
3762
  });
3753
3763
  const lastTabDirectionRef = (0, import_react21.useRef)("forward");
3754
3764
  const suppressGuardHopRef = (0, import_react21.useRef)(null);
3755
- const ringStylesRef = (0, import_react21.useRef)(
3756
- /* @__PURE__ */ new WeakMap()
3757
- );
3758
3765
  const [targetRingActive, setTargetRingActive] = (0, import_react21.useState)(false);
3766
+ const [popoverRingActive, setPopoverRingActive] = (0, import_react21.useState)(false);
3767
+ const [popoverRect, setPopoverRect] = (0, import_react21.useState)(null);
3759
3768
  const restoreFocus = () => {
3760
3769
  const previous = previousFocusRef.current;
3761
3770
  previousFocusRef.current = null;
@@ -3807,33 +3816,9 @@ var TourFocusManager = ({
3807
3816
  });
3808
3817
  return node;
3809
3818
  };
3810
- const applyRing = (element, activeRing) => {
3811
- if (!element) return;
3812
- const cache = ringStylesRef.current;
3813
- if (activeRing) {
3814
- if (!cache.has(element)) {
3815
- cache.set(element, {
3816
- outline: element.style.outline,
3817
- outlineOffset: element.style.outlineOffset
3818
- });
3819
- }
3820
- element.style.outline = "2px solid var(--tour-focus-ring-color, rgba(59, 130, 246, 0.8))";
3821
- element.style.outlineOffset = "3px";
3822
- return;
3823
- }
3824
- const previous = cache.get(element);
3825
- if (previous) {
3826
- element.style.outline = previous.outline;
3827
- element.style.outlineOffset = previous.outlineOffset;
3828
- cache.delete(element);
3829
- } else {
3830
- element.style.outline = "";
3831
- element.style.outlineOffset = "";
3832
- }
3833
- };
3834
3819
  const clearRings = () => {
3835
3820
  setTargetRingActive(false);
3836
- applyRing(popoverNode, false);
3821
+ setPopoverRingActive(false);
3837
3822
  };
3838
3823
  const removeGuards = () => {
3839
3824
  for (const key of Object.keys(guardNodesRef.current)) {
@@ -3970,10 +3955,10 @@ var TourFocusManager = ({
3970
3955
  const key = targetNode.getAttribute("data-tour-focus-guard");
3971
3956
  if (key?.startsWith("target")) {
3972
3957
  setTargetRingActive(true);
3973
- applyRing(popoverNode, false);
3958
+ setPopoverRingActive(false);
3974
3959
  } else if (key?.startsWith("popover")) {
3975
3960
  setTargetRingActive(false);
3976
- applyRing(popoverNode, true);
3961
+ setPopoverRingActive(true);
3977
3962
  }
3978
3963
  return;
3979
3964
  }
@@ -3999,25 +3984,59 @@ var TourFocusManager = ({
3999
3984
  target.stepId,
4000
3985
  target.visibility
4001
3986
  ]);
3987
+ (0, import_react21.useLayoutEffect)(() => {
3988
+ if (popoverRingActive && popoverNode) {
3989
+ setPopoverRect(popoverNode.getBoundingClientRect());
3990
+ } else {
3991
+ setPopoverRect(null);
3992
+ }
3993
+ }, [popoverRingActive, popoverNode]);
4002
3994
  if (!isBrowser) return null;
4003
3995
  const host = portalHost();
4004
- if (!host || !highlightRect || !targetRingActive) return null;
4005
- const offset = Math.max(0, targetRingOffset);
4006
- const ringStyle = {
4007
- position: "fixed",
4008
- top: highlightRect.top - offset,
4009
- left: highlightRect.left - offset,
4010
- width: highlightRect.width + offset * 2,
4011
- height: highlightRect.height + offset * 2,
4012
- borderRadius: highlightRect.radius + offset,
4013
- boxShadow: [
4014
- "0 0 0 2px var(--tour-focus-ring-offset-color, transparent)",
4015
- "0 0 0 2px var(--tour-focus-ring-color, rgba(59, 130, 246, 0.8))"
4016
- ].join(", "),
4017
- pointerEvents: "none",
4018
- zIndex: 2001
4019
- };
4020
- return (0, import_react_dom3.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: ringStyle, "aria-hidden": true }), host);
3996
+ if (!host) return null;
3997
+ const boxShadow = guardElementFocusRing?.boxShadow ?? DEFAULT_BOX_SHADOW;
3998
+ const showTargetRing = targetRingActive && highlightRect;
3999
+ const showPopoverRing = popoverRingActive && popoverRect;
4000
+ if (!showTargetRing && !showPopoverRing) return null;
4001
+ return (0, import_react_dom3.createPortal)(
4002
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
4003
+ showTargetRing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4004
+ "div",
4005
+ {
4006
+ style: {
4007
+ position: "fixed",
4008
+ top: highlightRect.top,
4009
+ left: highlightRect.left,
4010
+ width: highlightRect.width,
4011
+ height: highlightRect.height,
4012
+ borderRadius: highlightRect.radius,
4013
+ boxShadow,
4014
+ pointerEvents: "none",
4015
+ zIndex: 2001
4016
+ },
4017
+ "aria-hidden": true
4018
+ }
4019
+ ),
4020
+ showPopoverRing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4021
+ "div",
4022
+ {
4023
+ style: {
4024
+ position: "fixed",
4025
+ top: popoverRect.top,
4026
+ left: popoverRect.left,
4027
+ width: popoverRect.width,
4028
+ height: popoverRect.height,
4029
+ borderRadius: 12,
4030
+ boxShadow,
4031
+ pointerEvents: "none",
4032
+ zIndex: 2001
4033
+ },
4034
+ "aria-hidden": true
4035
+ }
4036
+ )
4037
+ ] }),
4038
+ host
4039
+ );
4021
4040
  };
4022
4041
 
4023
4042
  // src/motion/useHudMotion.ts
package/dist/index.mjs CHANGED
@@ -4,10 +4,10 @@ import {
4
4
  getTourRouter,
5
5
  setTanStackRouter,
6
6
  setTourRouter
7
- } from "./chunk-U757YVZP.mjs";
7
+ } from "./chunk-B6OJ26VH.mjs";
8
8
  import {
9
9
  useTanStackRouterTourAdapter
10
- } from "./chunk-RCASLQRS.mjs";
10
+ } from "./chunk-LQFOZS4Y.mjs";
11
11
  import {
12
12
  createPathString,
13
13
  expandRect,
@@ -20,7 +20,7 @@ import {
20
20
  portalHost,
21
21
  subscribeToRouteChanges,
22
22
  supportsMasking
23
- } from "./chunk-RPA2S5UP.mjs";
23
+ } from "./chunk-WTGQUDPT.mjs";
24
24
 
25
25
  // src/context.tsx
26
26
  import {
@@ -2140,9 +2140,16 @@ var useTourHud = (options = {}) => {
2140
2140
  active: hudState.focusTrapActive,
2141
2141
  target: hudState.hudTarget,
2142
2142
  popoverNode,
2143
- setPopoverNode
2143
+ setPopoverNode,
2144
+ guardElementFocusRing: hudState.flowHudOptions?.guardElementFocusRing
2144
2145
  }),
2145
- [hudState.focusTrapActive, hudState.hudTarget, popoverNode, setPopoverNode]
2146
+ [
2147
+ hudState.focusTrapActive,
2148
+ hudState.hudTarget,
2149
+ popoverNode,
2150
+ setPopoverNode,
2151
+ hudState.flowHudOptions?.guardElementFocusRing
2152
+ ]
2146
2153
  );
2147
2154
  return {
2148
2155
  hudState,
@@ -3471,7 +3478,7 @@ var focusElement = (element, options) => {
3471
3478
  };
3472
3479
 
3473
3480
  // src/components/TourFocusManager.tsx
3474
- import { jsx as jsx4 } from "react/jsx-runtime";
3481
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
3475
3482
  var runMicrotask = (callback) => {
3476
3483
  if (typeof queueMicrotask === "function") {
3477
3484
  queueMicrotask(callback);
@@ -3479,12 +3486,13 @@ var runMicrotask = (callback) => {
3479
3486
  setTimeout(callback, 0);
3480
3487
  }
3481
3488
  };
3489
+ var DEFAULT_BOX_SHADOW = "0 0 0 2px var(--primary), 0 0 8px 2px color-mix(in srgb, var(--primary) 40%, transparent)";
3482
3490
  var TourFocusManager = ({
3483
3491
  active,
3484
3492
  target,
3485
3493
  popoverNode,
3486
3494
  highlightRect,
3487
- targetRingOffset = -2
3495
+ guardElementFocusRing
3488
3496
  }) => {
3489
3497
  const previousFocusRef = useRef8(null);
3490
3498
  const guardNodesRef = useRef8({
@@ -3495,10 +3503,9 @@ var TourFocusManager = ({
3495
3503
  });
3496
3504
  const lastTabDirectionRef = useRef8("forward");
3497
3505
  const suppressGuardHopRef = useRef8(null);
3498
- const ringStylesRef = useRef8(
3499
- /* @__PURE__ */ new WeakMap()
3500
- );
3501
3506
  const [targetRingActive, setTargetRingActive] = useState11(false);
3507
+ const [popoverRingActive, setPopoverRingActive] = useState11(false);
3508
+ const [popoverRect, setPopoverRect] = useState11(null);
3502
3509
  const restoreFocus = () => {
3503
3510
  const previous = previousFocusRef.current;
3504
3511
  previousFocusRef.current = null;
@@ -3550,33 +3557,9 @@ var TourFocusManager = ({
3550
3557
  });
3551
3558
  return node;
3552
3559
  };
3553
- const applyRing = (element, activeRing) => {
3554
- if (!element) return;
3555
- const cache = ringStylesRef.current;
3556
- if (activeRing) {
3557
- if (!cache.has(element)) {
3558
- cache.set(element, {
3559
- outline: element.style.outline,
3560
- outlineOffset: element.style.outlineOffset
3561
- });
3562
- }
3563
- element.style.outline = "2px solid var(--tour-focus-ring-color, rgba(59, 130, 246, 0.8))";
3564
- element.style.outlineOffset = "3px";
3565
- return;
3566
- }
3567
- const previous = cache.get(element);
3568
- if (previous) {
3569
- element.style.outline = previous.outline;
3570
- element.style.outlineOffset = previous.outlineOffset;
3571
- cache.delete(element);
3572
- } else {
3573
- element.style.outline = "";
3574
- element.style.outlineOffset = "";
3575
- }
3576
- };
3577
3560
  const clearRings = () => {
3578
3561
  setTargetRingActive(false);
3579
- applyRing(popoverNode, false);
3562
+ setPopoverRingActive(false);
3580
3563
  };
3581
3564
  const removeGuards = () => {
3582
3565
  for (const key of Object.keys(guardNodesRef.current)) {
@@ -3713,10 +3696,10 @@ var TourFocusManager = ({
3713
3696
  const key = targetNode.getAttribute("data-tour-focus-guard");
3714
3697
  if (key?.startsWith("target")) {
3715
3698
  setTargetRingActive(true);
3716
- applyRing(popoverNode, false);
3699
+ setPopoverRingActive(false);
3717
3700
  } else if (key?.startsWith("popover")) {
3718
3701
  setTargetRingActive(false);
3719
- applyRing(popoverNode, true);
3702
+ setPopoverRingActive(true);
3720
3703
  }
3721
3704
  return;
3722
3705
  }
@@ -3742,25 +3725,59 @@ var TourFocusManager = ({
3742
3725
  target.stepId,
3743
3726
  target.visibility
3744
3727
  ]);
3728
+ useLayoutEffect3(() => {
3729
+ if (popoverRingActive && popoverNode) {
3730
+ setPopoverRect(popoverNode.getBoundingClientRect());
3731
+ } else {
3732
+ setPopoverRect(null);
3733
+ }
3734
+ }, [popoverRingActive, popoverNode]);
3745
3735
  if (!isBrowser) return null;
3746
3736
  const host = portalHost();
3747
- if (!host || !highlightRect || !targetRingActive) return null;
3748
- const offset = Math.max(0, targetRingOffset);
3749
- const ringStyle = {
3750
- position: "fixed",
3751
- top: highlightRect.top - offset,
3752
- left: highlightRect.left - offset,
3753
- width: highlightRect.width + offset * 2,
3754
- height: highlightRect.height + offset * 2,
3755
- borderRadius: highlightRect.radius + offset,
3756
- boxShadow: [
3757
- "0 0 0 2px var(--tour-focus-ring-offset-color, transparent)",
3758
- "0 0 0 2px var(--tour-focus-ring-color, rgba(59, 130, 246, 0.8))"
3759
- ].join(", "),
3760
- pointerEvents: "none",
3761
- zIndex: 2001
3762
- };
3763
- return createPortal3(/* @__PURE__ */ jsx4("div", { style: ringStyle, "aria-hidden": true }), host);
3737
+ if (!host) return null;
3738
+ const boxShadow = guardElementFocusRing?.boxShadow ?? DEFAULT_BOX_SHADOW;
3739
+ const showTargetRing = targetRingActive && highlightRect;
3740
+ const showPopoverRing = popoverRingActive && popoverRect;
3741
+ if (!showTargetRing && !showPopoverRing) return null;
3742
+ return createPortal3(
3743
+ /* @__PURE__ */ jsxs2(Fragment, { children: [
3744
+ showTargetRing && /* @__PURE__ */ jsx4(
3745
+ "div",
3746
+ {
3747
+ style: {
3748
+ position: "fixed",
3749
+ top: highlightRect.top,
3750
+ left: highlightRect.left,
3751
+ width: highlightRect.width,
3752
+ height: highlightRect.height,
3753
+ borderRadius: highlightRect.radius,
3754
+ boxShadow,
3755
+ pointerEvents: "none",
3756
+ zIndex: 2001
3757
+ },
3758
+ "aria-hidden": true
3759
+ }
3760
+ ),
3761
+ showPopoverRing && /* @__PURE__ */ jsx4(
3762
+ "div",
3763
+ {
3764
+ style: {
3765
+ position: "fixed",
3766
+ top: popoverRect.top,
3767
+ left: popoverRect.left,
3768
+ width: popoverRect.width,
3769
+ height: popoverRect.height,
3770
+ borderRadius: 12,
3771
+ boxShadow,
3772
+ pointerEvents: "none",
3773
+ zIndex: 2001
3774
+ },
3775
+ "aria-hidden": true
3776
+ }
3777
+ )
3778
+ ] }),
3779
+ host
3780
+ );
3764
3781
  };
3765
3782
 
3766
3783
  // src/motion/useHudMotion.ts
@@ -4,17 +4,17 @@ import {
4
4
  getTourRouter,
5
5
  setTanStackRouter,
6
6
  setTourRouter
7
- } from "../chunk-U757YVZP.mjs";
7
+ } from "../chunk-B6OJ26VH.mjs";
8
8
  import {
9
9
  useTanStackRouterTourAdapter
10
- } from "../chunk-RCASLQRS.mjs";
10
+ } from "../chunk-LQFOZS4Y.mjs";
11
11
  import {
12
12
  createPathString,
13
13
  getCurrentRoutePath,
14
14
  notifyRouteChange,
15
15
  routeGatingChannel,
16
16
  subscribeToRouteChanges
17
- } from "../chunk-RPA2S5UP.mjs";
17
+ } from "../chunk-WTGQUDPT.mjs";
18
18
  export {
19
19
  TanStackRouterSync,
20
20
  createPathString,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-RPA2S5UP.mjs";
4
+ } from "../chunk-WTGQUDPT.mjs";
5
5
 
6
6
  // src/router/nextAppRouterAdapter.tsx
7
7
  import * as NextNavigation from "next/navigation";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-RPA2S5UP.mjs";
4
+ } from "../chunk-WTGQUDPT.mjs";
5
5
 
6
6
  // src/router/nextPagesRouterAdapter.tsx
7
7
  import * as NextRouter from "next/router";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-RPA2S5UP.mjs";
4
+ } from "../chunk-WTGQUDPT.mjs";
5
5
 
6
6
  // src/router/reactRouterAdapter.tsx
7
7
  import { useEffect } from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  useTanStackRouterTourAdapter
3
- } from "../chunk-RCASLQRS.mjs";
4
- import "../chunk-RPA2S5UP.mjs";
3
+ } from "../chunk-LQFOZS4Y.mjs";
4
+ import "../chunk-WTGQUDPT.mjs";
5
5
  export {
6
6
  useTanStackRouterTourAdapter
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,SAC4C,CAAA;AAElE,KAAK,QAAQ,GAAG;IACd,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,+BAKxB,QAAQ,KAAG,cAOZ,CAAA;AAEF,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,GAAG,eAAe,KAAG,cAM3D,CAAA;AAEJ,eAAO,MAAM,eAAe,QAAO,cAgBlC,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,MAAM,cAAc,EACpB,SAAS,MAAM,KACd,cAeF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,cAAc,EAAE,eAAU,YAUhE,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,KAAG,cACF,CAAA;AAe/C,eAAO,MAAM,gBAAgB,GAAI,SAAS,OAAO,KAAG,KAAK,CAAC,OAAO,CA4BhE,CAAA;AAED,eAAO,MAAM,UAAU,0BAA2C,CAAA;AA4BlE,eAAO,MAAM,eAAe,eAM3B,CAAA"}
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,SAC4C,CAAA;AAElE,KAAK,QAAQ,GAAG;IACd,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,+BAKxB,QAAQ,KAAG,cAOZ,CAAA;AAEF,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,GAAG,eAAe,KAAG,cAM3D,CAAA;AAEJ,eAAO,MAAM,eAAe,QAAO,cAgBlC,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,MAAM,cAAc,EACpB,SAAS,MAAM,KACd,cAqBF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,cAAc,EAAE,eAAU,YAUhE,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,KAAG,cACF,CAAA;AAe/C,eAAO,MAAM,gBAAgB,GAAI,SAAS,OAAO,KAAG,KAAK,CAAC,OAAO,CA4BhE,CAAA;AAED,eAAO,MAAM,UAAU,0BAA2C,CAAA;AA4BlE,eAAO,MAAM,eAAe,eAM3B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowsterix/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "React bindings for Flowsterix - guided tours and onboarding flows",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -64,7 +64,7 @@
64
64
  ],
65
65
  "dependencies": {
66
66
  "@floating-ui/dom": "^1.7.4",
67
- "@flowsterix/core": "0.1.0"
67
+ "@flowsterix/core": "0.2.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "react": ">=18",