@vectara/vectara-ui 1.0.1 → 3.4.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 (66) hide show
  1. package/.github/workflows/open-vui-pr.yml +85 -0
  2. package/.github/workflows/{publish-on-version-change.yml → tag-on-version-change.yml} +6 -19
  3. package/README.md +77 -0
  4. package/lib/components/app/appSideNav/AppSideNav.js +1 -1
  5. package/lib/components/app/appSideNav/AppSideNavTree.js +1 -1
  6. package/lib/components/button/BaseButton.d.ts +4 -1
  7. package/lib/components/button/BaseButton.js +9 -5
  8. package/lib/components/button/IconButton.d.ts +5 -1
  9. package/lib/components/button/IconButton.js +4 -1
  10. package/lib/components/callout/Callout.js +1 -1
  11. package/lib/components/chat/Chat.js +7 -1
  12. package/lib/components/chat/ChatPanel.js +1 -1
  13. package/lib/components/chat/ChatTurn.js +1 -1
  14. package/lib/components/code/Code.d.ts +2 -1
  15. package/lib/components/code/Code.js +15 -6
  16. package/lib/components/code/_index.scss +23 -4
  17. package/lib/components/drawer/Drawer.js +1 -1
  18. package/lib/components/drawer/_index.scss +4 -8
  19. package/lib/components/form/index.d.ts +1 -0
  20. package/lib/components/form/input/TextInput.d.ts +5 -0
  21. package/lib/components/form/textArea/TextArea.d.ts +1 -0
  22. package/lib/components/form/textArea/TextArea.js +2 -1
  23. package/lib/components/form/textArea/_index.scss +4 -0
  24. package/lib/components/formGroup/FormGroup.js +11 -1
  25. package/lib/components/icon/Icon.js +1 -1
  26. package/lib/components/icon/_index.scss +1 -0
  27. package/lib/components/index.d.ts +6 -4
  28. package/lib/components/index.js +4 -2
  29. package/lib/components/infoList/InfoList.d.ts +9 -0
  30. package/lib/components/infoList/InfoList.js +4 -0
  31. package/lib/components/infoList/_index.scss +17 -0
  32. package/lib/components/infoMenu/InfoMenu.d.ts +7 -0
  33. package/lib/components/infoMenu/InfoMenu.js +19 -0
  34. package/lib/components/infoMenu/_index.scss +8 -0
  35. package/lib/components/link/types.d.ts +3 -0
  36. package/lib/components/modal/Modal.js +1 -1
  37. package/lib/components/modal/_index.scss +18 -9
  38. package/lib/components/notification/Notification.js +1 -1
  39. package/lib/components/optionsButton/OptionsButton.d.ts +1 -1
  40. package/lib/components/popover/Popover.d.ts +3 -1
  41. package/lib/components/popover/Popover.js +12 -9
  42. package/lib/components/screenBlock/ScreenBlock.d.ts +2 -1
  43. package/lib/components/screenBlock/ScreenBlock.js +4 -2
  44. package/lib/components/screenBlock/_index.scss +24 -0
  45. package/lib/components/searchSelect/SearchSelect.js +8 -6
  46. package/lib/components/statList/StatList.d.ts +3 -1
  47. package/lib/components/statList/StatList.js +20 -6
  48. package/lib/components/statList/_index.scss +10 -0
  49. package/lib/components/summary/Summary.d.ts +1 -1
  50. package/lib/components/summary/Summary.js +14 -2
  51. package/lib/components/table/Table.d.ts +9 -8
  52. package/lib/components/table/Table.js +20 -10
  53. package/lib/components/table/TableBulkActions.js +1 -1
  54. package/lib/components/table/_index.scss +18 -0
  55. package/lib/components/timeline/Timeline.d.ts +6 -0
  56. package/lib/components/timeline/Timeline.js +12 -0
  57. package/lib/components/timeline/TimelineItem.d.ts +6 -0
  58. package/lib/components/timeline/TimelineItem.js +6 -0
  59. package/lib/components/timeline/_index.scss +26 -0
  60. package/lib/components/timeline/index.d.ts +2 -0
  61. package/lib/components/timeline/index.js +2 -0
  62. package/lib/components/typography/_title.scss +6 -6
  63. package/lib/sassUtils/_depth.scss +2 -1
  64. package/lib/sassUtils/_typography.scss +1 -0
  65. package/lib/styles/index.css +141 -55
  66. package/package.json +6 -6
@@ -0,0 +1,85 @@
1
+ on:
2
+ push:
3
+ branches:
4
+ - main
5
+
6
+ name: open-vui-pr
7
+
8
+ jobs:
9
+ send-vectara-ui-pull-request:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v3
14
+ with:
15
+ fetch-depth: 0 # Checkout everything to get access to the tags
16
+ ref: ${{github.event.pull_request.head.ref}}
17
+ repository: ${{github.event.pull_request.head.repo.full_name}}
18
+ token: ${{ secrets.GITHUB_TOKEN }}
19
+
20
+ - name: Set up Node.js for NPM
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ registry-url: "https://registry.npmjs.org"
24
+
25
+ - name: Install json cli tool
26
+ run: sudo npm i -g json
27
+
28
+ - name: Send pull-request
29
+ run: |
30
+ LATEST_TAG=$(git describe --tags --always --abbrev=0)
31
+ REPOSITORY="vectara/vectara-ui"
32
+ FOLDER="bin/$REPOSITORY"
33
+ BRANCH_NAME="migrate-vui-source-changes-$LATEST_TAG"
34
+
35
+ # Clone the remote repository and change working directory to the
36
+ # folder it was cloned to.
37
+ git clone \
38
+ --depth=1 \
39
+ --branch=main \
40
+ https://mrderyk:${{secrets.AUTOMATED_PR_ACCESS_TOKEN}}@github.com/$REPOSITORY \
41
+ $FOLDER
42
+
43
+ cd $FOLDER
44
+
45
+ # Setup the committers identity.
46
+ git config user.email "deryk@vectara.com"
47
+ git config user.name "Deryk DeGuzman"
48
+
49
+ # Create a new feature branch for the changes.
50
+ git checkout -b $BRANCH_NAME
51
+
52
+ # Copy latest package.json
53
+ cp ${{ github.workspace }}/package.json .
54
+
55
+ # Update unique local package.json fields
56
+
57
+ # Update homepage field.
58
+ json -I -f package.json -e "this.homepage=\"https://vectara.github.io/vectara-ui/\""
59
+
60
+ # Update repo URL field.
61
+ json -I -f package.json -e "this.repository.url=\"git+https://github.com/vectara/vectara-ui.git\""
62
+
63
+ # Update bugs URL field.
64
+ json -I -f package.json -e "this.bugs.url=\"https://github.com/vectara/vectara-ui/issues\""
65
+
66
+ # Update source files.
67
+ cp -R ${{ github.workspace }}/src .
68
+
69
+ # Commit the changes and push the feature branch to origin
70
+ git add .
71
+ git commit -m "chore: migrate vui-source changes to $LATEST_TAG"
72
+ git push origin $BRANCH_NAME
73
+
74
+ # Store the PAT in a file that can be accessed by the
75
+ # GitHub CLI.
76
+ echo "${{secrets.AUTOMATED_PR_ACCESS_TOKEN}}" > token.txt
77
+
78
+ # Authorize GitHub CLI for the current repository and
79
+ # create a pull-requests containing the updates.
80
+ gh auth login --with-token < token.txt
81
+ gh pr create \
82
+ --body "" \
83
+ --title "chore: migrate vui-source changes to $LATEST_TAG" \
84
+ --head "$BRANCH_NAME" \
85
+ --base "main"
@@ -1,4 +1,4 @@
1
- name: publish-on-version-change
1
+ name: tag-on-version-change
2
2
  on:
3
3
  push:
4
4
  branches:
@@ -22,8 +22,8 @@ jobs:
22
22
  diff-search: true
23
23
  id: check
24
24
 
25
- publish-to-npm:
26
- name: publish-to-npm
25
+ tag-if-necessary:
26
+ name: tag-if-necessary
27
27
  runs-on: ubuntu-latest
28
28
  needs: [check-version-change]
29
29
  if: needs.check-version-change.outputs.did-version-change == 'true'
@@ -31,21 +31,8 @@ jobs:
31
31
  - name: Checkout repository
32
32
  uses: actions/checkout@v2
33
33
 
34
- # Draft a release if version name changed
35
- - name: Draft release
36
- run: 'gh release create v${{ needs.check-version-change.outputs.new-version }} -d --title "Release ${{ needs.check-version-change.outputs.new-version }}" --generate-notes'
34
+ # Create a release if version name changed
35
+ - name: Create release
36
+ run: 'gh release create v${{ needs.check-version-change.outputs.new-version }} --title "Release ${{ needs.check-version-change.outputs.new-version }}" --generate-notes'
37
37
  env:
38
38
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39
-
40
- - name: Set up Node.js for NPM
41
- uses: actions/setup-node@v4
42
- with:
43
- registry-url: "https://registry.npmjs.org"
44
-
45
- - name: Build lib
46
- run: "npm i && npm run buildLib"
47
-
48
- - name: Publish package to NPM
49
- run: npm publish --access=public
50
- env:
51
- NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Vectara UI
2
+
3
+ This is Vectara's design system, codified as a React component library. It's intended solely for consumption by Vectara and currently it isn't available for use by anybody else. For more information see [NO_LICENSE](./NO_LICENSE).
4
+
5
+ ## Usage
6
+
7
+ Import components like this:
8
+
9
+ ```tsx
10
+ import { VuiFlexContainer, VuiItem } from "@vectara/vectara-ui";
11
+ ```
12
+
13
+ Import our utils like this:
14
+
15
+ ```tsx
16
+ import { extractCitations } from "@vectara/vectara-ui/lib/utils/citations";
17
+ ```
18
+
19
+ To import the CSS for the components, import this stylesheet at the root level:
20
+
21
+ ```tsx
22
+ import "@vectara/vectara-ui/lib/styles/index";
23
+ ```
24
+
25
+ If you are using Sass and need Vectara UI's Sass variables, you can use this import in the files that use the variables:
26
+
27
+ ```scss
28
+ @import "@vectara/vectara-ui/lib/sassUtils/index";
29
+ ```
30
+
31
+ ## Publishing
32
+
33
+ Publishing a new version of the package consists of three steps:
34
+
35
+ 1. Maintaining the CHANGELOG.
36
+ 2. Versioning the package.
37
+ 3. Publishing to NPM.
38
+
39
+ ### Maintain the CHANGELOG
40
+
41
+ As you introduce changes, record them in the CHANGELOG beneath the `main` section. Before you create a new version, submit a PR that updates the `package.json` version and moves the `main` content into a new section for the new version. We follow semver, so breaking changes should result in a major version bump.
42
+
43
+ ### Version the package
44
+
45
+ 1. Run `npm version {number}` to update package.json with the new version number and create a tag to track the version.
46
+ 2. Run `git push origin --tags` to push the new tag to the repo.
47
+ 3. Optional: [Manually create a release in GitHub.](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository)
48
+
49
+ ### Publish to NPM
50
+
51
+ 1. Run `npm run buildPackage` to create the distributable files.
52
+ 2. Run `npm login --scope=@vectara --registry="https://registry.npmjs.org/"` to log into the registry and scope.
53
+ 3. Run `npm publish --access public` to publish the package to NPM.
54
+
55
+ ## Local development
56
+
57
+ Use `npm run start` to run the docs site locally and interact with the code you're developing.
58
+
59
+ To test the package locally, use [`npm link`](https://docs.npmjs.com/cli/v9/commands/npm-link) to consume the distributable files in a sibling project.
60
+
61
+ If you get an error regarding an ["invalid hook call"](https://iws.io/2022/invalid-hook-multiple-react-instances), you might need to use `npm link` to temporarily link the consumer's React dependencies to Vectara-UI's React dependencies. In this example, we're consuming Vectara-UI in [Vectara-Answer](https://github.com/vectara/vectara-answer):
62
+
63
+ ```bash
64
+ npm link ../vectara-answer/node_modules/react ../vectara-answer/node_modules/react-dom ../vectara-answer/node_modules/react-router-dom
65
+ ```
66
+
67
+ When you're done testing out the consumer, you can unlink these dependencies:
68
+
69
+ ```bash
70
+ npm unlink ../vectara-answer/node_modules/react ../vectara-answer/node_modules/react-dom ../vectara-answer/node_modules/react-router-dom
71
+ ```
72
+
73
+ ## Licensing and public use
74
+
75
+ Though the GitHub terms of service grant anybody the right to fork and look through this repository, we haven't yet licensed this code for use by anybody else. This means Vectara reserves all rights to the contents of this repository. You can't reproduce, distribute, or create derivative works from it. For more information on reserved copyright of GitHub repos, see https://choosealicense.com/no-permission/.
76
+
77
+ For more information on our lack of licensing, see [NO_LICENSE](./NO_LICENSE).
@@ -39,7 +39,7 @@ export const VuiAppSideNav = ({ items = [], content }) => {
39
39
  "vuiAppSideNavContent-isHidden": isCollapsed
40
40
  });
41
41
  const navItems = buildSideNavItems(items);
42
- return (_jsx("div", Object.assign({ className: classes }, { children: _jsxs("div", Object.assign({ className: "vuiAppSideNav__inner" }, { children: [isCollapsed ? (_jsx(VuiIconButton, { ref: expandButtonRef, "aria-label": "Expand nav", onClick: () => setIsCollapsed(false), className: "vuiAppSideNavExpandButton", color: "neutral", icon: _jsx(VuiIcon, { children: _jsx(BiChevronRight, {}) }) })) : (_jsx(_Fragment, { children: _jsx("button", Object.assign({ ref: collapseButtonRef, className: "vuiAppSideNavCollapseButton", onClick: () => {
42
+ return (_jsx("div", Object.assign({ className: classes }, { children: _jsxs("div", Object.assign({ className: "vuiAppSideNav__inner" }, { children: [isCollapsed ? (_jsx(VuiIconButton, { ref: expandButtonRef, "aria-label": "Show nav", onClick: () => setIsCollapsed(false), className: "vuiAppSideNavExpandButton", color: "neutral", icon: _jsx(VuiIcon, { children: _jsx(BiChevronRight, {}) }) })) : (_jsx(_Fragment, { children: _jsx("button", Object.assign({ ref: collapseButtonRef, className: "vuiAppSideNavCollapseButton", onClick: () => {
43
43
  setIsTouched(true);
44
44
  setIsCollapsed(true);
45
45
  } }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xxs" }, { children: [_jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIcon, { children: _jsx(BiChevronLeft, {}) }) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: "Collapse nav" }))] })) })) })), _jsxs("div", Object.assign({ className: contentClasses, inert: isCollapsed ? "" : null }, { children: [navItems, content] }))] })) })));
@@ -34,5 +34,5 @@ const buildTreeItems = (items) => {
34
34
  const AppSideNavTreeSection = (_a) => {
35
35
  var { name, path, children, iconBefore, iconAfter, isActive } = _a, rest = __rest(_a, ["name", "path", "children", "iconBefore", "iconAfter", "isActive"]);
36
36
  const [isOpen, setIsOpen] = useState(true);
37
- return (_jsxs("div", Object.assign({ className: "vuiAppSideNavTreeSection" }, { children: [_jsx(VuiAppSideNavLink, Object.assign({ path: path !== null && path !== void 0 ? path : "/", name: name, iconBefore: iconBefore, iconAfter: iconAfter, isActive: isActive }, rest)), _jsx(VuiIconButton, { size: "s", className: "vuiAppSideNavTreeToggleButton", onClick: () => setIsOpen(!isOpen), color: "neutral", icon: _jsx(VuiIcon, { children: isOpen ? _jsx(BiChevronUp, {}) : _jsx(BiChevronDown, {}) }) }), isOpen && _jsx("div", Object.assign({ className: "vuiAppSideNavTreeChildren" }, { children: children }))] })));
37
+ return (_jsxs("div", Object.assign({ className: "vuiAppSideNavTreeSection" }, { children: [_jsx(VuiAppSideNavLink, Object.assign({ path: path !== null && path !== void 0 ? path : "/", name: name, iconBefore: iconBefore, iconAfter: iconAfter, isActive: isActive }, rest)), _jsx(VuiIconButton, { "aria-label": isOpen ? "Hide section" : "Show section", size: "s", className: "vuiAppSideNavTreeToggleButton", onClick: () => setIsOpen(!isOpen), color: "neutral", icon: _jsx(VuiIcon, { children: isOpen ? _jsx(BiChevronUp, {}) : _jsx(BiChevronDown, {}) }) }), isOpen && _jsx("div", Object.assign({ className: "vuiAppSideNavTreeChildren" }, { children: children }))] })));
38
38
  };
@@ -13,7 +13,10 @@ export type BaseButtonProps = {
13
13
  isSelected?: boolean;
14
14
  isInert?: boolean;
15
15
  isDisabled?: boolean;
16
- onClick?: (e: React.MouseEvent<HTMLAnchorElement | HTMLAnchorElement, MouseEvent>) => void;
16
+ onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
17
+ onMouseOver?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
18
+ onMouseOut?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
19
+ onMouseMove?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
17
20
  href?: LinkProps["href"];
18
21
  target?: LinkProps["target"];
19
22
  track?: LinkProps["track"];
@@ -27,7 +27,7 @@ const sizeToSpinnerSizeMap = {
27
27
  l: "m"
28
28
  };
29
29
  export const BaseButton = forwardRef((_a, ref) => {
30
- var { children, icon, iconSide = "left", align = "center", className, size = "m", fullWidth, onClick, tabIndex, isInert, isDisabled, href, target, track, htmlFor, isSubmit, isLoading, spinnerColor } = _a, rest = __rest(_a, ["children", "icon", "iconSide", "align", "className", "size", "fullWidth", "onClick", "tabIndex", "isInert", "isDisabled", "href", "target", "track", "htmlFor", "isSubmit", "isLoading", "spinnerColor"]);
30
+ var { children, icon, iconSide = "left", align = "center", className, size = "m", fullWidth, onClick, onMouseOver, onMouseOut, onMouseMove, tabIndex, isInert, isDisabled, href, target, track, htmlFor, isSubmit, isLoading, spinnerColor } = _a, rest = __rest(_a, ["children", "icon", "iconSide", "align", "className", "size", "fullWidth", "onClick", "onMouseOver", "onMouseOut", "onMouseMove", "tabIndex", "isInert", "isDisabled", "href", "target", "track", "htmlFor", "isSubmit", "isLoading", "spinnerColor"]);
31
31
  const { createLink } = useVuiContext();
32
32
  const classes = classNames("vuiBaseButton", className, `vuiBaseButton--${size}`, alignToClassMap[align], {
33
33
  "vuiBaseButton-isInert": isInert,
@@ -52,14 +52,18 @@ export const BaseButton = forwardRef((_a, ref) => {
52
52
  "vuiBaseButtonLinkWrapper--fullWidth": fullWidth
53
53
  });
54
54
  return createLink(Object.assign(Object.assign({ className: wrapperClasses, href,
55
- onClick, children: (
55
+ onClick,
56
+ onMouseOver,
57
+ onMouseOut,
58
+ onMouseMove, children: (
56
59
  //* Wrap a button otherwise the flex layout breaks */}
57
60
  _jsxs("button", Object.assign({ className: classes, tabIndex: -1, ref: ref }, { children: [iconContainer, children] }))), target,
58
61
  tabIndex }, rest), getTrackingProps(track)));
59
62
  }
60
63
  const props = Object.assign({ onClick,
64
+ onMouseOver,
65
+ onMouseOut,
66
+ onMouseMove,
61
67
  tabIndex, ["type"]: isSubmit ? "submit" : "button", disabled: isDisabled }, rest);
62
- return (
63
- // @ts-expect-error HTMLButtonElement conflict with HTMLAnchorElement
64
- _jsxs("button", Object.assign({ className: classes }, props, { ref: ref }, { children: [iconContainer, children] })));
68
+ return (_jsxs("button", Object.assign({ className: classes }, props, { ref: ref }, { children: [iconContainer, children] })));
65
69
  });
@@ -4,9 +4,13 @@ import { LinkProps } from "../link/types";
4
4
  type Props = {
5
5
  className?: string;
6
6
  icon: ReactElement;
7
+ "aria-label": string;
7
8
  color?: ButtonColor;
8
9
  size?: (typeof BUTTON_SIZE)[number];
9
- onClick?: () => void;
10
+ onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
11
+ onMouseOver?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
12
+ onMouseOut?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
13
+ onMouseMove?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
10
14
  href?: LinkProps["href"];
11
15
  target?: LinkProps["target"];
12
16
  track?: LinkProps["track"];
@@ -16,9 +16,12 @@ import { getTrackingProps } from "../../utils/getTrackingProps";
16
16
  import { createButtonIcon } from "./createButtonIcon";
17
17
  import { useVuiContext } from "../context/Context";
18
18
  export const VuiIconButton = forwardRef((_a, ref) => {
19
- var { className, icon, color = "primary", size = "m", onClick, href, target, track, tabIndex } = _a, rest = __rest(_a, ["className", "icon", "color", "size", "onClick", "href", "target", "track", "tabIndex"]);
19
+ var { className, icon, color = "primary", size = "m", onClick, onMouseOver, onMouseOut, onMouseMove, href, target, track, tabIndex } = _a, rest = __rest(_a, ["className", "icon", "color", "size", "onClick", "onMouseOver", "onMouseOut", "onMouseMove", "href", "target", "track", "tabIndex"]);
20
20
  const { createLink } = useVuiContext();
21
21
  const props = Object.assign({ className: classNames("vuiIconButton", className, `vuiIconButton--${color}`, `vuiIconButton--${size}`), onClick,
22
+ onMouseOver,
23
+ onMouseOut,
24
+ onMouseMove,
22
25
  tabIndex }, rest);
23
26
  const buttonIcon = createButtonIcon(icon, size, color);
24
27
  if (href) {
@@ -36,5 +36,5 @@ export const VuiCallout = (_a) => {
36
36
  var { children, title, headingElement, color, size = "m", onDismiss } = _a, rest = __rest(_a, ["children", "title", "headingElement", "color", "size", "onDismiss"]);
37
37
  const classes = classNames("vuiCallout", `vuiCallout--${color}`, `vuiCallout--${size}`);
38
38
  const HeadingElement = headingElement;
39
- return (_jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "start", justifyContent: "spaceBetween" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx(VuiTitle, Object.assign({ size: sizeToTitleSizeMap[size] }, { children: _jsx(HeadingElement, { children: _jsx(VuiTextColor, Object.assign({ color: color }, { children: title })) }) })) })), onDismiss && (_jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { className: "vuiCallout__closeButton", "data-testid": "calloutCloseButton", color: color, onClick: onDismiss, icon: _jsx(BiX, {}), size: "s" }) })))] })), children && (_jsxs(_Fragment, { children: [_jsx(VuiSpacer, { size: sizeToSpacerSizeMap[size] }), _jsx(VuiText, Object.assign({ size: sizeToContentSizeMap[size] }, { children: children }))] }))] })));
39
+ return (_jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "start", justifyContent: "spaceBetween" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx(VuiTitle, Object.assign({ size: sizeToTitleSizeMap[size] }, { children: _jsx(HeadingElement, { children: _jsx(VuiTextColor, Object.assign({ color: color }, { children: title })) }) })) })), onDismiss && (_jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { "aria-label": "Hide information", className: "vuiCallout__closeButton", "data-testid": "calloutCloseButton", color: color, onClick: onDismiss, icon: _jsx(BiX, {}), size: "s" }) })))] })), children && (_jsxs(_Fragment, { children: [_jsx(VuiSpacer, { size: sizeToSpacerSizeMap[size] }), _jsx(VuiText, Object.assign({ size: sizeToContentSizeMap[size] }, { children: children }))] }))] })));
40
40
  };
@@ -20,6 +20,12 @@ const chatStyleToIconMap = {
20
20
  tall: _jsx(BiExpand, {}),
21
21
  fullScreen: _jsx(BiX, {})
22
22
  };
23
+ const chatStyleToAriaLabelMap = {
24
+ closed: "Show chat",
25
+ condensed: "Expand height of chat",
26
+ tall: "Full-screen chat",
27
+ fullScreen: "Hide chat"
28
+ };
23
29
  export const VuiChat = ({ openPrompt, chatStyle, setChatStyle, introduction, suggestions, onInput, onRetry, onReset, conversation, settings, isInspectionEnabled }) => {
24
30
  const [isTouched, setIsTouched] = useState(false);
25
31
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
@@ -126,5 +132,5 @@ export const VuiChat = ({ openPrompt, chatStyle, setChatStyle, introduction, sug
126
132
  setChatStyle("closed");
127
133
  } }, { children: [_jsx("div", Object.assign({ className: "vuiChat__header" }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", justifyContent: "spaceBetween" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "s" }, { children: [_jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIcon, Object.assign({ size: "s" }, { children: _jsx(BiChat, {}) })) })), _jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx("div", Object.assign({ className: "vuiChatButton__prompt" }, { children: _jsx("h2", { children: openPrompt }) })) }))] })) })), settings && (_jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiButtonSecondary, Object.assign({ color: "neutral", size: "xs", onClick: () => setIsSettingsOpen(true) }, { children: "Settings" })) })))] })) })), _jsxs("div", Object.assign({ className: "vuiChat__conversation", ref: conversationRef }, { children: [(introduction || suggestions) && (_jsxs("div", Object.assign({ className: "vuiChat__introduction" }, { children: [introduction, introduction && _jsx(VuiSpacer, { size: "s" }), suggestions === null || suggestions === void 0 ? void 0 : suggestions.map((suggestion) => (_jsx("div", { children: _jsx(VuiButtonTertiary, Object.assign({ size: "s", color: "primary", onClick: () => onInput(suggestion), noPadding: true }, { children: suggestion }), suggestion) }))), suggestions && suggestions.length > 0 && _jsx(VuiSpacer, { size: "s" })] }))), conversation.length > 0 && (_jsx("div", Object.assign({ className: "vuiChat__turns" }, { children: conversation.map((turn, index) => (_jsx(VuiChatTurn, { turn: turn, isInspectionEnabled: isInspectionEnabled, setInspectedTurn: setInspectedTurn, onRetry: onRetry }, index))) }))), conversation.length > 0 && (_jsx("div", Object.assign({ className: "vuiChat__conversationActions" }, { children: _jsx(VuiFlexContainer, Object.assign({ alignItems: "center", justifyContent: "center" }, { children: _jsx(VuiFlexItem, { children: _jsx(VuiButtonSecondary, Object.assign({ color: "neutral", size: "xs", onClick: onReset }, { children: "Start over" })) }) })) })))] })), _jsx("div", Object.assign({ className: "vuiChat__input" }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xxs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx(VuiTextInput, { value: input, onChange: (e) => {
128
134
  setInput(e.currentTarget.value);
129
- }, onSubmit: onSubmit, fullWidth: true, ref: inputRef }) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { icon: _jsx(VuiIcon, { children: _jsx(BiPaperPlane, {}) }), color: "primary", onClick: onSubmit }) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { icon: _jsx(VuiIcon, { children: chatStyleToIconMap[chatStyle] }), color: "neutral", onClick: cycleChatStyle }) }))] })) })), isSettingsOpen && (_jsx(VuiChatPanel, Object.assign({ title: "Chat settings", onClose: () => setIsSettingsOpen(false) }, { children: settings }))), Boolean(inspectedTurn) && (_jsx(VuiChatInspector, { turn: inspectedTurn, onClose: () => setInspectedTurn(undefined) }))] }))] }));
135
+ }, onSubmit: onSubmit, fullWidth: true, ref: inputRef }) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { "aria-label": "Send message", icon: _jsx(VuiIcon, { children: _jsx(BiPaperPlane, {}) }), color: "primary", onClick: onSubmit }) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { "aria-label": chatStyleToAriaLabelMap[chatStyle], icon: _jsx(VuiIcon, { children: chatStyleToIconMap[chatStyle] }), color: "neutral", onClick: cycleChatStyle }) }))] })) })), isSettingsOpen && (_jsx(VuiChatPanel, Object.assign({ title: "Chat settings", onClose: () => setIsSettingsOpen(false) }, { children: settings }))), Boolean(inspectedTurn) && (_jsx(VuiChatInspector, { turn: inspectedTurn, onClose: () => setInspectedTurn(undefined) }))] }))] }));
130
136
  };
@@ -7,5 +7,5 @@ import { VuiIcon } from "../icon/Icon";
7
7
  import { VuiSpacer } from "../spacer/Spacer";
8
8
  import { VuiTitle } from "../typography/Title";
9
9
  export const VuiChatPanel = ({ title, onClose, children }) => {
10
- return (_jsxs("div", Object.assign({ className: "vuiChatPanel" }, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", justifyContent: "spaceBetween" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx(VuiTitle, Object.assign({ size: "s" }, { children: _jsx("h3", { children: title }) })) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { icon: _jsx(VuiIcon, { children: _jsx(BiX, {}) }), color: "neutral", onClick: () => onClose() }) }))] })), _jsx(VuiSpacer, { size: "s" }), children, _jsx(VuiSpacer, { size: "l" })] })));
10
+ return (_jsxs("div", Object.assign({ className: "vuiChatPanel" }, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", justifyContent: "spaceBetween" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx(VuiTitle, Object.assign({ size: "s" }, { children: _jsx("h3", { children: title }) })) })), _jsx(VuiFlexItem, Object.assign({ shrink: false, grow: false }, { children: _jsx(VuiIconButton, { "aria-label": "Hide chat", icon: _jsx(VuiIcon, { children: _jsx(BiX, {}) }), color: "neutral", onClick: () => onClose() }) }))] })), _jsx(VuiSpacer, { size: "s" }), children, _jsx(VuiSpacer, { size: "l" })] })));
11
11
  };
@@ -15,5 +15,5 @@ export const VuiChatTurn = ({ turn, isInspectionEnabled, setInspectedTurn, onRet
15
15
  const turnClasses = classNames("vuiChatQuestion", {
16
16
  "vuiChatQuestion--error": !turn.isLoading && turn.error
17
17
  });
18
- return (_jsxs("div", Object.assign({ className: "vuiChatTurn" }, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "start", justifyContent: "spaceBetween", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx("div", Object.assign({ className: turnClasses }, { children: _jsx("h3", { children: turn.question }) })) })), isInspectionEnabled && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIconButton, { size: "xs", className: "vuiChat__inspectButton", color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "s" }, { children: _jsx(BiListUl, {}) })), onClick: () => setInspectedTurn(turn) }) })))] })), _jsx("div", Object.assign({ className: "vuiChatAnswer" }, { children: turn.isLoading ? (_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiSpinner, { size: "xs" }) })), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: "Thinking\u2026" })) }) }) }))] }))) : turn.error ? (_jsxs(_Fragment, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiIcon, Object.assign({ color: "subdued" }, { children: _jsx(BiError, {}) })) })), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: (_a = turn.error) === null || _a === void 0 ? void 0 : _a.message })) }) }) }))] })), _jsx(VuiSpacer, { size: "s" }), _jsx(VuiButtonSecondary, Object.assign({ size: "xs", color: "neutral", onClick: () => onRetry(turn) }, { children: "Ask again" }))] })) : (turn.answer) }))] })));
18
+ return (_jsxs("div", Object.assign({ className: "vuiChatTurn" }, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "start", justifyContent: "spaceBetween", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: 1 }, { children: _jsx("div", Object.assign({ className: turnClasses }, { children: _jsx("h3", { children: turn.question }) })) })), isInspectionEnabled && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIconButton, { "aria-label": "Inspect turn", size: "xs", className: "vuiChat__inspectButton", color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "s" }, { children: _jsx(BiListUl, {}) })), onClick: () => setInspectedTurn(turn) }) })))] })), _jsx("div", Object.assign({ className: "vuiChatAnswer" }, { children: turn.isLoading ? (_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiSpinner, { size: "xs" }) })), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: "Thinking\u2026" })) }) }) }))] }))) : turn.error ? (_jsxs(_Fragment, { children: [_jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiIcon, Object.assign({ color: "subdued" }, { children: _jsx(BiError, {}) })) })), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: (_a = turn.error) === null || _a === void 0 ? void 0 : _a.message })) }) }) }))] })), _jsx(VuiSpacer, { size: "s" }), _jsx(VuiButtonSecondary, Object.assign({ size: "xs", color: "neutral", onClick: () => onRetry(turn) }, { children: "Ask again" }))] })) : (turn.answer) }))] })));
19
19
  };
@@ -9,9 +9,10 @@ import { CodeLanguage } from "./types";
9
9
  type Props = {
10
10
  language?: CodeLanguage;
11
11
  onCopy?: () => void;
12
+ isFullscreenEnabled?: boolean;
12
13
  children?: string;
13
14
  fullHeight?: boolean;
14
15
  "data-testid"?: string;
15
16
  };
16
- export declare const VuiCode: ({ onCopy, language, fullHeight, children, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
17
+ export declare const VuiCode: ({ onCopy, isFullscreenEnabled, language, fullHeight, children, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
17
18
  export {};
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useEffect } from "react";
13
+ import { useEffect, useState } from "react";
14
14
  import Prism from "prismjs";
15
15
  import "prismjs/themes/prism.css";
16
16
  import "prismjs/components/prism-json";
@@ -20,15 +20,18 @@ import "prismjs/components/prism-bash";
20
20
  import "prismjs/components/prism-jsx";
21
21
  import "prismjs/components/prism-tsx";
22
22
  import classNames from "classnames";
23
- import { BiClipboard } from "react-icons/bi";
23
+ import { BiClipboard, BiFullscreen, BiX } from "react-icons/bi";
24
24
  import { VuiIconButton } from "../button/IconButton";
25
25
  import { VuiIcon } from "../icon/Icon";
26
+ import { VuiFlexContainer } from "../flex/FlexContainer";
27
+ import { FocusOn } from "react-focus-on";
26
28
  // PrismJS clears highlighting when language-none is set.
27
29
  export const VuiCode = (_a) => {
28
- var { onCopy, language = "none", fullHeight, children = "" } = _a, rest = __rest(_a, ["onCopy", "language", "fullHeight", "children"]);
30
+ var { onCopy, isFullscreenEnabled = true, language = "none", fullHeight, children = "" } = _a, rest = __rest(_a, ["onCopy", "isFullscreenEnabled", "language", "fullHeight", "children"]);
31
+ const [isFullscreen, setIsFullscreen] = useState(false);
29
32
  useEffect(() => {
30
33
  Prism.highlightAll();
31
- }, [children, language]);
34
+ }, [children, language, isFullscreen]);
32
35
  const containerClasses = classNames("vuiCodeContainer", {
33
36
  "vuiCodeContainer--fullHeight": fullHeight
34
37
  });
@@ -36,9 +39,15 @@ export const VuiCode = (_a) => {
36
39
  "vuiCode--fullHeight": fullHeight
37
40
  });
38
41
  const testId = rest["data-testid"];
39
- return (_jsxs("div", Object.assign({ className: containerClasses }, rest, { children: [_jsx("pre", Object.assign({ className: "vuiCodePre" }, { children: _jsx("code", Object.assign({ className: classes }, { children: children })) })), _jsx(VuiIconButton, { color: "neutral", icon: _jsx(VuiIcon, { children: _jsx(BiClipboard, { size: 20 }) }), "aria-label": "Copy to clipboard", className: "vuiCodeCopyButton", onClick: () => {
42
+ const actions = (_jsxs(VuiFlexContainer, Object.assign({ className: "vuiCodeActions", spacing: "xxs" }, { children: [isFullscreenEnabled && (_jsx(VuiIconButton, { color: "neutral", size: "xs", icon: _jsx(VuiIcon, { children: _jsx(BiFullscreen, {}) }), "aria-label": "Full screen", onClick: () => {
43
+ setIsFullscreen(!isFullscreen);
44
+ } })), _jsx(VuiIconButton, { color: "neutral", size: "xs", icon: _jsx(VuiIcon, { children: _jsx(BiClipboard, {}) }), "aria-label": "Copy to clipboard", onClick: () => {
40
45
  navigator.clipboard.writeText(children);
41
46
  if (onCopy)
42
47
  onCopy();
43
- } }), testId && (_jsx("div", Object.assign({ "data-testid": `${testId}-hidden`, hidden: true }, { children: children })))] })));
48
+ } })] })));
49
+ const code = (_jsx("pre", Object.assign({ className: "vuiCodePre" }, { children: _jsx("code", Object.assign({ className: classes }, { children: children })) })));
50
+ return (_jsxs("div", Object.assign({ className: containerClasses }, rest, { children: [code, actions, testId && (_jsx("div", Object.assign({ "data-testid": `${testId}-hidden`, hidden: true }, { children: children }))), isFullscreen && (_jsx(FocusOn, Object.assign({ onEscapeKey: () => {
51
+ setIsFullscreen(false);
52
+ } }, { children: _jsxs("div", Object.assign({ className: "vuiCodeFullscreen" }, { children: [_jsx(VuiIconButton, { className: "vuiCodeFullscreen__closeButton", color: "neutral", size: "m", icon: _jsx(VuiIcon, { children: _jsx(BiX, {}) }), "aria-label": "Exit fullscreen code", onClick: () => setIsFullscreen(false) }), code] })) })))] })));
44
53
  };
@@ -8,9 +8,9 @@
8
8
  max-height: 100%;
9
9
  }
10
10
 
11
- .vuiCodeCopyButton {
11
+ .vuiCodeActions {
12
12
  position: absolute;
13
- right: $sizeXxs;
13
+ right: $sizeS;
14
14
  top: $sizeXxs;
15
15
  }
16
16
 
@@ -27,7 +27,26 @@
27
27
  background-color: $colorLightShade;
28
28
  color: $colorText;
29
29
  font-family: "Roboto Mono", monospace;
30
- word-wrap: break-word;
31
- white-space: pre-wrap;
30
+ // Ensure PrismJS components wrap their lines.
31
+ word-wrap: break-word !important;
32
+ white-space: pre-wrap !important;
32
33
  font-size: $fontSizeSmall !important;
33
34
  }
35
+
36
+ .vuiCodeFullscreen {
37
+ position: fixed;
38
+ top: 0;
39
+ left: 0;
40
+ right: 0;
41
+ bottom: 0;
42
+ z-index: $fullscreenZIndex;
43
+ // PrismJS theme color.
44
+ background-color: #f5f2f0;
45
+ overflow: auto;
46
+ }
47
+
48
+ .vuiCodeFullscreen__closeButton {
49
+ position: absolute;
50
+ right: $sizeS;
51
+ top: $sizeXxs;
52
+ }
@@ -49,5 +49,5 @@ export const VuiDrawer = (_a) => {
49
49
  returnFocus: false,
50
50
  // Enable focus on contents when it's open,
51
51
  // but enable manual focus return to work when it's closed.
52
- autoFocus: isOpen }, { children: _jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsx("div", Object.assign({ className: "vuiDrawerHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiDrawerHeader__title" }, { children: _jsx(DrawerTitle, { children: title }) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "data-testid": "drawerCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiDrawerContent" }, { children: _jsx("div", Object.assign({ className: "vuiDrawerContent__inner" }, { children: children })) }))] })) })) })) }));
52
+ autoFocus: isOpen }, { children: _jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsx("div", Object.assign({ className: "vuiDrawerHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiDrawerHeader__title" }, { children: _jsx(DrawerTitle, { children: title }) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Close drawer", "data-testid": "drawerCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiDrawerContent" }, { children: _jsx("div", Object.assign({ className: "vuiDrawerContent__inner" }, { children: children })) }))] })) })) })) }));
53
53
  };
@@ -28,11 +28,12 @@ $drawerWidth: 680px;
28
28
  }
29
29
 
30
30
  .vuiDrawerHeader {
31
- padding: $sizeL $sizeL;
31
+ padding: $sizeS $sizeL;
32
+ background-color: $colorLightShade;
32
33
  }
33
34
 
34
35
  .vuiDrawerHeader__title {
35
- font-size: $fontSizeXLarge;
36
+ font-size: $fontSizeMedium;
36
37
  font-weight: $fontWeightBold;
37
38
  line-height: 1.2;
38
39
  color: $colorText;
@@ -50,11 +51,9 @@ $drawerWidth: 680px;
50
51
  // Color
51
52
  $color: (
52
53
  primary: (
53
- "background-color": $colorPrimaryLightShade,
54
- "color": $colorText
54
+ "color": $colorPrimary
55
55
  ),
56
56
  danger: (
57
- "background-color": $colorDangerLightShade,
58
57
  "color": $colorDanger
59
58
  )
60
59
  );
@@ -62,9 +61,6 @@ $color: (
62
61
  @each $colorName, $colorValue in $color {
63
62
  .vuiDrawer--#{$colorName} {
64
63
  .vuiDrawerHeader {
65
- background-color: #{map.get($colorValue, "background-color")};
66
-
67
- .vuiDrawerHeader__title,
68
64
  .vuiIcon {
69
65
  color: #{map.get($colorValue, "color")};
70
66
  }
@@ -7,4 +7,5 @@ export { VuiSuperRadioGroup } from "./superRadioGroup/SuperRadioGroup";
7
7
  export { VuiTextInput } from "./input/TextInput";
8
8
  export { VuiTextArea } from "./textArea/TextArea";
9
9
  export { VuiPasswordInput } from "./input/PasswordInput";
10
+ export type { Props as TextInputProps } from "./input/TextInput";
10
11
  export type { RadioButtonConfig } from "./superRadioGroup/types";
@@ -1,4 +1,9 @@
1
1
  import { BasicInputProps } from "./BasicInput";
2
+ export type Props = BasicInputProps & {
3
+ value?: string;
4
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
5
+ maxLength?: number;
6
+ };
2
7
  export declare const VuiTextInput: import("react").ForwardRefExoticComponent<BasicInputProps & {
3
8
  value?: string | undefined;
4
9
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
@@ -7,6 +7,7 @@ type Props = {
7
7
  onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
8
8
  placeholder?: string;
9
9
  maxLength?: number;
10
+ isInvalid?: boolean;
10
11
  };
11
12
  export declare const VuiTextArea: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<HTMLTextAreaElement | null>>;
12
13
  export {};
@@ -13,8 +13,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { forwardRef } from "react";
14
14
  import classNames from "classnames";
15
15
  export const VuiTextArea = forwardRef((_a, ref) => {
16
- var { className, id, placeholder, value, onChange, fullWidth, name } = _a, rest = __rest(_a, ["className", "id", "placeholder", "value", "onChange", "fullWidth", "name"]);
16
+ var { className, id, placeholder, value, onChange, fullWidth, name, isInvalid } = _a, rest = __rest(_a, ["className", "id", "placeholder", "value", "onChange", "fullWidth", "name", "isInvalid"]);
17
17
  const classes = classNames("vuiTextArea", {
18
+ "vuiTextArea-isInvalid": isInvalid,
18
19
  "vuiTextArea--fullWidth": fullWidth
19
20
  }, className);
20
21
  return (_jsx("textarea", Object.assign({ ref: ref, className: classes, id: id, name: name, placeholder: placeholder, value: value, onChange: onChange }, rest)));
@@ -9,6 +9,10 @@
9
9
  padding: $sizeS;
10
10
  }
11
11
 
12
+ .vuiTextArea-isInvalid {
13
+ border-color: $colorDanger;
14
+ }
15
+
12
16
  .vuiTextArea--fullWidth {
13
17
  width: 100%;
14
18
  }
@@ -5,6 +5,11 @@ import { VuiSpacer } from "../spacer/Spacer";
5
5
  import { VuiText } from "../typography/Text";
6
6
  import { VuiTextColor } from "../typography/TextColor";
7
7
  import { createId } from "../../utils/createId";
8
+ import { VuiTextInput } from "../form/input/TextInput";
9
+ import { VuiNumberInput } from "../form/input/NumberInput";
10
+ import { VuiTextArea } from "../form/textArea/TextArea";
11
+ import { VuiSelect } from "../form/select/Select";
12
+ const VALIDATION_ALLOWLIST = [VuiTextInput, VuiNumberInput, VuiTextArea, VuiSelect];
8
13
  export const VuiFormGroup = ({ children, labelFor, helpText, label, errors, isRequired }) => {
9
14
  const ariaProps = {
10
15
  "aria-describedby": ""
@@ -22,6 +27,11 @@ export const VuiFormGroup = ({ children, labelFor, helpText, label, errors, isRe
22
27
  if (errorMessages === null || errorMessages === void 0 ? void 0 : errorMessages.length) {
23
28
  ariaProps["aria-describedby"] += " " + errorMessageIds.join(" ");
24
29
  }
25
- const content = cloneElement(children, Object.assign(Object.assign({}, ariaProps), { isInvalid: errors && errors.length > 0, id: labelFor, required: isRequired }));
30
+ const cloneProps = Object.assign(Object.assign({}, ariaProps), { id: labelFor, required: isRequired });
31
+ const canValidateChild = VALIDATION_ALLOWLIST.includes(children.type);
32
+ if (canValidateChild) {
33
+ cloneProps.isInvalid = errors && errors.length > 0;
34
+ }
35
+ const content = cloneElement(children, cloneProps);
26
36
  return (_jsxs("div", { children: [_jsxs(VuiLabel, Object.assign({ labelFor: labelFor }, { children: [label, isRequired && " (required)"] })), _jsx(VuiSpacer, { size: "xs" }), helpText && (_jsxs(_Fragment, { children: [_jsx(VuiText, Object.assign({ size: "xs", id: ariaDescribedByLabel }, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: helpText })) }) })), _jsx(VuiSpacer, { size: "xs" })] })), errorMessages && (_jsxs(_Fragment, { children: [errorMessages, _jsx(VuiSpacer, { size: "xs" })] })), content] }));
27
37
  };
@@ -33,5 +33,5 @@ export const VuiIcon = (_a) => {
33
33
  const icon = cloneElement(children, {
34
34
  size: sizeToValueMap[size]
35
35
  });
36
- return (_jsx(IconContext.Provider, Object.assign({ value: { className: innerClasses } }, { children: _jsx("div", Object.assign({ className: classes }, rest, { children: icon })) })));
36
+ return (_jsx(IconContext.Provider, Object.assign({ value: { className: innerClasses } }, { children: _jsx("span", Object.assign({ className: classes }, rest, { children: icon })) })));
37
37
  };
@@ -1,4 +1,5 @@
1
1
  .vuiIcon {
2
+ display: inline-block;
2
3
  // Remove extra space at bottom of icon.
3
4
  line-height: 0;
4
5
  }