@react-magma/charts 13.0.2-next.1 → 13.0.2

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.
@@ -2123,6 +2123,148 @@ function transparentize(amount, color) {
2123
2123
  var curriedTransparentize = curry /* ::<number | string, string, string> */(transparentize);
2124
2124
  var curriedTransparentize$1 = curriedTransparentize;
2125
2125
 
2126
+ var FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
2127
+ function getFocusableElements(container) {
2128
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(function (el) {
2129
+ var style = window.getComputedStyle(el);
2130
+ return (style.display !== 'none' &&
2131
+ style.visibility !== 'hidden' &&
2132
+ !el.hasAttribute('disabled'));
2133
+ });
2134
+ }
2135
+ function findVisibleModal(wrapper) {
2136
+ var modal = wrapper.querySelector('.cds--modal');
2137
+ if (!modal)
2138
+ return null;
2139
+ var isVisible = modal.getAttribute('aria-modal') === 'true' ||
2140
+ modal.style.visibility === 'visible' ||
2141
+ modal.classList.contains('is-visible');
2142
+ return isVisible ? modal : null;
2143
+ }
2144
+ function useCarbonModalFocusManagement(wrapperRef) {
2145
+ var previouslyFocusedElement = React.useRef(null);
2146
+ var keydownHandler = React.useRef(null);
2147
+ var focusinHandler = React.useRef(null);
2148
+ var currentModal = React.useRef(null);
2149
+ React.useEffect(function () {
2150
+ var wrapper = wrapperRef.current;
2151
+ if (!wrapper)
2152
+ return;
2153
+ function focusModalCloseButton(modal) {
2154
+ var closeButton = modal.querySelector('.cds--modal-close');
2155
+ if (closeButton) {
2156
+ closeButton.focus();
2157
+ }
2158
+ else {
2159
+ var focusable = getFocusableElements(modal);
2160
+ if (focusable.length > 0) {
2161
+ focusable[0].focus();
2162
+ }
2163
+ }
2164
+ }
2165
+ function handleModalOpen(modal) {
2166
+ currentModal.current = modal;
2167
+ previouslyFocusedElement.current = document.activeElement;
2168
+ // Permanent guard: redirect focus back into modal whenever it escapes
2169
+ // (e.g. Carbon's overflow menu returning focus to its trigger).
2170
+ focusinHandler.current = function (event) {
2171
+ var target = event.target;
2172
+ if (!modal.contains(target)) {
2173
+ setTimeout(function () {
2174
+ if (currentModal.current === modal) {
2175
+ focusModalCloseButton(modal);
2176
+ }
2177
+ }, 0);
2178
+ }
2179
+ };
2180
+ document.addEventListener('focusin', focusinHandler.current);
2181
+ var pollAttempts = 0;
2182
+ var pollAndFocus = function () {
2183
+ if (currentModal.current !== modal)
2184
+ return;
2185
+ if (modal.contains(document.activeElement))
2186
+ return;
2187
+ var closeBtn = modal.querySelector('.cds--modal-close');
2188
+ if (closeBtn &&
2189
+ window.getComputedStyle(closeBtn).visibility !== 'hidden') {
2190
+ closeBtn.focus();
2191
+ return;
2192
+ }
2193
+ if (++pollAttempts < 30) {
2194
+ requestAnimationFrame(pollAndFocus);
2195
+ }
2196
+ };
2197
+ requestAnimationFrame(pollAndFocus);
2198
+ keydownHandler.current = function (event) {
2199
+ if (event.key !== 'Tab')
2200
+ return;
2201
+ var focusable = getFocusableElements(modal);
2202
+ if (focusable.length === 0) {
2203
+ event.preventDefault();
2204
+ return;
2205
+ }
2206
+ if (focusable.length === 1) {
2207
+ event.preventDefault();
2208
+ if (focusable[0] !== document.activeElement) {
2209
+ focusable[0].focus();
2210
+ }
2211
+ return;
2212
+ }
2213
+ var firstItem = focusable[0];
2214
+ var lastItem = focusable[focusable.length - 1];
2215
+ if (!event.shiftKey && document.activeElement === lastItem) {
2216
+ event.preventDefault();
2217
+ firstItem.focus();
2218
+ }
2219
+ else if (event.shiftKey && document.activeElement === firstItem) {
2220
+ event.preventDefault();
2221
+ lastItem.focus();
2222
+ }
2223
+ };
2224
+ document.addEventListener('keydown', keydownHandler.current);
2225
+ }
2226
+ function handleModalClose() {
2227
+ // Null out currentModal first so any pending setTimeout redirects
2228
+ // (scheduled by the focusin guard) see a closed modal and bail out.
2229
+ currentModal.current = null;
2230
+ if (focusinHandler.current) {
2231
+ document.removeEventListener('focusin', focusinHandler.current);
2232
+ focusinHandler.current = null;
2233
+ }
2234
+ if (keydownHandler.current) {
2235
+ document.removeEventListener('keydown', keydownHandler.current);
2236
+ keydownHandler.current = null;
2237
+ }
2238
+ if (previouslyFocusedElement.current instanceof HTMLElement) {
2239
+ previouslyFocusedElement.current.focus();
2240
+ }
2241
+ }
2242
+ var observer = new MutationObserver(function () {
2243
+ var visibleModal = findVisibleModal(wrapper);
2244
+ if (visibleModal && !currentModal.current) {
2245
+ handleModalOpen(visibleModal);
2246
+ }
2247
+ else if (!visibleModal && currentModal.current) {
2248
+ handleModalClose();
2249
+ }
2250
+ });
2251
+ observer.observe(wrapper, {
2252
+ attributes: true,
2253
+ attributeFilter: ['class', 'style', 'aria-modal'],
2254
+ subtree: true,
2255
+ });
2256
+ return function () {
2257
+ observer.disconnect();
2258
+ if (keydownHandler.current) {
2259
+ document.removeEventListener('keydown', keydownHandler.current);
2260
+ }
2261
+ if (focusinHandler.current) {
2262
+ document.removeEventListener('focusin', focusinHandler.current);
2263
+ }
2264
+ };
2265
+ }, [wrapperRef]);
2266
+ }
2267
+
2126
2268
  function styleInject(css, ref) {
2127
2269
  if ( ref === void 0 ) ref = {};
2128
2270
  var insertAt = ref.insertAt;
@@ -2368,6 +2510,17 @@ var CarbonChart = React.forwardRef(function (props, ref) {
2368
2510
  var testId = props.testId, isInverseProp = props.isInverse, type = props.type, dataSet = props.dataSet, options = props.options, ariaLabel = props.ariaLabel, rest = __rest(props, ["testId", "isInverse", "type", "dataSet", "options", "ariaLabel"]);
2369
2511
  var theme = React.useContext(ThemeContext);
2370
2512
  var isInverse = useIsInverse(isInverseProp);
2513
+ var internalRef = React.useRef(null);
2514
+ var mergedRef = React.useCallback(function (node) {
2515
+ internalRef.current = node;
2516
+ if (typeof ref === 'function') {
2517
+ ref(node);
2518
+ }
2519
+ else if (ref) {
2520
+ ref.current = node;
2521
+ }
2522
+ }, [ref]);
2523
+ useCarbonModalFocusManagement(internalRef);
2371
2524
  var allCharts = {
2372
2525
  area: AreaChart,
2373
2526
  areaStacked: StackedAreaChart,
@@ -2422,7 +2575,7 @@ var CarbonChart = React.forwardRef(function (props, ref) {
2422
2575
  }
2423
2576
  });
2424
2577
  var groupsLength = Object.keys(buildColors()).length;
2425
- return (React.createElement(CarbonChartWrapper, __assign({ "data-testid": testId, ref: ref, isInverse: isInverse, theme: theme, className: "carbon-chart-wrapper", groupsLength: groupsLength < 6 ? groupsLength : 14 }, rest),
2578
+ return (React.createElement(CarbonChartWrapper, __assign({ "data-testid": testId, ref: mergedRef, isInverse: isInverse, theme: theme, className: "carbon-chart-wrapper", groupsLength: groupsLength < 6 ? groupsLength : 14 }, rest),
2426
2579
  React.createElement(ChartType, { data: dataSet, options: newOptions })));
2427
2580
  });
2428
2581
  var templateObject_1;