@khanacademy/wonder-blocks-clickable 6.1.6 → 7.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @khanacademy/wonder-blocks-clickable
2
2
 
3
+ ## 7.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [e8ccf60]
8
+ - @khanacademy/wonder-blocks-tokens@7.0.0
9
+
10
+ ## 7.0.0
11
+
12
+ ### Major Changes
13
+
14
+ - 38c926c: Upgrade WB to using react-router-dom-v5-compat.
15
+
16
+ ### Patch Changes
17
+
18
+ - @khanacademy/wonder-blocks-core@12.2.1
19
+
3
20
  ## 6.1.6
4
21
 
5
22
  ### Patch Changes
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { NavigateFunction } from "react-router-dom-v5-compat";
2
3
  export type ClickableRole = "button" | "checkbox" | "link" | "listbox" | "menu" | "menuitem" | "menuitemcheckbox" | "option" | "radio" | "switch" | "tab";
3
4
  type CommonProps = Readonly<{
4
5
  /**
@@ -55,10 +56,10 @@ type CommonProps = Readonly<{
55
56
  */
56
57
  safeWithNav?: () => Promise<unknown>;
57
58
  /**
58
- * Passed in by withRouter HOC.
59
+ * Passed in by an HOC in get-clickable-behavior.tsx.
59
60
  * @ignore
60
61
  */
61
- history?: any;
62
+ navigate?: NavigateFunction;
62
63
  /**
63
64
  * A role that encapsulates how the clickable component should behave, which
64
65
  * affects which keyboard actions trigger the component. For example, a
@@ -1,5 +1,4 @@
1
1
  import * as React from "react";
2
- import { Link } from "react-router-dom";
3
2
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
4
3
  import type { ClickableRole, ClickableState } from "./clickable-behavior";
5
4
  type CommonProps =
@@ -183,5 +182,5 @@ type Props = (CommonProps & {
183
182
  * </Clickable>
184
183
  * ```
185
184
  */
186
- declare const Clickable: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | typeof Link>>;
185
+ declare const Clickable: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | React.ForwardRefExoticComponent<import("react-router-dom-v5-compat").LinkProps & React.RefAttributes<HTMLAnchorElement>>>>;
187
186
  export default Clickable;
package/dist/es/index.js CHANGED
@@ -2,8 +2,7 @@ import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutP
2
2
  import _extends from '@babel/runtime/helpers/extends';
3
3
  import * as React from 'react';
4
4
  import { StyleSheet } from 'aphrodite';
5
- import { withRouter, Link } from 'react-router-dom';
6
- import { __RouterContext } from 'react-router';
5
+ import { useNavigate, Link, useInRouterContext } from 'react-router-dom-v5-compat';
7
6
  import { keys, addStyle } from '@khanacademy/wonder-blocks-core';
8
7
  import { border, semanticColor } from '@khanacademy/wonder-blocks-tokens';
9
8
 
@@ -198,7 +197,7 @@ class ClickableBehavior extends React.Component {
198
197
  navigateOrReset(shouldNavigate) {
199
198
  if (shouldNavigate) {
200
199
  const {
201
- history,
200
+ navigate,
202
201
  href,
203
202
  skipClientNav,
204
203
  target = undefined
@@ -209,8 +208,8 @@ class ClickableBehavior extends React.Component {
209
208
  this.setState({
210
209
  waiting: false
211
210
  });
212
- } else if (history && !skipClientNav) {
213
- history.push(href);
211
+ } else if (navigate && !skipClientNav) {
212
+ navigate(href);
214
213
  this.setState({
215
214
  waiting: false
216
215
  });
@@ -227,9 +226,9 @@ class ClickableBehavior extends React.Component {
227
226
  handleSafeWithNav(safeWithNav, shouldNavigate) {
228
227
  const {
229
228
  skipClientNav,
230
- history
229
+ navigate
231
230
  } = this.props;
232
- if (history && !skipClientNav || this.props.target === "_blank") {
231
+ if (navigate && !skipClientNav || this.props.target === "_blank") {
233
232
  safeWithNav();
234
233
  this.navigateOrReset(shouldNavigate);
235
234
  return Promise.resolve();
@@ -340,9 +339,19 @@ const isClientSideUrl = href => {
340
339
  return !/^(https?:)?\/\//i.test(href) && !/^([^#]*#[\w-]*|[\w\-.]+:)/.test(href);
341
340
  };
342
341
 
342
+ function withRouter(Component) {
343
+ function WithRouterWrapper(props) {
344
+ const navigate = useNavigate();
345
+ return React.createElement(Component, _extends({}, props, {
346
+ navigate: navigate
347
+ }));
348
+ }
349
+ WithRouterWrapper.displayName = "withRouter(ClickableBehavior)";
350
+ return WithRouterWrapper;
351
+ }
343
352
  const ClickableBehaviorWithRouter = withRouter(ClickableBehavior);
344
- function getClickableBehavior(href, skipClientNav, router) {
345
- if (router && skipClientNav !== true && href && isClientSideUrl(href)) {
353
+ function getClickableBehavior(href, skipClientNav, inRouterContext) {
354
+ if (inRouterContext && skipClientNav !== true && href && isClientSideUrl(href)) {
346
355
  return ClickableBehaviorWithRouter;
347
356
  }
348
357
  return ClickableBehavior;
@@ -353,9 +362,9 @@ const StyledA = addStyle("a");
353
362
  const StyledButton = addStyle("button");
354
363
  const StyledLink = addStyle(Link);
355
364
  const Clickable = React.forwardRef(function Clickable(props, ref) {
356
- const getCorrectTag = (clickableState, router, commonProps) => {
365
+ const getCorrectTag = (clickableState, inRouterContext, commonProps) => {
357
366
  const activeHref = props.href && !props.disabled;
358
- const useClient = router && !props.skipClientNav && isClientSideUrl(props.href || "");
367
+ const useClient = inRouterContext && !props.skipClientNav && isClientSideUrl(props.href || "");
359
368
  if (activeHref && useClient && props.href) {
360
369
  return React.createElement(StyledLink, _extends({}, commonProps, {
361
370
  to: props.href,
@@ -380,66 +389,64 @@ const Clickable = React.forwardRef(function Clickable(props, ref) {
380
389
  }), props.children(clickableState));
381
390
  }
382
391
  };
383
- const renderClickableBehavior = router => {
384
- const {
385
- href,
386
- onClick,
387
- skipClientNav,
388
- beforeNav = undefined,
389
- safeWithNav = undefined,
390
- style,
391
- target = undefined,
392
- testId,
393
- onFocus,
394
- onKeyDown,
395
- onKeyUp,
396
- onMouseDown,
397
- onMouseUp,
398
- hideDefaultFocusRing,
399
- light,
400
- disabled,
401
- tabIndex
402
- } = props,
403
- restProps = _objectWithoutPropertiesLoose(props, _excluded);
404
- const ClickableBehavior = getClickableBehavior(href, skipClientNav, router);
405
- const getStyle = state => [styles.reset, styles.link, !hideDefaultFocusRing && state.focused && (light ? styles.focusedLight : styles.focused), disabled && styles.disabled, style];
406
- if (beforeNav) {
407
- return React.createElement(ClickableBehavior, {
408
- href: href,
409
- onClick: onClick,
410
- beforeNav: beforeNav,
411
- safeWithNav: safeWithNav,
412
- onFocus: onFocus,
413
- onKeyDown: onKeyDown,
414
- onKeyUp: onKeyUp,
415
- onMouseDown: onMouseDown,
416
- onMouseUp: onMouseUp,
417
- disabled: disabled,
418
- tabIndex: tabIndex
419
- }, (state, childrenProps) => getCorrectTag(state, router, _extends({}, restProps, {
420
- "data-testid": testId,
421
- style: getStyle(state)
422
- }, childrenProps)));
423
- } else {
424
- return React.createElement(ClickableBehavior, {
425
- href: href,
426
- onClick: onClick,
427
- safeWithNav: safeWithNav,
428
- onFocus: onFocus,
429
- onKeyDown: onKeyDown,
430
- onKeyUp: onKeyUp,
431
- onMouseDown: onMouseDown,
432
- onMouseUp: onMouseUp,
433
- target: target,
434
- disabled: disabled,
435
- tabIndex: tabIndex
436
- }, (state, childrenProps) => getCorrectTag(state, router, _extends({}, restProps, {
437
- "data-testid": testId,
438
- style: getStyle(state)
439
- }, childrenProps)));
440
- }
441
- };
442
- return React.createElement(__RouterContext.Consumer, null, router => renderClickableBehavior(router));
392
+ const inRouterContext = useInRouterContext();
393
+ const {
394
+ href,
395
+ onClick,
396
+ skipClientNav,
397
+ beforeNav = undefined,
398
+ safeWithNav = undefined,
399
+ style,
400
+ target = undefined,
401
+ testId,
402
+ onFocus,
403
+ onKeyDown,
404
+ onKeyUp,
405
+ onMouseDown,
406
+ onMouseUp,
407
+ hideDefaultFocusRing,
408
+ light,
409
+ disabled,
410
+ tabIndex
411
+ } = props,
412
+ restProps = _objectWithoutPropertiesLoose(props, _excluded);
413
+ const ClickableBehavior = getClickableBehavior(href, skipClientNav, inRouterContext);
414
+ const getStyle = state => [styles.reset, styles.link, !hideDefaultFocusRing && state.focused && (light ? styles.focusedLight : styles.focused), disabled && styles.disabled, style];
415
+ if (beforeNav) {
416
+ return React.createElement(ClickableBehavior, {
417
+ href: href,
418
+ onClick: onClick,
419
+ beforeNav: beforeNav,
420
+ safeWithNav: safeWithNav,
421
+ onFocus: onFocus,
422
+ onKeyDown: onKeyDown,
423
+ onKeyUp: onKeyUp,
424
+ onMouseDown: onMouseDown,
425
+ onMouseUp: onMouseUp,
426
+ disabled: disabled,
427
+ tabIndex: tabIndex
428
+ }, (state, childrenProps) => getCorrectTag(state, inRouterContext, _extends({}, restProps, {
429
+ "data-testid": testId,
430
+ style: getStyle(state)
431
+ }, childrenProps)));
432
+ } else {
433
+ return React.createElement(ClickableBehavior, {
434
+ href: href,
435
+ onClick: onClick,
436
+ safeWithNav: safeWithNav,
437
+ onFocus: onFocus,
438
+ onKeyDown: onKeyDown,
439
+ onKeyUp: onKeyUp,
440
+ onMouseDown: onMouseDown,
441
+ onMouseUp: onMouseUp,
442
+ target: target,
443
+ disabled: disabled,
444
+ tabIndex: tabIndex
445
+ }, (state, childrenProps) => getCorrectTag(state, inRouterContext, _extends({}, restProps, {
446
+ "data-testid": testId,
447
+ style: getStyle(state)
448
+ }, childrenProps)));
449
+ }
443
450
  });
444
451
  Clickable.defaultProps = {
445
452
  light: false,
package/dist/index.js CHANGED
@@ -6,8 +6,7 @@ var _objectWithoutPropertiesLoose = require('@babel/runtime/helpers/objectWithou
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var aphrodite = require('aphrodite');
9
- var reactRouterDom = require('react-router-dom');
10
- var reactRouter = require('react-router');
9
+ var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
11
10
  var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
12
11
  var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
13
12
 
@@ -226,7 +225,7 @@ class ClickableBehavior extends React__namespace.Component {
226
225
  navigateOrReset(shouldNavigate) {
227
226
  if (shouldNavigate) {
228
227
  const {
229
- history,
228
+ navigate,
230
229
  href,
231
230
  skipClientNav,
232
231
  target = undefined
@@ -237,8 +236,8 @@ class ClickableBehavior extends React__namespace.Component {
237
236
  this.setState({
238
237
  waiting: false
239
238
  });
240
- } else if (history && !skipClientNav) {
241
- history.push(href);
239
+ } else if (navigate && !skipClientNav) {
240
+ navigate(href);
242
241
  this.setState({
243
242
  waiting: false
244
243
  });
@@ -255,9 +254,9 @@ class ClickableBehavior extends React__namespace.Component {
255
254
  handleSafeWithNav(safeWithNav, shouldNavigate) {
256
255
  const {
257
256
  skipClientNav,
258
- history
257
+ navigate
259
258
  } = this.props;
260
- if (history && !skipClientNav || this.props.target === "_blank") {
259
+ if (navigate && !skipClientNav || this.props.target === "_blank") {
261
260
  safeWithNav();
262
261
  this.navigateOrReset(shouldNavigate);
263
262
  return Promise.resolve();
@@ -368,9 +367,19 @@ const isClientSideUrl = href => {
368
367
  return !/^(https?:)?\/\//i.test(href) && !/^([^#]*#[\w-]*|[\w\-.]+:)/.test(href);
369
368
  };
370
369
 
371
- const ClickableBehaviorWithRouter = reactRouterDom.withRouter(ClickableBehavior);
372
- function getClickableBehavior(href, skipClientNav, router) {
373
- if (router && skipClientNav !== true && href && isClientSideUrl(href)) {
370
+ function withRouter(Component) {
371
+ function WithRouterWrapper(props) {
372
+ const navigate = reactRouterDomV5Compat.useNavigate();
373
+ return React__namespace.createElement(Component, _extends__default["default"]({}, props, {
374
+ navigate: navigate
375
+ }));
376
+ }
377
+ WithRouterWrapper.displayName = "withRouter(ClickableBehavior)";
378
+ return WithRouterWrapper;
379
+ }
380
+ const ClickableBehaviorWithRouter = withRouter(ClickableBehavior);
381
+ function getClickableBehavior(href, skipClientNav, inRouterContext) {
382
+ if (inRouterContext && skipClientNav !== true && href && isClientSideUrl(href)) {
374
383
  return ClickableBehaviorWithRouter;
375
384
  }
376
385
  return ClickableBehavior;
@@ -379,11 +388,11 @@ function getClickableBehavior(href, skipClientNav, router) {
379
388
  const _excluded = ["href", "onClick", "skipClientNav", "beforeNav", "safeWithNav", "style", "target", "testId", "onFocus", "onKeyDown", "onKeyUp", "onMouseDown", "onMouseUp", "hideDefaultFocusRing", "light", "disabled", "tabIndex"];
380
389
  const StyledA = wonderBlocksCore.addStyle("a");
381
390
  const StyledButton = wonderBlocksCore.addStyle("button");
382
- const StyledLink = wonderBlocksCore.addStyle(reactRouterDom.Link);
391
+ const StyledLink = wonderBlocksCore.addStyle(reactRouterDomV5Compat.Link);
383
392
  const Clickable = React__namespace.forwardRef(function Clickable(props, ref) {
384
- const getCorrectTag = (clickableState, router, commonProps) => {
393
+ const getCorrectTag = (clickableState, inRouterContext, commonProps) => {
385
394
  const activeHref = props.href && !props.disabled;
386
- const useClient = router && !props.skipClientNav && isClientSideUrl(props.href || "");
395
+ const useClient = inRouterContext && !props.skipClientNav && isClientSideUrl(props.href || "");
387
396
  if (activeHref && useClient && props.href) {
388
397
  return React__namespace.createElement(StyledLink, _extends__default["default"]({}, commonProps, {
389
398
  to: props.href,
@@ -408,66 +417,64 @@ const Clickable = React__namespace.forwardRef(function Clickable(props, ref) {
408
417
  }), props.children(clickableState));
409
418
  }
410
419
  };
411
- const renderClickableBehavior = router => {
412
- const {
413
- href,
414
- onClick,
415
- skipClientNav,
416
- beforeNav = undefined,
417
- safeWithNav = undefined,
418
- style,
419
- target = undefined,
420
- testId,
421
- onFocus,
422
- onKeyDown,
423
- onKeyUp,
424
- onMouseDown,
425
- onMouseUp,
426
- hideDefaultFocusRing,
427
- light,
428
- disabled,
429
- tabIndex
430
- } = props,
431
- restProps = _objectWithoutPropertiesLoose__default["default"](props, _excluded);
432
- const ClickableBehavior = getClickableBehavior(href, skipClientNav, router);
433
- const getStyle = state => [styles.reset, styles.link, !hideDefaultFocusRing && state.focused && (light ? styles.focusedLight : styles.focused), disabled && styles.disabled, style];
434
- if (beforeNav) {
435
- return React__namespace.createElement(ClickableBehavior, {
436
- href: href,
437
- onClick: onClick,
438
- beforeNav: beforeNav,
439
- safeWithNav: safeWithNav,
440
- onFocus: onFocus,
441
- onKeyDown: onKeyDown,
442
- onKeyUp: onKeyUp,
443
- onMouseDown: onMouseDown,
444
- onMouseUp: onMouseUp,
445
- disabled: disabled,
446
- tabIndex: tabIndex
447
- }, (state, childrenProps) => getCorrectTag(state, router, _extends__default["default"]({}, restProps, {
448
- "data-testid": testId,
449
- style: getStyle(state)
450
- }, childrenProps)));
451
- } else {
452
- return React__namespace.createElement(ClickableBehavior, {
453
- href: href,
454
- onClick: onClick,
455
- safeWithNav: safeWithNav,
456
- onFocus: onFocus,
457
- onKeyDown: onKeyDown,
458
- onKeyUp: onKeyUp,
459
- onMouseDown: onMouseDown,
460
- onMouseUp: onMouseUp,
461
- target: target,
462
- disabled: disabled,
463
- tabIndex: tabIndex
464
- }, (state, childrenProps) => getCorrectTag(state, router, _extends__default["default"]({}, restProps, {
465
- "data-testid": testId,
466
- style: getStyle(state)
467
- }, childrenProps)));
468
- }
469
- };
470
- return React__namespace.createElement(reactRouter.__RouterContext.Consumer, null, router => renderClickableBehavior(router));
420
+ const inRouterContext = reactRouterDomV5Compat.useInRouterContext();
421
+ const {
422
+ href,
423
+ onClick,
424
+ skipClientNav,
425
+ beforeNav = undefined,
426
+ safeWithNav = undefined,
427
+ style,
428
+ target = undefined,
429
+ testId,
430
+ onFocus,
431
+ onKeyDown,
432
+ onKeyUp,
433
+ onMouseDown,
434
+ onMouseUp,
435
+ hideDefaultFocusRing,
436
+ light,
437
+ disabled,
438
+ tabIndex
439
+ } = props,
440
+ restProps = _objectWithoutPropertiesLoose__default["default"](props, _excluded);
441
+ const ClickableBehavior = getClickableBehavior(href, skipClientNav, inRouterContext);
442
+ const getStyle = state => [styles.reset, styles.link, !hideDefaultFocusRing && state.focused && (light ? styles.focusedLight : styles.focused), disabled && styles.disabled, style];
443
+ if (beforeNav) {
444
+ return React__namespace.createElement(ClickableBehavior, {
445
+ href: href,
446
+ onClick: onClick,
447
+ beforeNav: beforeNav,
448
+ safeWithNav: safeWithNav,
449
+ onFocus: onFocus,
450
+ onKeyDown: onKeyDown,
451
+ onKeyUp: onKeyUp,
452
+ onMouseDown: onMouseDown,
453
+ onMouseUp: onMouseUp,
454
+ disabled: disabled,
455
+ tabIndex: tabIndex
456
+ }, (state, childrenProps) => getCorrectTag(state, inRouterContext, _extends__default["default"]({}, restProps, {
457
+ "data-testid": testId,
458
+ style: getStyle(state)
459
+ }, childrenProps)));
460
+ } else {
461
+ return React__namespace.createElement(ClickableBehavior, {
462
+ href: href,
463
+ onClick: onClick,
464
+ safeWithNav: safeWithNav,
465
+ onFocus: onFocus,
466
+ onKeyDown: onKeyDown,
467
+ onKeyUp: onKeyUp,
468
+ onMouseDown: onMouseDown,
469
+ onMouseUp: onMouseUp,
470
+ target: target,
471
+ disabled: disabled,
472
+ tabIndex: tabIndex
473
+ }, (state, childrenProps) => getCorrectTag(state, inRouterContext, _extends__default["default"]({}, restProps, {
474
+ "data-testid": testId,
475
+ style: getStyle(state)
476
+ }, childrenProps)));
477
+ }
471
478
  });
472
479
  Clickable.defaultProps = {
473
480
  light: false,
@@ -1,15 +1,3 @@
1
- /**
2
- * Returns either the default ClickableBehavior or a react-router aware version.
3
- *
4
- * The react-router aware version is returned if `router` is a react-router-dom
5
- * router, `skipClientNav` is not `true`, and `href` is an internal URL.
6
- *
7
- * The `router` can be accessed via __RouterContext (imported from 'react-router')
8
- * from a component rendered as a descendant of a BrowserRouter.
9
- * See https://reacttraining.com/react-router/web/guides/basic-components.
10
- */
11
- import * as React from "react";
12
- import { PropsFor } from "@khanacademy/wonder-blocks-core";
13
1
  import ClickableBehavior from "../components/clickable-behavior";
14
2
  export default function getClickableBehavior(
15
3
  /**
@@ -21,6 +9,6 @@ href?: string,
21
9
  */
22
10
  skipClientNav?: boolean,
23
11
  /**
24
- * router object added to the React context object by react-router-dom.
12
+ * Whether we're in a react-router context.
25
13
  */
26
- router?: any): React.ComponentType<PropsFor<typeof ClickableBehavior>>;
14
+ inRouterContext?: boolean): typeof ClickableBehavior;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-clickable",
3
- "version": "6.1.6",
3
+ "version": "7.0.1",
4
4
  "design": "v1",
5
5
  "description": "Clickable component for Wonder-Blocks.",
6
6
  "main": "dist/index.js",
@@ -14,14 +14,15 @@
14
14
  "dependencies": {
15
15
  "@babel/runtime": "^7.24.5",
16
16
  "@khanacademy/wonder-blocks-core": "12.2.1",
17
- "@khanacademy/wonder-blocks-tokens": "6.0.0"
17
+ "@khanacademy/wonder-blocks-tokens": "7.0.0"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "aphrodite": "^1.2.5",
21
21
  "react": "18.2.0",
22
22
  "react-dom": "18.2.0",
23
23
  "react-router": "5.3.4",
24
- "react-router-dom": "5.3.4"
24
+ "react-router-dom": "5.3.4",
25
+ "react-router-dom-v5-compat": "^6.30.0"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@khanacademy/wb-dev-build-settings": "2.1.1"