@khanacademy/perseus 29.0.0 → 30.0.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.
@@ -14,6 +14,9 @@ type Props = {
14
14
  blockHighlight?: boolean;
15
15
  severity?: Severity;
16
16
  };
17
+ type State = {
18
+ tooltipAbove: boolean;
19
+ };
17
20
  /**
18
21
  * This component renders "lint" nodes in a markdown parse tree. Lint nodes
19
22
  * are inserted into the tree by the Perseus linter (see
@@ -36,8 +39,12 @@ type Props = {
36
39
  * that has a right margin (like anything blockquoted) the circle will appear
37
40
  * to the left of where it belongs. And if there is more
38
41
  **/
39
- declare class Lint extends React.Component<Props> {
42
+ declare class Lint extends React.Component<Props, State> {
40
43
  _positionTimeout: number | undefined;
44
+ state: State;
45
+ componentDidMount(): void;
46
+ componentWillUnmount(): void;
47
+ getPosition: () => void;
41
48
  renderLink: (arg1: any) => React.ReactElement;
42
49
  render(): React.ReactNode;
43
50
  }
package/dist/es/index.js CHANGED
@@ -15,7 +15,7 @@ import ReactDOM__default from 'react-dom';
15
15
  import _, { debounce as debounce$1 } from 'underscore';
16
16
  import Clickable from '@khanacademy/wonder-blocks-clickable';
17
17
  import { Popover, PopoverContentCore, PopoverContent } from '@khanacademy/wonder-blocks-popover';
18
- import { color, spacing, font } from '@khanacademy/wonder-blocks-tokens';
18
+ import { color, spacing } from '@khanacademy/wonder-blocks-tokens';
19
19
  import $ from 'jquery';
20
20
  import { v4 } from 'uuid';
21
21
  import PropTypes from 'prop-types';
@@ -18171,9 +18171,27 @@ class Lint extends React.Component {
18171
18171
  constructor(...args) {
18172
18172
  super(...args);
18173
18173
  this._positionTimeout = void 0;
18174
+ this.state = {
18175
+ tooltipAbove: true
18176
+ };
18177
+ // We can't call setState in componentDidMount without risking a render
18178
+ // thrash, and we can't call getBoundingClientRect in render, so we
18179
+ // borrow a timeout approach from learnstorm-dashboard.jsx and set our
18180
+ // state once the component has mounted and we can get what we need.
18181
+ this.getPosition = () => {
18182
+ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'getBoundingClientRect' does not exist on type 'Element | Text'.
18183
+ const rect = ReactDOM__default.findDOMNode(this).getBoundingClientRect();
18184
+ // TODO(scottgrant): This is a magic number! We don't know the size
18185
+ // of the tooltip at this point, so we're arbitrarily choosing a
18186
+ // point at which to flip the tooltip's position.
18187
+ this.setState({
18188
+ tooltipAbove: rect.top > 100
18189
+ });
18190
+ };
18174
18191
  // Render the <a> element that holds the indicator icon and the tooltip
18175
18192
  // We pass different styles for the inline and block cases
18176
18193
  this.renderLink = style => {
18194
+ const tooltipAbove = this.state.tooltipAbove;
18177
18195
  let severityStyle;
18178
18196
  let warningText;
18179
18197
  let warningTextStyle;
@@ -18190,23 +18208,34 @@ class Lint extends React.Component {
18190
18208
  warningText = "Recommendation";
18191
18209
  warningTextStyle = styles$B.warning;
18192
18210
  }
18193
- return /*#__PURE__*/React.createElement(Tooltip$1, {
18194
- backgroundColor: "offBlack",
18195
- content: /*#__PURE__*/React.createElement(React.Fragment, null, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
18196
- key: i,
18197
- className: css(styles$B.tooltipParagraph)
18198
- }, /*#__PURE__*/React.createElement("span", {
18199
- className: css(warningTextStyle)
18200
- }, warningText, ":", " "), m)))
18201
- }, /*#__PURE__*/React.createElement("a", {
18211
+ return /*#__PURE__*/React.createElement("a", {
18202
18212
  href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
18203
18213
  target: "lint-help-window",
18204
18214
  className: css(style)
18205
18215
  }, /*#__PURE__*/React.createElement("span", {
18206
18216
  className: css(styles$B.indicator, severityStyle)
18207
- }, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon))));
18217
+ }, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
18218
+ className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
18219
+ }, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
18220
+ key: i,
18221
+ className: css(styles$B.tooltipParagraph)
18222
+ }, /*#__PURE__*/React.createElement("span", {
18223
+ className: css(warningTextStyle)
18224
+ }, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
18225
+ className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
18226
+ })));
18208
18227
  };
18209
18228
  }
18229
+ componentDidMount() {
18230
+ // TODO(somewhatabstract): Use WB timing
18231
+ // eslint-disable-next-line no-restricted-syntax
18232
+ this._positionTimeout = window.setTimeout(this.getPosition);
18233
+ }
18234
+ componentWillUnmount() {
18235
+ // TODO(somewhatabstract): Use WB timing
18236
+ // eslint-disable-next-line no-restricted-syntax
18237
+ window.clearTimeout(this._positionTimeout);
18238
+ }
18210
18239
  // The main render method surrounds linty content with a block or
18211
18240
  // inline container and the link element that displays the indicator
18212
18241
  // and holds the tooltip.
@@ -18407,11 +18436,54 @@ const styles$B = StyleSheet.create({
18407
18436
  indicatorGuideline: {
18408
18437
  backgroundColor: "#ffbe26"
18409
18438
  },
18439
+ // These are the styles for the tooltip
18440
+ tooltip: {
18441
+ // Absolute positioning relative to the lint indicator circle.
18442
+ position: "absolute",
18443
+ right: -12,
18444
+ // The tooltip is hidden by default; only displayed on hover
18445
+ display: "none",
18446
+ // When it is displayed, it goes on top!
18447
+ zIndex: 1000,
18448
+ // These styles control what the tooltip looks like
18449
+ color: white$1,
18450
+ backgroundColor: gray17,
18451
+ opacity: 0.9,
18452
+ fontFamily: baseFontFamily$1,
18453
+ fontSize: "12px",
18454
+ lineHeight: "15px",
18455
+ width: "320px",
18456
+ borderRadius: "4px"
18457
+ },
18458
+ // If we're going to render the tooltip above the warning circle, we use
18459
+ // the previous rules in tooltip, but change the position slightly.
18460
+ tooltipAbove: {
18461
+ bottom: 32
18462
+ },
18463
+ // We give the tooltip a little triangular "tail" that points down at
18464
+ // the lint indicator circle. This is inside the tooltip and positioned
18465
+ // relative to it. It also shares the opacity of the tooltip. We're using
18466
+ // the standard CSS trick for drawing triangles with a thick border.
18467
+ tail: {
18468
+ position: "absolute",
18469
+ top: -12,
18470
+ right: 16,
18471
+ width: 0,
18472
+ height: 0,
18473
+ // This is the CSS triangle trick
18474
+ borderLeft: "8px solid transparent",
18475
+ borderRight: "8px solid transparent",
18476
+ borderBottom: "12px solid " + gray17
18477
+ },
18478
+ tailAbove: {
18479
+ bottom: -12,
18480
+ borderBottom: "none",
18481
+ borderTop: "12px solid " + gray17,
18482
+ top: "auto"
18483
+ },
18410
18484
  // Each warning in the tooltip is its own <p>. They are 12 pixels from
18411
18485
  // the edges of the tooltip and 12 pixels from each other.
18412
18486
  tooltipParagraph: {
18413
- fontFamily: font.family.sans,
18414
- color: color.white,
18415
18487
  margin: 12
18416
18488
  },
18417
18489
  // The text "Warning" inside the tooltip is highlighted like this
@@ -44201,7 +44273,7 @@ const init = function init(options) {
44201
44273
 
44202
44274
  // This file is processed by a Rollup plugin (replace) to inject the production
44203
44275
  const libName = "@khanacademy/perseus";
44204
- const libVersion = "29.0.0";
44276
+ const libVersion = "30.0.0";
44205
44277
  addLibraryVersionToPerseusDebug(libName, libVersion);
44206
44278
 
44207
44279
  const apiVersion = {