@kubit-ui-web/react-charts 1.5.1 → 1.6.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.
Files changed (156) hide show
  1. package/dist/cjs/components/focusRing/components/FocusRingInline.d.ts +25 -0
  2. package/dist/cjs/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  3. package/dist/cjs/components/focusRing/components/FocusRingInline.js +37 -0
  4. package/dist/cjs/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  5. package/dist/cjs/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  6. package/dist/cjs/components/focusRing/components/FocusRingRenderer.js +25 -0
  7. package/dist/cjs/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  8. package/dist/cjs/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  9. package/dist/cjs/components/focusRing/components/FocusRingSeparate.js +45 -0
  10. package/dist/cjs/components/focusRing/focusRing.css +14 -0
  11. package/dist/cjs/components/focusRing/focusRing.d.ts +35 -0
  12. package/dist/cjs/components/focusRing/focusRing.d.ts.map +1 -0
  13. package/dist/cjs/components/focusRing/focusRing.js +44 -0
  14. package/dist/cjs/components/focusRing/focusRing.types.d.ts +40 -0
  15. package/dist/cjs/components/focusRing/focusRing.types.d.ts.map +1 -0
  16. package/dist/cjs/components/focusRing/focusRing.types.js +1 -0
  17. package/dist/cjs/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  18. package/dist/cjs/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  19. package/dist/cjs/components/focusRing/hooks/useFocusRingData.js +67 -0
  20. package/dist/cjs/components/focusRing/index.d.ts +3 -0
  21. package/dist/cjs/components/focusRing/index.d.ts.map +1 -0
  22. package/dist/cjs/components/focusRing/index.js +1 -0
  23. package/dist/cjs/components/focusRing/utils/composeRefs.d.ts +7 -0
  24. package/dist/cjs/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  25. package/dist/cjs/components/focusRing/utils/composeRefs.js +16 -0
  26. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  27. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  28. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.js +141 -0
  29. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  30. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  31. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.js +126 -0
  32. package/dist/cjs/components/focusRing/utils/utils.types.d.ts +52 -0
  33. package/dist/cjs/components/focusRing/utils/utils.types.d.ts.map +1 -0
  34. package/dist/cjs/components/focusRing/utils/utils.types.js +1 -0
  35. package/dist/cjs/components/index.d.ts +1 -0
  36. package/dist/cjs/components/index.d.ts.map +1 -1
  37. package/dist/cjs/components/index.js +1 -0
  38. package/dist/cjs/components/plot/plot.d.ts.map +1 -1
  39. package/dist/cjs/components/plot/plot.js +7 -19
  40. package/dist/cjs/components/zoomArea/components/SelectionArea.d.ts +3 -23
  41. package/dist/cjs/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  42. package/dist/cjs/components/zoomArea/components/SelectionArea.js +7 -39
  43. package/dist/cjs/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  44. package/dist/cjs/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  45. package/dist/cjs/components/zoomArea/components/ZoomHandler.js +2 -15
  46. package/dist/cjs/components/zoomArea/components/index.d.ts +1 -1
  47. package/dist/cjs/components/zoomArea/components/index.d.ts.map +1 -1
  48. package/dist/cjs/components/zoomArea/components/index.js +1 -1
  49. package/dist/cjs/components/zoomArea/zoomArea.js +6 -6
  50. package/dist/cjs/components/zoomArea/zoomArea.type.d.ts +1 -1
  51. package/dist/cjs/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  52. package/dist/cjs/types/focusConfig.type.d.ts +15 -3
  53. package/dist/cjs/types/focusConfig.type.d.ts.map +1 -1
  54. package/dist/cjs/types/focusConfig.type.js +14 -1
  55. package/dist/esm/components/focusRing/components/FocusRingInline.d.ts +25 -0
  56. package/dist/esm/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  57. package/dist/esm/components/focusRing/components/FocusRingInline.js +37 -0
  58. package/dist/esm/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  59. package/dist/esm/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  60. package/dist/esm/components/focusRing/components/FocusRingRenderer.js +25 -0
  61. package/dist/esm/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  62. package/dist/esm/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  63. package/dist/esm/components/focusRing/components/FocusRingSeparate.js +45 -0
  64. package/dist/esm/components/focusRing/focusRing.css +14 -0
  65. package/dist/esm/components/focusRing/focusRing.d.ts +35 -0
  66. package/dist/esm/components/focusRing/focusRing.d.ts.map +1 -0
  67. package/dist/esm/components/focusRing/focusRing.js +44 -0
  68. package/dist/esm/components/focusRing/focusRing.types.d.ts +40 -0
  69. package/dist/esm/components/focusRing/focusRing.types.d.ts.map +1 -0
  70. package/dist/esm/components/focusRing/focusRing.types.js +1 -0
  71. package/dist/esm/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  72. package/dist/esm/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  73. package/dist/esm/components/focusRing/hooks/useFocusRingData.js +67 -0
  74. package/dist/esm/components/focusRing/index.d.ts +3 -0
  75. package/dist/esm/components/focusRing/index.d.ts.map +1 -0
  76. package/dist/esm/components/focusRing/index.js +1 -0
  77. package/dist/esm/components/focusRing/utils/composeRefs.d.ts +7 -0
  78. package/dist/esm/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  79. package/dist/esm/components/focusRing/utils/composeRefs.js +16 -0
  80. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  81. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  82. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.js +141 -0
  83. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  84. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  85. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.js +126 -0
  86. package/dist/esm/components/focusRing/utils/utils.types.d.ts +52 -0
  87. package/dist/esm/components/focusRing/utils/utils.types.d.ts.map +1 -0
  88. package/dist/esm/components/focusRing/utils/utils.types.js +1 -0
  89. package/dist/esm/components/index.d.ts +1 -0
  90. package/dist/esm/components/index.d.ts.map +1 -1
  91. package/dist/esm/components/index.js +1 -0
  92. package/dist/esm/components/plot/plot.d.ts.map +1 -1
  93. package/dist/esm/components/plot/plot.js +7 -19
  94. package/dist/esm/components/zoomArea/components/SelectionArea.d.ts +3 -23
  95. package/dist/esm/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  96. package/dist/esm/components/zoomArea/components/SelectionArea.js +7 -39
  97. package/dist/esm/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  98. package/dist/esm/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  99. package/dist/esm/components/zoomArea/components/ZoomHandler.js +2 -15
  100. package/dist/esm/components/zoomArea/components/index.d.ts +1 -1
  101. package/dist/esm/components/zoomArea/components/index.d.ts.map +1 -1
  102. package/dist/esm/components/zoomArea/components/index.js +1 -1
  103. package/dist/esm/components/zoomArea/zoomArea.js +6 -6
  104. package/dist/esm/components/zoomArea/zoomArea.type.d.ts +1 -1
  105. package/dist/esm/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  106. package/dist/esm/types/focusConfig.type.d.ts +15 -3
  107. package/dist/esm/types/focusConfig.type.d.ts.map +1 -1
  108. package/dist/esm/types/focusConfig.type.js +14 -1
  109. package/dist/kubit-ui-web-react-charts.cjs.js +1 -1
  110. package/dist/kubit-ui-web-react-charts.es.js +1 -1
  111. package/dist/kubit-ui-web-react-charts.umd.js +1 -1
  112. package/dist/react-charts.css +1 -1
  113. package/dist/types/components/focusRing/components/FocusRingInline.d.ts +25 -0
  114. package/dist/types/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  115. package/dist/types/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  116. package/dist/types/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  117. package/dist/types/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  118. package/dist/types/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  119. package/dist/types/components/focusRing/focusRing.d.ts +34 -0
  120. package/dist/types/components/focusRing/focusRing.d.ts.map +1 -0
  121. package/dist/types/components/focusRing/focusRing.types.d.ts +40 -0
  122. package/dist/types/components/focusRing/focusRing.types.d.ts.map +1 -0
  123. package/dist/types/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  124. package/dist/types/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  125. package/dist/types/components/focusRing/index.d.ts +3 -0
  126. package/dist/types/components/focusRing/index.d.ts.map +1 -0
  127. package/dist/types/components/focusRing/utils/composeRefs.d.ts +7 -0
  128. package/dist/types/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  129. package/dist/types/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  130. package/dist/types/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  131. package/dist/types/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  132. package/dist/types/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  133. package/dist/types/components/focusRing/utils/utils.types.d.ts +52 -0
  134. package/dist/types/components/focusRing/utils/utils.types.d.ts.map +1 -0
  135. package/dist/types/components/index.d.ts +1 -0
  136. package/dist/types/components/index.d.ts.map +1 -1
  137. package/dist/types/components/plot/plot.d.ts.map +1 -1
  138. package/dist/types/components/zoomArea/components/SelectionArea.d.ts +3 -23
  139. package/dist/types/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  140. package/dist/types/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  141. package/dist/types/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  142. package/dist/types/components/zoomArea/components/index.d.ts +1 -1
  143. package/dist/types/components/zoomArea/components/index.d.ts.map +1 -1
  144. package/dist/types/components/zoomArea/zoomArea.type.d.ts +1 -1
  145. package/dist/types/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  146. package/dist/types/types/focusConfig.type.d.ts +15 -3
  147. package/dist/types/types/focusConfig.type.d.ts.map +1 -1
  148. package/package.json +1 -1
  149. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  150. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
  151. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.js +0 -80
  152. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  153. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
  154. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.js +0 -80
  155. package/dist/types/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  156. package/dist/types/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
@@ -0,0 +1,25 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { FocusConfig } from '../../../types/focusConfig.type';
3
+ export interface FocusRingInlineProps {
4
+ children: ReactElement;
5
+ isFocused: boolean;
6
+ disabled?: boolean;
7
+ dataTestId?: string;
8
+ focusConfig?: FocusConfig;
9
+ }
10
+ /**
11
+ * FocusRing component for inline mode (children).
12
+ * Wraps the element and renders focus ring inline with automatic z-order.
13
+ *
14
+ * This component:
15
+ * - Clones the children element and attaches a ref to it
16
+ * - Detects element bounds on mount and when focus state changes
17
+ * - Renders the focus ring BEFORE the element (proper z-order)
18
+ * - Handles both adaptive and bounding-box variants
19
+ * - Preserves any existing ref the children might have
20
+ *
21
+ * @param props - FocusRingInlineProps
22
+ * @returns JSX element with focus ring + wrapped children
23
+ */
24
+ export declare const FocusRingInline: React.FC<FocusRingInlineProps>;
25
+ //# sourceMappingURL=FocusRingInline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusRingInline.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/components/FocusRingInline.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAwB,MAAM,OAAO,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAM5D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoC1D,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cloneElement, useRef } from 'react';
3
+ import { useFocusRingData } from '../hooks/useFocusRingData';
4
+ import { composeRefs } from '../utils/composeRefs';
5
+ import { FocusRingRenderer } from './FocusRingRenderer';
6
+ /**
7
+ * FocusRing component for inline mode (children).
8
+ * Wraps the element and renders focus ring inline with automatic z-order.
9
+ *
10
+ * This component:
11
+ * - Clones the children element and attaches a ref to it
12
+ * - Detects element bounds on mount and when focus state changes
13
+ * - Renders the focus ring BEFORE the element (proper z-order)
14
+ * - Handles both adaptive and bounding-box variants
15
+ * - Preserves any existing ref the children might have
16
+ *
17
+ * @param props - FocusRingInlineProps
18
+ * @returns JSX element with focus ring + wrapped children
19
+ */
20
+ export const FocusRingInline = ({ children, dataTestId = 'focus-ring', disabled = false, focusConfig, isFocused, }) => {
21
+ // Create ref for the SVG graphics element
22
+ const childrenRef = useRef(null);
23
+ const { layers } = useFocusRingData({
24
+ elementRef: childrenRef,
25
+ focusConfig,
26
+ isFocused,
27
+ });
28
+ // Extract the ref from children safely
29
+ // Children might have a ref attached, we need to preserve it while adding our own
30
+ const childrenWithRef = children;
31
+ const combinedRef = composeRefs(childrenRef, childrenWithRef.ref);
32
+ // Clone children and add ref (but NOT event handlers - parent manages those)
33
+ const wrappedChildren = cloneElement(children, {
34
+ ref: combinedRef,
35
+ });
36
+ return (_jsxs(_Fragment, { children: [isFocused && !disabled && (_jsx(FocusRingRenderer, { dataTestId: dataTestId, layers: layers ?? undefined })), wrappedChildren] }));
37
+ };
@@ -0,0 +1,13 @@
1
+ import type { FocusRingRendererProps } from '../focusRing.types';
2
+ /**
3
+ * Internal component that renders the actual focus ring elements.
4
+ * Supports both adaptive and bounding-box strategies with a unified rendering approach.
5
+ *
6
+ * This is a pure presentational component that receives pre-calculated FocusRingLayers
7
+ * and renders the appropriate SVG elements using React.createElement.
8
+ *
9
+ * @param props - FocusRingRendererProps
10
+ * @returns JSX element with focus ring SVG elements, or null if no valid data
11
+ */
12
+ export declare const FocusRingRenderer: React.FC<FocusRingRendererProps>;
13
+ //# sourceMappingURL=FocusRingRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusRingRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/components/FocusRingRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAkB9D,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createElement } from 'react';
3
+ /**
4
+ * Internal component that renders the actual focus ring elements.
5
+ * Supports both adaptive and bounding-box strategies with a unified rendering approach.
6
+ *
7
+ * This is a pure presentational component that receives pre-calculated FocusRingLayers
8
+ * and renders the appropriate SVG elements using React.createElement.
9
+ *
10
+ * @param props - FocusRingRendererProps
11
+ * @returns JSX element with focus ring SVG elements, or null if no valid data
12
+ */
13
+ export const FocusRingRenderer = ({ dataTestId, layers }) => {
14
+ if (!layers) {
15
+ return null;
16
+ }
17
+ // Unified rendering: both adaptive and bounding-box use the same structure
18
+ return (_jsxs("g", { className: "focus-ring-container", pointerEvents: "none", children: [createElement(layers.outerRing.type, {
19
+ ...layers.outerRing.props,
20
+ 'data-testid': `${dataTestId}-focus-outer`,
21
+ }), createElement(layers.innerRing.type, {
22
+ ...layers.innerRing.props,
23
+ 'data-testid': `${dataTestId}-focus-inner`,
24
+ })] }));
25
+ };
@@ -0,0 +1,40 @@
1
+ import type { RefObject } from 'react';
2
+ import type { FocusConfig } from '../../../types/focusConfig.type';
3
+ export interface FocusRingSeparateProps {
4
+ targetRef: RefObject<SVGGraphicsElement>;
5
+ isFocused: boolean;
6
+ disabled?: boolean;
7
+ dataTestId?: string;
8
+ focusConfig?: FocusConfig;
9
+ }
10
+ /**
11
+ * FocusRing component for separate mode (targetRef).
12
+ * Renders only the focus ring, allowing precise z-order control.
13
+ *
14
+ * This component:
15
+ * - Uses a ref to the target element (does not wrap it)
16
+ * - Only renders the focus ring (no children cloning)
17
+ * - Allows precise z-order control by controlling where FocusRing is placed in JSX
18
+ * - Handles both adaptive and bounding-box variants
19
+ *
20
+ * **IMPORTANT NOTE: Z-Order with Adaptive Variant**
21
+ *
22
+ * When using `variant: 'adaptive'` (default), the FocusRing **MUST be rendered BEFORE**
23
+ * the target element in SVG document order. Otherwise, focus ring strokes will cover the element.
24
+ *
25
+ * @param props - FocusRingSeparateProps
26
+ * @returns JSX element with only focus ring, or null if not focused/disabled
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * const ref = useRef<SVGCircleElement>(null);
31
+ *
32
+ * // CORRECT: FocusRing before element
33
+ * <>
34
+ * <FocusRingSeparate targetRef={ref} isFocused={true} />
35
+ * <circle ref={ref} cx={50} cy={50} r={30} />
36
+ * </>
37
+ * ```
38
+ */
39
+ export declare const FocusRingSeparate: React.FC<FocusRingSeparateProps>;
40
+ //# sourceMappingURL=FocusRingSeparate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FocusRingSeparate.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/components/FocusRingSeparate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAK5D,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAoB9D,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useFocusRingData } from '../hooks/useFocusRingData';
3
+ import { FocusRingRenderer } from './FocusRingRenderer';
4
+ /**
5
+ * FocusRing component for separate mode (targetRef).
6
+ * Renders only the focus ring, allowing precise z-order control.
7
+ *
8
+ * This component:
9
+ * - Uses a ref to the target element (does not wrap it)
10
+ * - Only renders the focus ring (no children cloning)
11
+ * - Allows precise z-order control by controlling where FocusRing is placed in JSX
12
+ * - Handles both adaptive and bounding-box variants
13
+ *
14
+ * **IMPORTANT NOTE: Z-Order with Adaptive Variant**
15
+ *
16
+ * When using `variant: 'adaptive'` (default), the FocusRing **MUST be rendered BEFORE**
17
+ * the target element in SVG document order. Otherwise, focus ring strokes will cover the element.
18
+ *
19
+ * @param props - FocusRingSeparateProps
20
+ * @returns JSX element with only focus ring, or null if not focused/disabled
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const ref = useRef<SVGCircleElement>(null);
25
+ *
26
+ * // CORRECT: FocusRing before element
27
+ * <>
28
+ * <FocusRingSeparate targetRef={ref} isFocused={true} />
29
+ * <circle ref={ref} cx={50} cy={50} r={30} />
30
+ * </>
31
+ * ```
32
+ */
33
+ export const FocusRingSeparate = ({ dataTestId = 'focus-ring', disabled = false, focusConfig, isFocused, targetRef, }) => {
34
+ const { layers } = useFocusRingData({
35
+ elementRef: targetRef,
36
+ focusConfig,
37
+ isFocused,
38
+ });
39
+ // Early return if not focused or disabled
40
+ if (!isFocused || disabled) {
41
+ return null;
42
+ }
43
+ // Render focus ring with unified structure
44
+ return _jsx(FocusRingRenderer, { dataTestId: dataTestId, layers: layers });
45
+ };
@@ -0,0 +1,14 @@
1
+ .focus-ring-outer {
2
+ /* Ensure focus rings don't interfere with pointer events */
3
+ pointer-events: none;
4
+ }
5
+
6
+ .focus-ring-inner {
7
+ /* Ensure focus rings don't interfere with pointer events */
8
+ pointer-events: none;
9
+ }
10
+
11
+ .focus-ring-container {
12
+ /* Ensure focus ring group doesn't interfere with interactions */
13
+ pointer-events: none;
14
+ }
@@ -0,0 +1,35 @@
1
+ import type { FC } from 'react';
2
+ import './focusRing.css';
3
+ import type { FocusRingProps } from './focusRing.types';
4
+ /**
5
+ * FocusRing - Controlled, purely decorative component for rendering focus rings around SVG elements.
6
+ *
7
+ * **Key Characteristics:**
8
+ * - **Controlled Component**: Parent manages `isFocused` state
9
+ * - **Purely Decorative**: Does not intercept or manage events
10
+ * - **Two Modes**: Inline (children) or Separate (targetRef) rendering
11
+ * - **Zero Configuration**: Automatic element detection
12
+ *
13
+ * **Two Modes:**
14
+ *
15
+ * 1. **Inline (children)** - Wraps element, focus ring rendered inline, z-order handled automatically
16
+ * 2. **Separate (targetRef)** - Only renders focus ring, allows precise z-order control
17
+ *
18
+ * **IMPORTANT NOTE: Z-Order with Adaptive Variant**
19
+ *
20
+ * When using `variant: 'adaptive'` (default) with `targetRef` mode, the FocusRing **MUST be rendered BEFORE**
21
+ * the target element in SVG document order. Otherwise, focus ring strokes will cover the element.
22
+ *
23
+ * ```tsx
24
+ * // CORRECT: FocusRing before element
25
+ * <>
26
+ * <FocusRing targetRef={ref} isFocused={focused} />
27
+ * <circle ref={ref} cx={50} cy={50} r={30} />
28
+ * </>
29
+ * ```
30
+ *
31
+ * @param props - FocusRingProps
32
+ * @returns JSX element with focus ring or null
33
+ */
34
+ export declare const FocusRing: FC<FocusRingProps>;
35
+ //# sourceMappingURL=focusRing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusRing.d.ts","sourceRoot":"","sources":["../../../../src/components/focusRing/focusRing.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,OAAO,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAsCxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,SAAS,oBAAqB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FocusRingInline } from './components/FocusRingInline';
3
+ import { FocusRingSeparate } from './components/FocusRingSeparate';
4
+ import './focusRing.css';
5
+ const FocusRingComponent = ({ children, dataTestId = 'focus-ring', disabled = false, focusConfig, isFocused, targetRef, }) => {
6
+ if (children) {
7
+ return (_jsx(FocusRingInline, { dataTestId: dataTestId, disabled: disabled, focusConfig: focusConfig, isFocused: isFocused, children: children }));
8
+ }
9
+ if (targetRef) {
10
+ return (_jsx(FocusRingSeparate, { dataTestId: dataTestId, disabled: disabled, focusConfig: focusConfig, isFocused: isFocused, targetRef: targetRef }));
11
+ }
12
+ return null;
13
+ };
14
+ /**
15
+ * FocusRing - Controlled, purely decorative component for rendering focus rings around SVG elements.
16
+ *
17
+ * **Key Characteristics:**
18
+ * - **Controlled Component**: Parent manages `isFocused` state
19
+ * - **Purely Decorative**: Does not intercept or manage events
20
+ * - **Two Modes**: Inline (children) or Separate (targetRef) rendering
21
+ * - **Zero Configuration**: Automatic element detection
22
+ *
23
+ * **Two Modes:**
24
+ *
25
+ * 1. **Inline (children)** - Wraps element, focus ring rendered inline, z-order handled automatically
26
+ * 2. **Separate (targetRef)** - Only renders focus ring, allows precise z-order control
27
+ *
28
+ * **IMPORTANT NOTE: Z-Order with Adaptive Variant**
29
+ *
30
+ * When using `variant: 'adaptive'` (default) with `targetRef` mode, the FocusRing **MUST be rendered BEFORE**
31
+ * the target element in SVG document order. Otherwise, focus ring strokes will cover the element.
32
+ *
33
+ * ```tsx
34
+ * // CORRECT: FocusRing before element
35
+ * <>
36
+ * <FocusRing targetRef={ref} isFocused={focused} />
37
+ * <circle ref={ref} cx={50} cy={50} r={30} />
38
+ * </>
39
+ * ```
40
+ *
41
+ * @param props - FocusRingProps
42
+ * @returns JSX element with focus ring or null
43
+ */
44
+ export const FocusRing = FocusRingComponent;
@@ -0,0 +1,40 @@
1
+ import type { ReactElement, RefObject } from 'react';
2
+ import type { FocusConfig } from '../../types/focusConfig.type';
3
+ import type { FocusRingLayers } from './utils/utils.types';
4
+ export interface FocusRingProps {
5
+ /**
6
+ * The SVG graphics element to wrap with focus ring (Mode 1: inline rendering).
7
+ * Must be a renderable SVG element (path, circle, rect, g, etc.).
8
+ * Mutually exclusive with targetRef - provide either children OR targetRef, not both.
9
+ */
10
+ children?: ReactElement;
11
+ /**
12
+ * Reference to external SVG graphics element (Mode 2: separate rendering).
13
+ * Must be a renderable SVG element (path, circle, rect, g, etc.).
14
+ * When provided, only the focus ring is rendered (not the element itself).
15
+ * Mutually exclusive with children - provide either children OR targetRef, not both.
16
+ */
17
+ targetRef?: RefObject<SVGGraphicsElement>;
18
+ /**
19
+ * Controlled focus state (REQUIRED).
20
+ * The parent component must manage this state and update it based on focus/blur events.
21
+ * FocusRing is purely decorative and does not manage state internally.
22
+ */
23
+ isFocused: boolean;
24
+ /** Test identifier for the focus ring elements */
25
+ dataTestId?: string;
26
+ /** Whether the focus ring is disabled */
27
+ disabled?: boolean;
28
+ /** Configuration for focus ring appearance */
29
+ focusConfig?: FocusConfig;
30
+ }
31
+ /**
32
+ * Props for the internal FocusRingRenderer component
33
+ */
34
+ export interface FocusRingRendererProps {
35
+ /** Test identifier for the focus ring elements */
36
+ dataTestId: string;
37
+ /** Pre-computed layers (unified structure for both adaptive and bounding-box modes) */
38
+ layers?: FocusRingLayers;
39
+ }
40
+ //# sourceMappingURL=focusRing.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusRing.types.d.ts","sourceRoot":"","sources":["../../../../src/components/focusRing/focusRing.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IAExB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAE1C;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IAEnB,uFAAuF;IACvF,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ import { type RefObject } from 'react';
2
+ import { type FocusConfig } from '../../../types/focusConfig.type';
3
+ import type { FocusRingLayers } from '../utils/utils.types';
4
+ export interface UseFocusRingDataOptions {
5
+ elementRef: RefObject<SVGGraphicsElement>;
6
+ isFocused: boolean;
7
+ focusConfig?: FocusConfig;
8
+ }
9
+ export interface FocusRingData {
10
+ resolvedConfig: Required<FocusConfig>;
11
+ layers: FocusRingLayers | undefined;
12
+ }
13
+ /**
14
+ * Hook that handles all focus ring data calculation logic.
15
+ * Separated from rendering concerns for better testability and reusability.
16
+ *
17
+ * This hook:
18
+ * - Generates layers for both adaptive and bounding-box variants
19
+ * - Both variants return the same FocusRingLayers structure
20
+ * - Only calculates what's needed based on the variant
21
+ * - Manages all the state and effects related to focus ring data
22
+ *
23
+ * @param options - Configuration options for the hook
24
+ * @returns Focus ring data including resolved config and calculated layers
25
+ */
26
+ export declare function useFocusRingData({ elementRef, focusConfig, isFocused, }: UseFocusRingDataOptions): FocusRingData;
27
+ //# sourceMappingURL=useFocusRingData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocusRingData.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/hooks/useFocusRingData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAgC,MAAM,OAAO,CAAC;AAErE,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,0BAA0B,CAAC;AAO5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,WAAW,EACX,SAAS,GACV,EAAE,uBAAuB,GAAG,aAAa,CA+DzC"}
@@ -0,0 +1,67 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import { getFocusConfig } from '../../../types/focusConfig.type';
3
+ import { SVG_GEOMETRIC_ATTRIBUTES, createAdaptiveFocusRings, } from '../utils/createAdaptiveFocusRings';
4
+ import { createBoundingBoxFocusRings } from '../utils/createBoundingBoxFocusRings';
5
+ /**
6
+ * Hook that handles all focus ring data calculation logic.
7
+ * Separated from rendering concerns for better testability and reusability.
8
+ *
9
+ * This hook:
10
+ * - Generates layers for both adaptive and bounding-box variants
11
+ * - Both variants return the same FocusRingLayers structure
12
+ * - Only calculates what's needed based on the variant
13
+ * - Manages all the state and effects related to focus ring data
14
+ *
15
+ * @param options - Configuration options for the hook
16
+ * @returns Focus ring data including resolved config and calculated layers
17
+ */
18
+ export function useFocusRingData({ elementRef, focusConfig, isFocused, }) {
19
+ // Resolve config once at the top
20
+ const resolvedConfig = useMemo(() => getFocusConfig(focusConfig), [focusConfig]);
21
+ const [layers, setLayers] = useState(undefined);
22
+ // Calculation happens when isFocused changes or when focus config changes
23
+ // MutationObserver watches for geometric attribute changes
24
+ // to automatically regenerate layers when the element moves or resizes
25
+ useEffect(() => {
26
+ if (!elementRef?.current || !isFocused) {
27
+ setLayers(undefined);
28
+ return undefined;
29
+ }
30
+ const element = elementRef.current;
31
+ // Function to calculate focus ring layers from current DOM state
32
+ const calculateRings = () => {
33
+ // Strategy 1: Adaptive variant - generate layers from DOM element
34
+ if (resolvedConfig.variant === 'adaptive') {
35
+ const adaptiveLayers = createAdaptiveFocusRings(element, resolvedConfig);
36
+ setLayers(adaptiveLayers);
37
+ }
38
+ // Strategy 2: Bounding-box variant - detect bounds and calculate layers
39
+ if (resolvedConfig.variant === 'bounding-box') {
40
+ const boundingBoxLayers = createBoundingBoxFocusRings(element, resolvedConfig);
41
+ setLayers(boundingBoxLayers);
42
+ }
43
+ };
44
+ // Calculate layers initially
45
+ calculateRings();
46
+ // Set up MutationObserver to detect changes in geometric attributes
47
+ // This ensures focus ring updates automatically when the element moves or resizes
48
+ const observer = new MutationObserver(mutations => {
49
+ const hasGeometricChanges = mutations.some(mutation => mutation.type === 'attributes' &&
50
+ SVG_GEOMETRIC_ATTRIBUTES.includes(mutation.attributeName ?? ''));
51
+ if (hasGeometricChanges) {
52
+ // Recalculate focus rings on relevant attribute changes
53
+ calculateRings();
54
+ }
55
+ });
56
+ // Observe only geometric attributes that affect position and size
57
+ observer.observe(element, {
58
+ attributeFilter: [...SVG_GEOMETRIC_ATTRIBUTES],
59
+ attributes: true,
60
+ });
61
+ return () => observer.disconnect();
62
+ }, [isFocused, resolvedConfig]);
63
+ return {
64
+ layers,
65
+ resolvedConfig,
66
+ };
67
+ }
@@ -0,0 +1,3 @@
1
+ export { FocusRing } from './focusRing';
2
+ export type { FocusRingProps, FocusRingRendererProps } from './focusRing.types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/focusRing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1 @@
1
+ export { FocusRing } from './focusRing';
@@ -0,0 +1,7 @@
1
+ import type { ForwardedRef } from 'react';
2
+ /**
3
+ * Composes multiple refs into a single ref callback
4
+ * Allows using both internal and external refs simultaneously
5
+ */
6
+ export declare function composeRefs<T>(...refs: Array<ForwardedRef<T> | undefined>): (instance: T | null) => void;
7
+ //# sourceMappingURL=composeRefs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composeRefs.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/utils/composeRefs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,GAAG,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAC1C,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAU9B"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Composes multiple refs into a single ref callback
3
+ * Allows using both internal and external refs simultaneously
4
+ */
5
+ export function composeRefs(...refs) {
6
+ return (instance) => {
7
+ refs.forEach(ref => {
8
+ if (typeof ref === 'function') {
9
+ ref(instance);
10
+ }
11
+ else if (ref) {
12
+ ref.current = instance;
13
+ }
14
+ });
15
+ };
16
+ }
@@ -0,0 +1,24 @@
1
+ import type { FocusConfig } from '../../../types/focusConfig.type';
2
+ import type { FocusRingLayers } from './utils.types';
3
+ /**
4
+ * SVG geometric attributes that define shape position and dimensions.
5
+ * These attributes are extracted from the original element to create focus rings.
6
+ * Also used by MutationObserver to detect when focus rings need to be regenerated.
7
+ */
8
+ export declare const SVG_GEOMETRIC_ATTRIBUTES: string[];
9
+ /**
10
+ * Creates adaptive focus ring layers from a DOM SVGElement.
11
+ *
12
+ * This function reads properties directly from the DOM element and creates
13
+ * props objects for rendering new SVG elements with scaled stroke-width for the focus rings.
14
+ * The focus rings adapt to the exact shape of the element (circle → circle, path → path, etc.)
15
+ *
16
+ * This unified approach works for both targetRef and children modes by
17
+ * reading from the mounted DOM element.
18
+ *
19
+ * @param element - The SVG graphics element to create focus rings for
20
+ * @param focusConfig - Focus ring configuration (colors, widths, gap)
21
+ * @returns Focus ring layers (outer and inner props) or null if not supported
22
+ */
23
+ export declare function createAdaptiveFocusRings(element: SVGGraphicsElement, focusConfig: Required<FocusConfig>): FocusRingLayers | undefined;
24
+ //# sourceMappingURL=createAdaptiveFocusRings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAdaptiveFocusRings.d.ts","sourceRoot":"","sources":["../../../../../src/components/focusRing/utils/createAdaptiveFocusRings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,UAsBpC,CAAC;AAqBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,GACjC,eAAe,GAAG,SAAS,CAkE7B"}