@kubit-ui-web/react-charts 1.5.0 → 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 (161) hide show
  1. package/dist/cjs/charts/lineChart/fragments/lineChartPath.d.ts.map +1 -1
  2. package/dist/cjs/charts/lineChart/fragments/lineChartPath.js +8 -4
  3. package/dist/cjs/components/focusRing/components/FocusRingInline.d.ts +25 -0
  4. package/dist/cjs/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  5. package/dist/cjs/components/focusRing/components/FocusRingInline.js +37 -0
  6. package/dist/cjs/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  7. package/dist/cjs/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  8. package/dist/cjs/components/focusRing/components/FocusRingRenderer.js +25 -0
  9. package/dist/cjs/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  10. package/dist/cjs/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  11. package/dist/cjs/components/focusRing/components/FocusRingSeparate.js +45 -0
  12. package/dist/cjs/components/focusRing/focusRing.css +14 -0
  13. package/dist/cjs/components/focusRing/focusRing.d.ts +35 -0
  14. package/dist/cjs/components/focusRing/focusRing.d.ts.map +1 -0
  15. package/dist/cjs/components/focusRing/focusRing.js +44 -0
  16. package/dist/cjs/components/focusRing/focusRing.types.d.ts +40 -0
  17. package/dist/cjs/components/focusRing/focusRing.types.d.ts.map +1 -0
  18. package/dist/cjs/components/focusRing/focusRing.types.js +1 -0
  19. package/dist/cjs/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  20. package/dist/cjs/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  21. package/dist/cjs/components/focusRing/hooks/useFocusRingData.js +67 -0
  22. package/dist/cjs/components/focusRing/index.d.ts +3 -0
  23. package/dist/cjs/components/focusRing/index.d.ts.map +1 -0
  24. package/dist/cjs/components/focusRing/index.js +1 -0
  25. package/dist/cjs/components/focusRing/utils/composeRefs.d.ts +7 -0
  26. package/dist/cjs/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  27. package/dist/cjs/components/focusRing/utils/composeRefs.js +16 -0
  28. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  29. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  30. package/dist/cjs/components/focusRing/utils/createAdaptiveFocusRings.js +141 -0
  31. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  32. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  33. package/dist/cjs/components/focusRing/utils/createBoundingBoxFocusRings.js +126 -0
  34. package/dist/cjs/components/focusRing/utils/utils.types.d.ts +52 -0
  35. package/dist/cjs/components/focusRing/utils/utils.types.d.ts.map +1 -0
  36. package/dist/cjs/components/focusRing/utils/utils.types.js +1 -0
  37. package/dist/cjs/components/index.d.ts +1 -0
  38. package/dist/cjs/components/index.d.ts.map +1 -1
  39. package/dist/cjs/components/index.js +1 -0
  40. package/dist/cjs/components/plot/plot.d.ts.map +1 -1
  41. package/dist/cjs/components/plot/plot.js +7 -19
  42. package/dist/cjs/components/zoomArea/components/SelectionArea.d.ts +3 -23
  43. package/dist/cjs/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  44. package/dist/cjs/components/zoomArea/components/SelectionArea.js +7 -39
  45. package/dist/cjs/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  46. package/dist/cjs/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  47. package/dist/cjs/components/zoomArea/components/ZoomHandler.js +2 -15
  48. package/dist/cjs/components/zoomArea/components/index.d.ts +1 -1
  49. package/dist/cjs/components/zoomArea/components/index.d.ts.map +1 -1
  50. package/dist/cjs/components/zoomArea/components/index.js +1 -1
  51. package/dist/cjs/components/zoomArea/zoomArea.js +6 -6
  52. package/dist/cjs/components/zoomArea/zoomArea.type.d.ts +1 -1
  53. package/dist/cjs/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  54. package/dist/cjs/types/focusConfig.type.d.ts +15 -3
  55. package/dist/cjs/types/focusConfig.type.d.ts.map +1 -1
  56. package/dist/cjs/types/focusConfig.type.js +14 -1
  57. package/dist/esm/charts/lineChart/fragments/lineChartPath.d.ts.map +1 -1
  58. package/dist/esm/charts/lineChart/fragments/lineChartPath.js +8 -4
  59. package/dist/esm/components/focusRing/components/FocusRingInline.d.ts +25 -0
  60. package/dist/esm/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  61. package/dist/esm/components/focusRing/components/FocusRingInline.js +37 -0
  62. package/dist/esm/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  63. package/dist/esm/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  64. package/dist/esm/components/focusRing/components/FocusRingRenderer.js +25 -0
  65. package/dist/esm/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  66. package/dist/esm/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  67. package/dist/esm/components/focusRing/components/FocusRingSeparate.js +45 -0
  68. package/dist/esm/components/focusRing/focusRing.css +14 -0
  69. package/dist/esm/components/focusRing/focusRing.d.ts +35 -0
  70. package/dist/esm/components/focusRing/focusRing.d.ts.map +1 -0
  71. package/dist/esm/components/focusRing/focusRing.js +44 -0
  72. package/dist/esm/components/focusRing/focusRing.types.d.ts +40 -0
  73. package/dist/esm/components/focusRing/focusRing.types.d.ts.map +1 -0
  74. package/dist/esm/components/focusRing/focusRing.types.js +1 -0
  75. package/dist/esm/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  76. package/dist/esm/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  77. package/dist/esm/components/focusRing/hooks/useFocusRingData.js +67 -0
  78. package/dist/esm/components/focusRing/index.d.ts +3 -0
  79. package/dist/esm/components/focusRing/index.d.ts.map +1 -0
  80. package/dist/esm/components/focusRing/index.js +1 -0
  81. package/dist/esm/components/focusRing/utils/composeRefs.d.ts +7 -0
  82. package/dist/esm/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  83. package/dist/esm/components/focusRing/utils/composeRefs.js +16 -0
  84. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  85. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  86. package/dist/esm/components/focusRing/utils/createAdaptiveFocusRings.js +141 -0
  87. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  88. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  89. package/dist/esm/components/focusRing/utils/createBoundingBoxFocusRings.js +126 -0
  90. package/dist/esm/components/focusRing/utils/utils.types.d.ts +52 -0
  91. package/dist/esm/components/focusRing/utils/utils.types.d.ts.map +1 -0
  92. package/dist/esm/components/focusRing/utils/utils.types.js +1 -0
  93. package/dist/esm/components/index.d.ts +1 -0
  94. package/dist/esm/components/index.d.ts.map +1 -1
  95. package/dist/esm/components/index.js +1 -0
  96. package/dist/esm/components/plot/plot.d.ts.map +1 -1
  97. package/dist/esm/components/plot/plot.js +7 -19
  98. package/dist/esm/components/zoomArea/components/SelectionArea.d.ts +3 -23
  99. package/dist/esm/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  100. package/dist/esm/components/zoomArea/components/SelectionArea.js +7 -39
  101. package/dist/esm/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  102. package/dist/esm/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  103. package/dist/esm/components/zoomArea/components/ZoomHandler.js +2 -15
  104. package/dist/esm/components/zoomArea/components/index.d.ts +1 -1
  105. package/dist/esm/components/zoomArea/components/index.d.ts.map +1 -1
  106. package/dist/esm/components/zoomArea/components/index.js +1 -1
  107. package/dist/esm/components/zoomArea/zoomArea.js +6 -6
  108. package/dist/esm/components/zoomArea/zoomArea.type.d.ts +1 -1
  109. package/dist/esm/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  110. package/dist/esm/types/focusConfig.type.d.ts +15 -3
  111. package/dist/esm/types/focusConfig.type.d.ts.map +1 -1
  112. package/dist/esm/types/focusConfig.type.js +14 -1
  113. package/dist/kubit-ui-web-react-charts.cjs.js +1 -1
  114. package/dist/kubit-ui-web-react-charts.es.js +1 -1
  115. package/dist/kubit-ui-web-react-charts.umd.js +1 -1
  116. package/dist/react-charts.css +1 -1
  117. package/dist/types/charts/lineChart/fragments/lineChartPath.d.ts.map +1 -1
  118. package/dist/types/components/focusRing/components/FocusRingInline.d.ts +25 -0
  119. package/dist/types/components/focusRing/components/FocusRingInline.d.ts.map +1 -0
  120. package/dist/types/components/focusRing/components/FocusRingRenderer.d.ts +13 -0
  121. package/dist/types/components/focusRing/components/FocusRingRenderer.d.ts.map +1 -0
  122. package/dist/types/components/focusRing/components/FocusRingSeparate.d.ts +40 -0
  123. package/dist/types/components/focusRing/components/FocusRingSeparate.d.ts.map +1 -0
  124. package/dist/types/components/focusRing/focusRing.d.ts +34 -0
  125. package/dist/types/components/focusRing/focusRing.d.ts.map +1 -0
  126. package/dist/types/components/focusRing/focusRing.types.d.ts +40 -0
  127. package/dist/types/components/focusRing/focusRing.types.d.ts.map +1 -0
  128. package/dist/types/components/focusRing/hooks/useFocusRingData.d.ts +27 -0
  129. package/dist/types/components/focusRing/hooks/useFocusRingData.d.ts.map +1 -0
  130. package/dist/types/components/focusRing/index.d.ts +3 -0
  131. package/dist/types/components/focusRing/index.d.ts.map +1 -0
  132. package/dist/types/components/focusRing/utils/composeRefs.d.ts +7 -0
  133. package/dist/types/components/focusRing/utils/composeRefs.d.ts.map +1 -0
  134. package/dist/types/components/focusRing/utils/createAdaptiveFocusRings.d.ts +24 -0
  135. package/dist/types/components/focusRing/utils/createAdaptiveFocusRings.d.ts.map +1 -0
  136. package/dist/types/components/focusRing/utils/createBoundingBoxFocusRings.d.ts +33 -0
  137. package/dist/types/components/focusRing/utils/createBoundingBoxFocusRings.d.ts.map +1 -0
  138. package/dist/types/components/focusRing/utils/utils.types.d.ts +52 -0
  139. package/dist/types/components/focusRing/utils/utils.types.d.ts.map +1 -0
  140. package/dist/types/components/index.d.ts +1 -0
  141. package/dist/types/components/index.d.ts.map +1 -1
  142. package/dist/types/components/plot/plot.d.ts.map +1 -1
  143. package/dist/types/components/zoomArea/components/SelectionArea.d.ts +3 -23
  144. package/dist/types/components/zoomArea/components/SelectionArea.d.ts.map +1 -1
  145. package/dist/types/components/zoomArea/components/ZoomHandler.d.ts +3 -3
  146. package/dist/types/components/zoomArea/components/ZoomHandler.d.ts.map +1 -1
  147. package/dist/types/components/zoomArea/components/index.d.ts +1 -1
  148. package/dist/types/components/zoomArea/components/index.d.ts.map +1 -1
  149. package/dist/types/components/zoomArea/zoomArea.type.d.ts +1 -1
  150. package/dist/types/components/zoomArea/zoomArea.type.d.ts.map +1 -1
  151. package/dist/types/types/focusConfig.type.d.ts +15 -3
  152. package/dist/types/types/focusConfig.type.d.ts.map +1 -1
  153. package/package.json +1 -1
  154. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  155. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
  156. package/dist/cjs/utils/calculateFocusOutline/calculateFocusOutline.js +0 -80
  157. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  158. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
  159. package/dist/esm/utils/calculateFocusOutline/calculateFocusOutline.js +0 -80
  160. package/dist/types/utils/calculateFocusOutline/calculateFocusOutline.d.ts +0 -73
  161. package/dist/types/utils/calculateFocusOutline/calculateFocusOutline.d.ts.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
2
+ import { useMemo, useRef } from 'react';
3
3
  import { SvgContainer } from '../../components/svgContainer/svgContainer';
4
- import { getFocusConfig } from '../../utils/calculateFocusOutline/calculateFocusOutline';
5
4
  import { getDataFingerprint } from '../../utils/getDataFingerprint/getDataFingerprint';
5
+ import { FocusRing } from '../focusRing/focusRing';
6
6
  import { LineRenderer } from './components/LineRenderer';
7
- import { SelectionArea, SelectionAreaFocusRing } from './components/SelectionArea';
7
+ import { SelectionArea } from './components/SelectionArea';
8
8
  import { ZoomHandler } from './components/ZoomHandler';
9
9
  import { useDragInteraction } from './hooks/useDragInteraction';
10
10
  import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
@@ -34,8 +34,6 @@ initialRange, interactionConfig, lines, onDataChange, role, screenReaderTextConf
34
34
  const resolvedInteractionConfig = getInteractionConfig(interactionConfig);
35
35
  // Resolve selection config with defaults
36
36
  const resolvedSelectionConfig = getSelectionConfig(selectionConfig);
37
- // Resolve focus config with defaults
38
- const resolvedFocusConfig = getFocusConfig(focusConfig);
39
37
  // Hook for core data filtering functionality
40
38
  const { currentRange, handleRangeChange } = useZoomData({
41
39
  data,
@@ -52,6 +50,8 @@ initialRange, interactionConfig, lines, onDataChange, role, screenReaderTextConf
52
50
  // Create a fingerprint of the data/lines to avoid unnecessary updates
53
51
  const dataFingerprint = getDataFingerprint(data);
54
52
  const linesFingerprint = JSON.stringify(lines);
53
+ // Create ref for SelectionArea to enable separate focus ring rendering
54
+ const selectionAreaRef = useRef(null);
55
55
  const accessibilityLabels = generateAccessibilityLabels(data, xKey, currentRange, screenReaderTextConfig);
56
56
  // Memoize expensive line calculations
57
57
  const linesData = useMemo(() => {
@@ -76,5 +76,5 @@ initialRange, interactionConfig, lines, onDataChange, role, screenReaderTextConf
76
76
  });
77
77
  return (_jsxs(SvgContainer, { ref: groupRef, ariaHidden: ariaHidden, ariaLabel: ariaLabel, backgroundColor: backgroundColor, caption: caption, className: classNames, "data-testid": dataTestId, height: height,
78
78
  // set overflow visible so handlers and focus rings are visible always
79
- overflow: "visible", role: role, viewBox: viewBox, width: width, ...eventHandlers, children: [_jsx(LineRenderer, { linesData: linesData }), _jsx(SelectionArea, { currentRange: currentRange, dataLength: data.length, dataTestId: `${dataTestId}-selection-area`, endX: endX, height: parsedCanvas.height, screenReaderText: accessibilityLabels.selectionArea, selectionConfig: resolvedSelectionConfig, startX: startX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.SELECTION_AREA), onKeyDown: handleKeyDown(ZoomAreaElements.SELECTION_AREA), onMouseDown: handleMouseDown(ZoomAreaElements.SELECTION_AREA), onTouchStart: handleTouchStart(ZoomAreaElements.SELECTION_AREA) }), _jsx(ZoomHandler, { dataTestId: `${dataTestId}-start-handler`, focusConfig: resolvedFocusConfig, handlerConfig: handlerConfig, height: parsedCanvas.height, isFocused: isFocused(ZoomAreaElements.START_HANDLER), max: currentRange.end - resolvedInteractionConfig.minHandlerDistance, min: 0, screenReaderText: accessibilityLabels.startHandler, type: ZoomAreaElements.START_HANDLER, value: currentRange.start, x: startX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.START_HANDLER), onKeyDown: handleKeyDown(ZoomAreaElements.START_HANDLER), onMouseDown: handleMouseDown(ZoomAreaElements.START_HANDLER), onTouchStart: handleTouchStart(ZoomAreaElements.START_HANDLER) }), _jsx(ZoomHandler, { dataTestId: `${dataTestId}-end-handler`, focusConfig: resolvedFocusConfig, handlerConfig: handlerConfig, height: parsedCanvas.height, isFocused: isFocused(ZoomAreaElements.END_HANDLER), max: data.length - 1, min: currentRange.start + resolvedInteractionConfig.minHandlerDistance, screenReaderText: accessibilityLabels.endHandler, type: ZoomAreaElements.END_HANDLER, value: currentRange.end, x: endX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.END_HANDLER), onKeyDown: handleKeyDown(ZoomAreaElements.END_HANDLER), onMouseDown: handleMouseDown(ZoomAreaElements.END_HANDLER), onTouchStart: handleTouchStart(ZoomAreaElements.END_HANDLER) }), _jsx(SelectionAreaFocusRing, { endX: endX, focusConfig: resolvedFocusConfig, height: parsedCanvas.height, isFocused: isFocused(ZoomAreaElements.SELECTION_AREA), startX: startX })] }));
79
+ overflow: "visible", role: role, viewBox: viewBox, width: width, ...eventHandlers, children: [_jsx(LineRenderer, { linesData: linesData }), _jsx(SelectionArea, { ref: selectionAreaRef, currentRange: currentRange, dataLength: data.length, dataTestId: `${dataTestId}-selection-area`, endX: endX, height: parsedCanvas.height, screenReaderText: accessibilityLabels.selectionArea, selectionConfig: resolvedSelectionConfig, startX: startX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.SELECTION_AREA), onKeyDown: handleKeyDown(ZoomAreaElements.SELECTION_AREA), onMouseDown: handleMouseDown(ZoomAreaElements.SELECTION_AREA), onTouchStart: handleTouchStart(ZoomAreaElements.SELECTION_AREA) }), _jsx(ZoomHandler, { dataTestId: `${dataTestId}-start-handler`, focusConfig: focusConfig, handlerConfig: handlerConfig, height: parsedCanvas.height, isFocused: isFocused(ZoomAreaElements.START_HANDLER), max: currentRange.end - resolvedInteractionConfig.minHandlerDistance, min: 0, screenReaderText: accessibilityLabels.startHandler, type: ZoomAreaElements.START_HANDLER, value: currentRange.start, x: startX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.START_HANDLER), onKeyDown: handleKeyDown(ZoomAreaElements.START_HANDLER), onMouseDown: handleMouseDown(ZoomAreaElements.START_HANDLER), onTouchStart: handleTouchStart(ZoomAreaElements.START_HANDLER) }), _jsx(ZoomHandler, { dataTestId: `${dataTestId}-end-handler`, focusConfig: focusConfig, handlerConfig: handlerConfig, height: parsedCanvas.height, isFocused: isFocused(ZoomAreaElements.END_HANDLER), max: data.length - 1, min: currentRange.start + resolvedInteractionConfig.minHandlerDistance, screenReaderText: accessibilityLabels.endHandler, type: ZoomAreaElements.END_HANDLER, value: currentRange.end, x: endX, onBlur: handleBlur, onFocus: handleFocus(ZoomAreaElements.END_HANDLER), onKeyDown: handleKeyDown(ZoomAreaElements.END_HANDLER), onMouseDown: handleMouseDown(ZoomAreaElements.END_HANDLER), onTouchStart: handleTouchStart(ZoomAreaElements.END_HANDLER) }), _jsx(FocusRing, { dataTestId: "selection-area-focus", focusConfig: { ...focusConfig, variant: 'bounding-box' }, isFocused: isFocused(ZoomAreaElements.SELECTION_AREA), targetRef: selectionAreaRef })] }));
80
80
  };
@@ -121,7 +121,7 @@ export interface ZoomAreaProps {
121
121
  /** Custom selection area configuration */
122
122
  selectionConfig?: ZoomAreaSelectionConfig;
123
123
  /** Custom focus configuration applied to all focusable elements */
124
- focusConfig?: FocusConfig;
124
+ focusConfig?: Omit<FocusConfig, 'variant'>;
125
125
  /** Configuration for interaction behavior (keyboard navigation, handler distances) */
126
126
  interactionConfig?: ZoomAreaInteractionConfig;
127
127
  /** Configuration for accessibility label templates */
@@ -1 +1 @@
1
- {"version":3,"file":"zoomArea.type.d.ts","sourceRoot":"","sources":["../../../../src/components/zoomArea/zoomArea.type.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zoomArea.type.d.ts","sourceRoot":"","sources":["../../../../src/components/zoomArea/zoomArea.type.ts"],"names":[],"mappings":"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"}
@@ -3,16 +3,22 @@
3
3
  *
4
4
  * - `outlineColor` - Color of the outer outline when focused. Defaults to #0078D7.
5
5
  * - `outlineStrokeWidth` - Stroke width of the outer outline. Defaults to 2.
6
- * - `innerStrokeColor` - Color of the inner outline when focused. Defaults to #FFFFFF.
6
+ * - `innerColor` - Color of the inner outline when focused. Defaults to #FFFFFF.
7
7
  * - `innerStrokeWidth` - Stroke width of the inner outline. Defaults to 2.
8
- * - `gap` - Gap between the inner and outer outline. Defaults to 0.
8
+ * - `gap` - Gap between the element and the focus rings. Defaults to 0.
9
+ * Note: Only applies when variant is 'bounding-box'. Ignored in 'adaptive' mode.
10
+ * - `variant` - Focus ring rendering mode. Defaults to 'adaptive'.
11
+ * - 'adaptive': Ring follows the exact shape of the element (circle → circular ring, path → path ring)
12
+ * - 'bounding-box': Ring is always rectangular, wrapping the element's bounding box
9
13
  */
10
14
  export interface FocusConfig {
11
15
  outlineColor?: string;
12
16
  outlineStrokeWidth?: number;
13
17
  innerColor?: string;
14
18
  innerStrokeWidth?: number;
19
+ /** Only applicable when variant is 'bounding-box' */
15
20
  gap?: number;
21
+ variant?: 'adaptive' | 'bounding-box';
16
22
  }
17
23
  export declare const FOCUS_DEFAULT: {
18
24
  /** Focus ring color */
@@ -23,7 +29,13 @@ export declare const FOCUS_DEFAULT: {
23
29
  readonly INNER_FOCUS_STROKE_WIDTH: 2;
24
30
  /** Focus ring outer stroke width */
25
31
  readonly OUTER_FOCUS_STROKE_WIDTH: 2;
26
- /** Gap between element and outlines */
32
+ /** Gap between element and outlines (only applies in bounding-box variant) */
27
33
  readonly OUTLINES_GAP: 0;
34
+ /** Focus ring rendering variant */
35
+ readonly VARIANT: "adaptive";
28
36
  };
37
+ /**
38
+ * Helper function to get complete focus config with defaults applied
39
+ */
40
+ export declare const getFocusConfig: (focusConfig?: FocusConfig) => Required<FocusConfig>;
29
41
  //# sourceMappingURL=focusConfig.type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"focusConfig.type.d.ts","sourceRoot":"","sources":["../../../src/types/focusConfig.type.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,aAAa;IACxB,uBAAuB;;IAEvB,8BAA8B;;IAE9B,oCAAoC;;IAEpC,oCAAoC;;IAEpC,uCAAuC;;CAE/B,CAAC"}
1
+ {"version":3,"file":"focusConfig.type.d.ts","sourceRoot":"","sources":["../../../src/types/focusConfig.type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,UAAU,GAAG,cAAc,CAAC;CACvC;AAED,eAAO,MAAM,aAAa;IACxB,uBAAuB;;IAEvB,8BAA8B;;IAE9B,oCAAoC;;IAEpC,oCAAoC;;IAEpC,8EAA8E;;IAE9E,mCAAmC;;CAE3B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,cAAc,WAAW,KAAG,QAAQ,CAAC,WAAW,CAO7E,CAAC"}
@@ -7,6 +7,19 @@ export const FOCUS_DEFAULT = {
7
7
  INNER_FOCUS_STROKE_WIDTH: 2,
8
8
  /** Focus ring outer stroke width */
9
9
  OUTER_FOCUS_STROKE_WIDTH: 2,
10
- /** Gap between element and outlines */
10
+ /** Gap between element and outlines (only applies in bounding-box variant) */
11
11
  OUTLINES_GAP: 0,
12
+ /** Focus ring rendering variant */
13
+ VARIANT: 'adaptive',
12
14
  };
15
+ /**
16
+ * Helper function to get complete focus config with defaults applied
17
+ */
18
+ export const getFocusConfig = (focusConfig) => ({
19
+ gap: focusConfig?.gap ?? FOCUS_DEFAULT.OUTLINES_GAP,
20
+ innerColor: focusConfig?.innerColor ?? FOCUS_DEFAULT.FOCUS_INNER,
21
+ innerStrokeWidth: focusConfig?.innerStrokeWidth ?? FOCUS_DEFAULT.INNER_FOCUS_STROKE_WIDTH,
22
+ outlineColor: focusConfig?.outlineColor ?? FOCUS_DEFAULT.FOCUS_COLOR,
23
+ outlineStrokeWidth: focusConfig?.outlineStrokeWidth ?? FOCUS_DEFAULT.OUTER_FOCUS_STROKE_WIDTH,
24
+ variant: focusConfig?.variant ?? FOCUS_DEFAULT.VARIANT,
25
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"lineChartPath.d.ts","sourceRoot":"","sources":["../../../../../src/charts/lineChart/fragments/lineChartPath.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAoD,MAAM,OAAO,CAAC;AAWlF,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,qBAAqB,CAAC;AAO7B,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CA8LhD,CAAC"}
1
+ {"version":3,"file":"lineChartPath.d.ts","sourceRoot":"","sources":["../../../../../src/charts/lineChart/fragments/lineChartPath.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAoD,MAAM,OAAO,CAAC;AAWlF,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,qBAAqB,CAAC;AAO7B,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAoMhD,CAAC"}
@@ -65,9 +65,13 @@ export const LineChartPath = ({ ariaLabel, closestClick, curved, getNodeFocusInf
65
65
  const pressedRef = useRef(null);
66
66
  // the projection line logic
67
67
  const { autoClick, lineIndicator, ...nodeIndicatorConfig } = indicatorConfig || {};
68
- // line indicator <Y> coordinates
69
- const y1 = context.extraSpaceTopY;
70
- const y2 = Number(context.canvasHeight) - context.extraSpaceBottomY;
68
+ // Calculate line indicator boundaries using pre-calculated axis coordinates
69
+ // Y-axis: spans from top to bottom of chart area
70
+ const { y1, y2 } = yAxisCoordinates.coordinates;
71
+ // X-axis: constrain to path area to prevent overflow into axis labels
72
+ // The indicator should only render within the data visualization area
73
+ const { x1: pathAreaMinX, x2: pathAreaMaxX } = xAxisCoordinates.coordinates;
74
+ const isCursorWithinPathArea = context.xCursor >= pathAreaMinX && context.xCursor <= pathAreaMaxX;
71
75
  // the path
72
76
  const { tickValues: xTickValues } = xAxisCoordinates;
73
77
  const { tickValues: yTickValues } = yAxisCoordinates;
@@ -141,5 +145,5 @@ export const LineChartPath = ({ ariaLabel, closestClick, curved, getNodeFocusInf
141
145
  // Handle deprecated ariaLabel - give precedence to ariaLabel for backward compatibility
142
146
  ...(ariaLabel && { 'aria-label': ariaLabel }),
143
147
  };
144
- return (_jsxs(_Fragment, { children: [_jsx(Path, { ref: innerRefs, d: dataOnlyLine, dFill: dataFill, dataTestId: `${context.dataTestId}path`, dataValue: context.data, points: points, xKey: context.xKey, onClick: handleClick, ...mergedProps }), lineProjection && (_jsx(LineChartProjection, { curved: curved, dataKey: props.dataKey, lineProjection: lineProjection, points: points, svgHeight: Number(context.canvasHeight) - context.extraSpaceBottomY })), showIndicator && (_jsxs(_Fragment, { children: [!!lineIndicator && (_jsx(Line, { ...lineIndicator, className: "pointer-events-none", x1: context.xCursor, x2: context.xCursor, y1: y1, y2: y2 })), _jsx("g", { ref: indicatorRef, className: "pointer-events-none", children: _jsx(Node, { ...nodeIndicatorConfig }) })] }))] }));
148
+ return (_jsxs(_Fragment, { children: [_jsx(Path, { ref: innerRefs, d: dataOnlyLine, dFill: dataFill, dataTestId: `${context.dataTestId}path`, dataValue: context.data, points: points, xKey: context.xKey, onClick: handleClick, ...mergedProps }), lineProjection && (_jsx(LineChartProjection, { curved: curved, dataKey: props.dataKey, lineProjection: lineProjection, points: points, svgHeight: Number(context.canvasHeight) - context.extraSpaceBottomY })), showIndicator && (_jsxs(_Fragment, { children: [!!lineIndicator && isCursorWithinPathArea && (_jsx(Line, { ...lineIndicator, className: "pointer-events-none", x1: context.xCursor, x2: context.xCursor, y1: y1, y2: y2 })), _jsx("g", { ref: indicatorRef, className: "pointer-events-none", children: _jsx(Node, { ...nodeIndicatorConfig }) })] }))] }));
145
149
  };
@@ -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