@datarobot/design-system 30.4.0 → 30.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 (41) hide show
  1. package/cjs/expandable-content/expandable-content.d.ts +16 -0
  2. package/cjs/expandable-content/expandable-content.js +61 -0
  3. package/cjs/expandable-content/index.d.ts +3 -0
  4. package/cjs/expandable-content/index.js +12 -0
  5. package/cjs/form-field/constants.d.ts +2 -0
  6. package/cjs/form-field/constants.js +2 -1
  7. package/cjs/index.d.ts +1 -0
  8. package/cjs/index.js +11 -0
  9. package/cjs/markdown/markdown.d.ts +6 -0
  10. package/cjs/markdown/markdown.js +15 -2
  11. package/cjs/message/message.d.ts +2 -1
  12. package/cjs/message/message.js +25 -9
  13. package/cjs/message/thinking-icon.d.ts +12 -0
  14. package/cjs/message/thinking-icon.js +79 -0
  15. package/cjs/text-editor/text-editor-content.js +0 -2
  16. package/esm/expandable-content/expandable-content.d.ts +16 -0
  17. package/esm/expandable-content/expandable-content.js +53 -0
  18. package/esm/expandable-content/index.d.ts +3 -0
  19. package/esm/expandable-content/index.js +2 -0
  20. package/esm/form-field/constants.d.ts +2 -0
  21. package/esm/form-field/constants.js +2 -1
  22. package/esm/index.d.ts +1 -0
  23. package/esm/index.js +1 -0
  24. package/esm/markdown/markdown.d.ts +6 -0
  25. package/esm/markdown/markdown.js +15 -2
  26. package/esm/message/message.d.ts +2 -1
  27. package/esm/message/message.js +25 -9
  28. package/esm/message/thinking-icon.d.ts +12 -0
  29. package/esm/message/thinking-icon.js +71 -0
  30. package/esm/text-editor/text-editor-content.js +0 -2
  31. package/expandable-content/package.json +7 -0
  32. package/js/bundle/bundle.js +630 -380
  33. package/js/bundle/bundle.min.js +1 -1
  34. package/js/bundle/index.d.ts +31 -3
  35. package/package.json +1 -1
  36. package/styles/index.css +62 -1
  37. package/styles/index.min.css +1 -1
  38. package/styles/themes/alpine-light.css +1 -0
  39. package/styles/themes/alpine-light.min.css +1 -1
  40. package/styles/themes/midnight-gray.css +1 -0
  41. package/styles/themes/midnight-gray.min.css +1 -1
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import './expandable-content.less';
3
+ export type ExpandableContentProps = {
4
+ /** Content to render */
5
+ children: React.ReactNode;
6
+ /** Maximum height in pixels. When content exceeds this height it is clipped and a Show more/Show less button appears */
7
+ maxHeight: number;
8
+ /** Additional CSS class applied to the wrapper */
9
+ className?: string;
10
+ };
11
+ /** Clips content to a maximum height and shows a Show more/Show less ghost button when the content overflows.
12
+ * @midnight-gray-supported
13
+ * @alpine-light-supported
14
+ */
15
+ declare const ExpandableContent: React.FC<ExpandableContentProps>;
16
+ export { ExpandableContent };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ExpandableContent = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _classnames = _interopRequireDefault(require("classnames"));
9
+ var _faChevronDown = require("@fortawesome/free-solid-svg-icons/faChevronDown");
10
+ var _faChevronUp = require("@fortawesome/free-solid-svg-icons/faChevronUp");
11
+ var _button = require("../button");
12
+ var _useTranslation = require("../hooks/use-translation");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ /** Clips content to a maximum height and shows a Show more/Show less ghost button when the content overflows.
17
+ * @midnight-gray-supported
18
+ * @alpine-light-supported
19
+ */
20
+ const ExpandableContent = ({
21
+ children,
22
+ maxHeight,
23
+ className
24
+ }) => {
25
+ const [isExpanded, setIsExpanded] = (0, _react.useState)(false);
26
+ const [isOverflowing, setIsOverflowing] = (0, _react.useState)(false);
27
+ const contentRef = (0, _react.useRef)(null);
28
+ const {
29
+ t
30
+ } = (0, _useTranslation.useTranslation)();
31
+ (0, _react.useLayoutEffect)(() => {
32
+ if (contentRef.current) {
33
+ setIsOverflowing(contentRef.current.scrollHeight > maxHeight);
34
+ }
35
+ }, [children, maxHeight]);
36
+ const isClipped = isOverflowing && !isExpanded;
37
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
38
+ className: (0, _classnames.default)('expandable-content', className),
39
+ "test-id": "expandable-content",
40
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
41
+ ref: contentRef,
42
+ className: "expandable-content-body"
43
+ // eslint-disable-next-line react/forbid-dom-props
44
+ ,
45
+ style: isClipped ? {
46
+ maxHeight,
47
+ overflow: 'hidden'
48
+ } : undefined,
49
+ "test-id": "expandable-content-body",
50
+ children: children
51
+ }), isOverflowing && /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
52
+ accentType: _button.ACCENT_TYPES.GHOST,
53
+ onClick: () => setIsExpanded(prev => !prev),
54
+ className: "expandable-content-toggle",
55
+ rightIcon: isExpanded ? _faChevronUp.faChevronUp : _faChevronDown.faChevronDown,
56
+ testId: "expandable-content-toggle",
57
+ children: isExpanded ? t('Show less') : t('Show more')
58
+ })]
59
+ });
60
+ };
61
+ exports.ExpandableContent = ExpandableContent;
@@ -0,0 +1,3 @@
1
+ import { ExpandableContent, ExpandableContentProps } from './expandable-content';
2
+ export type { ExpandableContentProps };
3
+ export { ExpandableContent };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "ExpandableContent", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _expandableContent.ExpandableContent;
10
+ }
11
+ });
12
+ var _expandableContent = require("./expandable-content");
@@ -8,6 +8,7 @@ export declare const VALIDATION_RULE_TYPES: {
8
8
  readonly IN_PROGRESS: "in-progress";
9
9
  readonly EXPIRED: "expired";
10
10
  readonly DISABLED: "disabled";
11
+ readonly THINKING: "thinking";
11
12
  };
12
13
  export type ValidationRuleTypes = ValueOf<typeof VALIDATION_RULE_TYPES>;
13
14
  export declare const MESSAGE_DISPLAY_LOCATION: {
@@ -30,6 +31,7 @@ export type VALIDATION_VALUES = {
30
31
  [VALIDATION_RULE_TYPES.IN_PROGRESS]?: string;
31
32
  [VALIDATION_RULE_TYPES.EXPIRED]?: string;
32
33
  [VALIDATION_RULE_TYPES.DISABLED]?: string;
34
+ [VALIDATION_RULE_TYPES.THINKING]?: string;
33
35
  };
34
36
  export declare const useDefaultValidationValues: () => VALIDATION_VALUES;
35
37
  export declare const INPUT_TYPES: {
@@ -15,7 +15,8 @@ const VALIDATION_RULE_TYPES = exports.VALIDATION_RULE_TYPES = {
15
15
  SUCCESS_INFO: 'success-info',
16
16
  IN_PROGRESS: 'in-progress',
17
17
  EXPIRED: 'expired',
18
- DISABLED: 'disabled'
18
+ DISABLED: 'disabled',
19
+ THINKING: 'thinking'
19
20
  };
20
21
  const MESSAGE_DISPLAY_LOCATION = exports.MESSAGE_DISPLAY_LOCATION = {
21
22
  INLINE: 'inline',
package/cjs/index.d.ts CHANGED
@@ -33,6 +33,7 @@ export * from './editable-text';
33
33
  export * from './embedded-steps';
34
34
  export * from './empty-state';
35
35
  export * from './error-boundary';
36
+ export * from './expandable-content';
36
37
  export * from './export-button';
37
38
  export * from './file-tree';
38
39
  export * from './file-upload';
package/cjs/index.js CHANGED
@@ -388,6 +388,17 @@ Object.keys(_errorBoundary).forEach(function (key) {
388
388
  }
389
389
  });
390
390
  });
391
+ var _expandableContent = require("./expandable-content");
392
+ Object.keys(_expandableContent).forEach(function (key) {
393
+ if (key === "default" || key === "__esModule") return;
394
+ if (key in exports && exports[key] === _expandableContent[key]) return;
395
+ Object.defineProperty(exports, key, {
396
+ enumerable: true,
397
+ get: function () {
398
+ return _expandableContent[key];
399
+ }
400
+ });
401
+ });
391
402
  var _exportButton = require("./export-button");
392
403
  Object.keys(_exportButton).forEach(function (key) {
393
404
  if (key === "default" || key === "__esModule") return;
@@ -3,6 +3,12 @@ import './markdown.less';
3
3
  type Props = {
4
4
  className?: string;
5
5
  children?: React.ReactNode;
6
+ /** If set, content will be clipped to this height and a Show more/Show less button will appear */
7
+ maxHeight?: number;
6
8
  };
9
+ /** Renders markdown content as HTML with support for GFM, math, and syntax highlighting.
10
+ * @midnight-gray-supported
11
+ * @alpine-light-supported
12
+ */
7
13
  declare const Markdown: React.FC<Props>;
8
14
  export { Markdown };
@@ -7,14 +7,20 @@ exports.Markdown = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _classnames = _interopRequireDefault(require("classnames"));
9
9
  var _message = require("../message");
10
+ var _expandableContent = require("../expandable-content");
10
11
  var _markdownUtils = require("./markdown-utils");
11
12
  var _useTranslation = require("../hooks/use-translation");
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ /** Renders markdown content as HTML with support for GFM, math, and syntax highlighting.
17
+ * @midnight-gray-supported
18
+ * @alpine-light-supported
19
+ */
15
20
  const Markdown = ({
16
21
  children,
17
- className
22
+ className,
23
+ maxHeight
18
24
  }) => {
19
25
  const [html, setHtml] = (0, _react.useState)('');
20
26
  const [error, setError] = (0, _react.useState)('');
@@ -74,11 +80,18 @@ const Markdown = ({
74
80
  if (!html) {
75
81
  return null;
76
82
  }
77
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
83
+ const content = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
78
84
  className: (0, _classnames.default)('markdown', className),
79
85
  dangerouslySetInnerHTML: {
80
86
  __html: String(html)
81
87
  }
82
88
  });
89
+ if (maxHeight !== undefined) {
90
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_expandableContent.ExpandableContent, {
91
+ maxHeight: maxHeight,
92
+ children: content
93
+ });
94
+ }
95
+ return content;
83
96
  };
84
97
  exports.Markdown = Markdown;
@@ -11,6 +11,7 @@ export declare const MESSAGE_TYPES: {
11
11
  readonly SUCCESS_INFO: "success-info";
12
12
  readonly IN_PROGRESS: "in-progress";
13
13
  readonly EXPIRED: "expired";
14
+ readonly THINKING: "thinking";
14
15
  };
15
16
  export declare const MESSAGE_ICON_PLACEMENT: {
16
17
  readonly LEFT: "left";
@@ -37,7 +38,7 @@ type Icons = {
37
38
  [key: string]: IconLookup;
38
39
  };
39
40
  export type MessageProps = {
40
- children: ReactNode;
41
+ children?: ReactNode;
41
42
  className?: string;
42
43
  testId?: string;
43
44
  /** Identifies the type of the message */
@@ -14,6 +14,7 @@ var _faCircleXmark = require("@fortawesome/free-solid-svg-icons/faCircleXmark");
14
14
  var _faCircleCheck = require("@fortawesome/free-solid-svg-icons/faCircleCheck");
15
15
  var _faCircleNotch = require("@fortawesome/free-solid-svg-icons/faCircleNotch");
16
16
  var _fontAwesomeIcon = require("../font-awesome-icon");
17
+ var _thinkingIcon = require("./thinking-icon");
17
18
  var _jsxRuntime = require("react/jsx-runtime");
18
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
20
  const MESSAGE_TYPES = exports.MESSAGE_TYPES = {
@@ -24,7 +25,8 @@ const MESSAGE_TYPES = exports.MESSAGE_TYPES = {
24
25
  SUCCESS: 'success',
25
26
  SUCCESS_INFO: 'success-info',
26
27
  IN_PROGRESS: 'in-progress',
27
- EXPIRED: 'expired'
28
+ EXPIRED: 'expired',
29
+ THINKING: 'thinking'
28
30
  };
29
31
  const MESSAGE_ICON_PLACEMENT = exports.MESSAGE_ICON_PLACEMENT = {
30
32
  LEFT: 'left',
@@ -88,6 +90,10 @@ function getMessageConfig(icons, type) {
88
90
  icon,
89
91
  className: 'expired'
90
92
  };
93
+ case MESSAGE_TYPES.THINKING:
94
+ return {
95
+ className: 'thinking'
96
+ };
91
97
  default:
92
98
  return {
93
99
  icon,
@@ -113,23 +119,33 @@ function Message({
113
119
  icons = MESSAGE_ICONS
114
120
  }) {
115
121
  const messageConfig = getMessageConfig(icons, type);
116
- const icon = /*#__PURE__*/(0, _jsxRuntime.jsx)(_fontAwesomeIcon.FontAwesomeIcon, {
117
- icon: messageConfig.icon,
118
- spin: type === MESSAGE_TYPES.IN_PROGRESS
119
- });
122
+ const renderIcon = () => {
123
+ if (type === MESSAGE_TYPES.THINKING) {
124
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_thinkingIcon.ThinkingIcon, {
125
+ size: size
126
+ });
127
+ }
128
+ if (messageConfig.icon) {
129
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_fontAwesomeIcon.FontAwesomeIcon, {
130
+ icon: messageConfig.icon,
131
+ spin: type === MESSAGE_TYPES.IN_PROGRESS
132
+ });
133
+ }
134
+ return null;
135
+ };
136
+ const icon = renderIcon();
137
+ const resolvedChildren = type === MESSAGE_TYPES.THINKING ? children ?? 'Thinking' : children;
120
138
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
121
139
  className: (0, _classnames.default)('message-component', isStatus && 'status', messageConfig.className, {
122
140
  'center-status': isCentered,
123
141
  sm: size === MESSAGE_SIZES.SM
124
- },
125
- // global styles for now, should be moved into the components styles, once we message css usages to React
126
- className, `with-${iconPlacement}-icon`),
142
+ }, className, `with-${iconPlacement}-icon`),
127
143
  "test-id": testId,
128
144
  id: id,
129
145
  "aria-live": "polite",
130
146
  role: messageConfig?.role,
131
147
  children: [iconPlacement === MESSAGE_ICON_PLACEMENT.LEFT && icon, /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
132
- children: children
148
+ children: resolvedChildren
133
149
  }), iconPlacement === MESSAGE_ICON_PLACEMENT.RIGHT && icon]
134
150
  });
135
151
  }
@@ -0,0 +1,12 @@
1
+ import { ValueOf } from '../types';
2
+ import './thinking-icon.less';
3
+ export declare const THINKING_ICON_SIZES: {
4
+ readonly SM: "sm";
5
+ readonly MD: "md";
6
+ };
7
+ export type ThinkingIconSize = ValueOf<typeof THINKING_ICON_SIZES>;
8
+ type ThinkingIconProps = {
9
+ size?: ThinkingIconSize;
10
+ };
11
+ export declare function ThinkingIcon({ size, }: ThinkingIconProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.THINKING_ICON_SIZES = void 0;
7
+ exports.ThinkingIcon = ThinkingIcon;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _classnames = _interopRequireDefault(require("classnames"));
10
+ var _jsxRuntime = require("react/jsx-runtime");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ const THINKING_ICON_SIZES = exports.THINKING_ICON_SIZES = {
13
+ SM: 'sm',
14
+ MD: 'md'
15
+ };
16
+ // Bar geometry in natural SVG coordinates (viewBox 0 0 18.667 18).
17
+ const BARS = [{
18
+ top: 0,
19
+ left: 0,
20
+ width: 9.334
21
+ }, {
22
+ top: 2,
23
+ left: 9.334,
24
+ width: 4.661
25
+ }, {
26
+ top: 4,
27
+ left: 0,
28
+ width: 9.334
29
+ }, {
30
+ top: 6,
31
+ left: 14,
32
+ width: 4.667
33
+ }, {
34
+ top: 8,
35
+ left: 0,
36
+ width: 14
37
+ }, {
38
+ top: 10,
39
+ left: 14,
40
+ width: 4.667
41
+ }, {
42
+ top: 12,
43
+ left: 0,
44
+ width: 9.334
45
+ }, {
46
+ top: 14,
47
+ left: 9.334,
48
+ width: 4.661
49
+ }, {
50
+ top: 16,
51
+ left: 0,
52
+ width: 9.334
53
+ }];
54
+ const BAR_HEIGHT = 2;
55
+
56
+ // Staggered cascade: left backbone bars enter first, right accent bars follow.
57
+ // Entry order: r1 → r7 → r3 → r9 → r5 → r8 → r2 → r4 → r6
58
+ const DELAYS = [0.0, 0.62, 0.22, 0.7, 0.44, 0.76, 0.12, 0.54, 0.32];
59
+ function ThinkingIcon({
60
+ size = THINKING_ICON_SIZES.MD
61
+ }) {
62
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
63
+ className: (0, _classnames.default)('thinking-icon', size),
64
+ viewBox: "0 0 18.667 18",
65
+ "aria-hidden": "true",
66
+ children: BARS.map((bar, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)("rect", {
67
+ className: "bar",
68
+ x: bar.left,
69
+ y: bar.top,
70
+ width: bar.width,
71
+ height: BAR_HEIGHT
72
+ // eslint-disable-next-line react/forbid-dom-props
73
+ ,
74
+ style: {
75
+ animationDelay: `${DELAYS[i]}s`
76
+ }
77
+ }, i))
78
+ });
79
+ }
@@ -170,9 +170,7 @@ function TextEditorContent({
170
170
  useSlate
171
171
  } = slateReact;
172
172
  const editor = useSlate();
173
- /* eslint-disable-next-line testing-library/render-result-naming-convention */
174
173
  const ElementNode = elementRender;
175
- /* eslint-disable-next-line testing-library/render-result-naming-convention */
176
174
  const LeafNode = leafRender;
177
175
 
178
176
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import './expandable-content.less';
3
+ export type ExpandableContentProps = {
4
+ /** Content to render */
5
+ children: React.ReactNode;
6
+ /** Maximum height in pixels. When content exceeds this height it is clipped and a Show more/Show less button appears */
7
+ maxHeight: number;
8
+ /** Additional CSS class applied to the wrapper */
9
+ className?: string;
10
+ };
11
+ /** Clips content to a maximum height and shows a Show more/Show less ghost button when the content overflows.
12
+ * @midnight-gray-supported
13
+ * @alpine-light-supported
14
+ */
15
+ declare const ExpandableContent: React.FC<ExpandableContentProps>;
16
+ export { ExpandableContent };
@@ -0,0 +1,53 @@
1
+ import React, { useLayoutEffect, useRef, useState } from 'react';
2
+ import classNames from 'classnames';
3
+ import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
4
+ import { faChevronUp } from '@fortawesome/free-solid-svg-icons/faChevronUp';
5
+ import { Button, ACCENT_TYPES } from '../button';
6
+ import { useTranslation } from '../hooks/use-translation';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ /** Clips content to a maximum height and shows a Show more/Show less ghost button when the content overflows.
9
+ * @midnight-gray-supported
10
+ * @alpine-light-supported
11
+ */
12
+ const ExpandableContent = ({
13
+ children,
14
+ maxHeight,
15
+ className
16
+ }) => {
17
+ const [isExpanded, setIsExpanded] = useState(false);
18
+ const [isOverflowing, setIsOverflowing] = useState(false);
19
+ const contentRef = useRef(null);
20
+ const {
21
+ t
22
+ } = useTranslation();
23
+ useLayoutEffect(() => {
24
+ if (contentRef.current) {
25
+ setIsOverflowing(contentRef.current.scrollHeight > maxHeight);
26
+ }
27
+ }, [children, maxHeight]);
28
+ const isClipped = isOverflowing && !isExpanded;
29
+ return /*#__PURE__*/_jsxs("div", {
30
+ className: classNames('expandable-content', className),
31
+ "test-id": "expandable-content",
32
+ children: [/*#__PURE__*/_jsx("div", {
33
+ ref: contentRef,
34
+ className: "expandable-content-body"
35
+ // eslint-disable-next-line react/forbid-dom-props
36
+ ,
37
+ style: isClipped ? {
38
+ maxHeight,
39
+ overflow: 'hidden'
40
+ } : undefined,
41
+ "test-id": "expandable-content-body",
42
+ children: children
43
+ }), isOverflowing && /*#__PURE__*/_jsx(Button, {
44
+ accentType: ACCENT_TYPES.GHOST,
45
+ onClick: () => setIsExpanded(prev => !prev),
46
+ className: "expandable-content-toggle",
47
+ rightIcon: isExpanded ? faChevronUp : faChevronDown,
48
+ testId: "expandable-content-toggle",
49
+ children: isExpanded ? t('Show less') : t('Show more')
50
+ })]
51
+ });
52
+ };
53
+ export { ExpandableContent };
@@ -0,0 +1,3 @@
1
+ import { ExpandableContent, ExpandableContentProps } from './expandable-content';
2
+ export type { ExpandableContentProps };
3
+ export { ExpandableContent };
@@ -0,0 +1,2 @@
1
+ import { ExpandableContent } from './expandable-content';
2
+ export { ExpandableContent };
@@ -8,6 +8,7 @@ export declare const VALIDATION_RULE_TYPES: {
8
8
  readonly IN_PROGRESS: "in-progress";
9
9
  readonly EXPIRED: "expired";
10
10
  readonly DISABLED: "disabled";
11
+ readonly THINKING: "thinking";
11
12
  };
12
13
  export type ValidationRuleTypes = ValueOf<typeof VALIDATION_RULE_TYPES>;
13
14
  export declare const MESSAGE_DISPLAY_LOCATION: {
@@ -30,6 +31,7 @@ export type VALIDATION_VALUES = {
30
31
  [VALIDATION_RULE_TYPES.IN_PROGRESS]?: string;
31
32
  [VALIDATION_RULE_TYPES.EXPIRED]?: string;
32
33
  [VALIDATION_RULE_TYPES.DISABLED]?: string;
34
+ [VALIDATION_RULE_TYPES.THINKING]?: string;
33
35
  };
34
36
  export declare const useDefaultValidationValues: () => VALIDATION_VALUES;
35
37
  export declare const INPUT_TYPES: {
@@ -9,7 +9,8 @@ export const VALIDATION_RULE_TYPES = {
9
9
  SUCCESS_INFO: 'success-info',
10
10
  IN_PROGRESS: 'in-progress',
11
11
  EXPIRED: 'expired',
12
- DISABLED: 'disabled'
12
+ DISABLED: 'disabled',
13
+ THINKING: 'thinking'
13
14
  };
14
15
  export const MESSAGE_DISPLAY_LOCATION = {
15
16
  INLINE: 'inline',
package/esm/index.d.ts CHANGED
@@ -33,6 +33,7 @@ export * from './editable-text';
33
33
  export * from './embedded-steps';
34
34
  export * from './empty-state';
35
35
  export * from './error-boundary';
36
+ export * from './expandable-content';
36
37
  export * from './export-button';
37
38
  export * from './file-tree';
38
39
  export * from './file-upload';
package/esm/index.js CHANGED
@@ -33,6 +33,7 @@ export * from './editable-text';
33
33
  export * from './embedded-steps';
34
34
  export * from './empty-state';
35
35
  export * from './error-boundary';
36
+ export * from './expandable-content';
36
37
  export * from './export-button';
37
38
  export * from './file-tree';
38
39
  export * from './file-upload';
@@ -3,6 +3,12 @@ import './markdown.less';
3
3
  type Props = {
4
4
  className?: string;
5
5
  children?: React.ReactNode;
6
+ /** If set, content will be clipped to this height and a Show more/Show less button will appear */
7
+ maxHeight?: number;
6
8
  };
9
+ /** Renders markdown content as HTML with support for GFM, math, and syntax highlighting.
10
+ * @midnight-gray-supported
11
+ * @alpine-light-supported
12
+ */
7
13
  declare const Markdown: React.FC<Props>;
8
14
  export { Markdown };
@@ -1,12 +1,18 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import { Message, MESSAGE_TYPES } from '../message';
4
+ import { ExpandableContent } from '../expandable-content';
4
5
  import { datarobotCSSClasses } from './markdown-utils';
5
6
  import { useTranslation } from '../hooks/use-translation';
6
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
+ /** Renders markdown content as HTML with support for GFM, math, and syntax highlighting.
9
+ * @midnight-gray-supported
10
+ * @alpine-light-supported
11
+ */
7
12
  const Markdown = ({
8
13
  children,
9
- className
14
+ className,
15
+ maxHeight
10
16
  }) => {
11
17
  const [html, setHtml] = useState('');
12
18
  const [error, setError] = useState('');
@@ -66,11 +72,18 @@ const Markdown = ({
66
72
  if (!html) {
67
73
  return null;
68
74
  }
69
- return /*#__PURE__*/_jsx("div", {
75
+ const content = /*#__PURE__*/_jsx("div", {
70
76
  className: classNames('markdown', className),
71
77
  dangerouslySetInnerHTML: {
72
78
  __html: String(html)
73
79
  }
74
80
  });
81
+ if (maxHeight !== undefined) {
82
+ return /*#__PURE__*/_jsx(ExpandableContent, {
83
+ maxHeight: maxHeight,
84
+ children: content
85
+ });
86
+ }
87
+ return content;
75
88
  };
76
89
  export { Markdown };
@@ -11,6 +11,7 @@ export declare const MESSAGE_TYPES: {
11
11
  readonly SUCCESS_INFO: "success-info";
12
12
  readonly IN_PROGRESS: "in-progress";
13
13
  readonly EXPIRED: "expired";
14
+ readonly THINKING: "thinking";
14
15
  };
15
16
  export declare const MESSAGE_ICON_PLACEMENT: {
16
17
  readonly LEFT: "left";
@@ -37,7 +38,7 @@ type Icons = {
37
38
  [key: string]: IconLookup;
38
39
  };
39
40
  export type MessageProps = {
40
- children: ReactNode;
41
+ children?: ReactNode;
41
42
  className?: string;
42
43
  testId?: string;
43
44
  /** Identifies the type of the message */