@react-magma/charts 13.0.2-next.0 → 13.0.2-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/charts.js CHANGED
@@ -2144,6 +2144,148 @@ function transparentize(amount, color) {
2144
2144
  var curriedTransparentize = curry /* ::<number | string, string, string> */(transparentize);
2145
2145
  var curriedTransparentize$1 = curriedTransparentize;
2146
2146
 
2147
+ var FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
2148
+ function getFocusableElements(container) {
2149
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(function (el) {
2150
+ var style = window.getComputedStyle(el);
2151
+ return (style.display !== 'none' &&
2152
+ style.visibility !== 'hidden' &&
2153
+ !el.hasAttribute('disabled'));
2154
+ });
2155
+ }
2156
+ function findVisibleModal(wrapper) {
2157
+ var modal = wrapper.querySelector('.cds--modal');
2158
+ if (!modal)
2159
+ return null;
2160
+ var isVisible = modal.getAttribute('aria-modal') === 'true' ||
2161
+ modal.style.visibility === 'visible' ||
2162
+ modal.classList.contains('is-visible');
2163
+ return isVisible ? modal : null;
2164
+ }
2165
+ function useCarbonModalFocusManagement(wrapperRef) {
2166
+ var previouslyFocusedElement = React__namespace.useRef(null);
2167
+ var keydownHandler = React__namespace.useRef(null);
2168
+ var focusinHandler = React__namespace.useRef(null);
2169
+ var currentModal = React__namespace.useRef(null);
2170
+ React__namespace.useEffect(function () {
2171
+ var wrapper = wrapperRef.current;
2172
+ if (!wrapper)
2173
+ return;
2174
+ function focusModalCloseButton(modal) {
2175
+ var closeButton = modal.querySelector('.cds--modal-close');
2176
+ if (closeButton) {
2177
+ closeButton.focus();
2178
+ }
2179
+ else {
2180
+ var focusable = getFocusableElements(modal);
2181
+ if (focusable.length > 0) {
2182
+ focusable[0].focus();
2183
+ }
2184
+ }
2185
+ }
2186
+ function handleModalOpen(modal) {
2187
+ currentModal.current = modal;
2188
+ previouslyFocusedElement.current = document.activeElement;
2189
+ // Permanent guard: redirect focus back into modal whenever it escapes
2190
+ // (e.g. Carbon's overflow menu returning focus to its trigger).
2191
+ focusinHandler.current = function (event) {
2192
+ var target = event.target;
2193
+ if (!modal.contains(target)) {
2194
+ setTimeout(function () {
2195
+ if (currentModal.current === modal) {
2196
+ focusModalCloseButton(modal);
2197
+ }
2198
+ }, 0);
2199
+ }
2200
+ };
2201
+ document.addEventListener('focusin', focusinHandler.current);
2202
+ var pollAttempts = 0;
2203
+ var pollAndFocus = function () {
2204
+ if (currentModal.current !== modal)
2205
+ return;
2206
+ if (modal.contains(document.activeElement))
2207
+ return;
2208
+ var closeBtn = modal.querySelector('.cds--modal-close');
2209
+ if (closeBtn &&
2210
+ window.getComputedStyle(closeBtn).visibility !== 'hidden') {
2211
+ closeBtn.focus();
2212
+ return;
2213
+ }
2214
+ if (++pollAttempts < 30) {
2215
+ requestAnimationFrame(pollAndFocus);
2216
+ }
2217
+ };
2218
+ requestAnimationFrame(pollAndFocus);
2219
+ keydownHandler.current = function (event) {
2220
+ if (event.key !== 'Tab')
2221
+ return;
2222
+ var focusable = getFocusableElements(modal);
2223
+ if (focusable.length === 0) {
2224
+ event.preventDefault();
2225
+ return;
2226
+ }
2227
+ if (focusable.length === 1) {
2228
+ event.preventDefault();
2229
+ if (focusable[0] !== document.activeElement) {
2230
+ focusable[0].focus();
2231
+ }
2232
+ return;
2233
+ }
2234
+ var firstItem = focusable[0];
2235
+ var lastItem = focusable[focusable.length - 1];
2236
+ if (!event.shiftKey && document.activeElement === lastItem) {
2237
+ event.preventDefault();
2238
+ firstItem.focus();
2239
+ }
2240
+ else if (event.shiftKey && document.activeElement === firstItem) {
2241
+ event.preventDefault();
2242
+ lastItem.focus();
2243
+ }
2244
+ };
2245
+ document.addEventListener('keydown', keydownHandler.current);
2246
+ }
2247
+ function handleModalClose() {
2248
+ // Null out currentModal first so any pending setTimeout redirects
2249
+ // (scheduled by the focusin guard) see a closed modal and bail out.
2250
+ currentModal.current = null;
2251
+ if (focusinHandler.current) {
2252
+ document.removeEventListener('focusin', focusinHandler.current);
2253
+ focusinHandler.current = null;
2254
+ }
2255
+ if (keydownHandler.current) {
2256
+ document.removeEventListener('keydown', keydownHandler.current);
2257
+ keydownHandler.current = null;
2258
+ }
2259
+ if (previouslyFocusedElement.current instanceof HTMLElement) {
2260
+ previouslyFocusedElement.current.focus();
2261
+ }
2262
+ }
2263
+ var observer = new MutationObserver(function () {
2264
+ var visibleModal = findVisibleModal(wrapper);
2265
+ if (visibleModal && !currentModal.current) {
2266
+ handleModalOpen(visibleModal);
2267
+ }
2268
+ else if (!visibleModal && currentModal.current) {
2269
+ handleModalClose();
2270
+ }
2271
+ });
2272
+ observer.observe(wrapper, {
2273
+ attributes: true,
2274
+ attributeFilter: ['class', 'style', 'aria-modal'],
2275
+ subtree: true,
2276
+ });
2277
+ return function () {
2278
+ observer.disconnect();
2279
+ if (keydownHandler.current) {
2280
+ document.removeEventListener('keydown', keydownHandler.current);
2281
+ }
2282
+ if (focusinHandler.current) {
2283
+ document.removeEventListener('focusin', focusinHandler.current);
2284
+ }
2285
+ };
2286
+ }, [wrapperRef]);
2287
+ }
2288
+
2147
2289
  function styleInject(css, ref) {
2148
2290
  if ( ref === void 0 ) ref = {};
2149
2291
  var insertAt = ref.insertAt;
@@ -2389,6 +2531,17 @@ var CarbonChart = React__namespace.forwardRef(function (props, ref) {
2389
2531
  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"]);
2390
2532
  var theme = React__namespace.useContext(reactMagmaDom.ThemeContext);
2391
2533
  var isInverse = reactMagmaDom.useIsInverse(isInverseProp);
2534
+ var internalRef = React__namespace.useRef(null);
2535
+ var mergedRef = React__namespace.useCallback(function (node) {
2536
+ internalRef.current = node;
2537
+ if (typeof ref === 'function') {
2538
+ ref(node);
2539
+ }
2540
+ else if (ref) {
2541
+ ref.current = node;
2542
+ }
2543
+ }, [ref]);
2544
+ useCarbonModalFocusManagement(internalRef);
2392
2545
  var allCharts = {
2393
2546
  area: chartsReact.AreaChart,
2394
2547
  areaStacked: chartsReact.StackedAreaChart,
@@ -2443,7 +2596,7 @@ var CarbonChart = React__namespace.forwardRef(function (props, ref) {
2443
2596
  }
2444
2597
  });
2445
2598
  var groupsLength = Object.keys(buildColors()).length;
2446
- return (React__namespace.createElement(CarbonChartWrapper, __assign({ "data-testid": testId, ref: ref, isInverse: isInverse, theme: theme, className: "carbon-chart-wrapper", groupsLength: groupsLength < 6 ? groupsLength : 14 }, rest),
2599
+ return (React__namespace.createElement(CarbonChartWrapper, __assign({ "data-testid": testId, ref: mergedRef, isInverse: isInverse, theme: theme, className: "carbon-chart-wrapper", groupsLength: groupsLength < 6 ? groupsLength : 14 }, rest),
2447
2600
  React__namespace.createElement(ChartType, { data: dataSet, options: newOptions })));
2448
2601
  });
2449
2602
  var templateObject_1;