@mitodl/smoot-design 1.0.1 → 1.1.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 (74) hide show
  1. package/README.md +14 -0
  2. package/dist/cjs/components/Button/ActionButton.d.ts +30 -0
  3. package/dist/cjs/components/Button/ActionButton.js +73 -0
  4. package/dist/cjs/components/Button/ActionButton.stories.d.ts +1 -4
  5. package/dist/cjs/components/Button/ActionButton.stories.js +22 -32
  6. package/dist/cjs/components/Button/Button.d.ts +13 -27
  7. package/dist/cjs/components/Button/Button.js +15 -60
  8. package/dist/cjs/components/Button/Button.stories.js +0 -30
  9. package/dist/cjs/components/Button/Button.test.js +7 -4
  10. package/dist/cjs/components/Input/Input.d.ts +115 -0
  11. package/dist/cjs/components/Input/Input.js +219 -0
  12. package/dist/cjs/components/Input/Input.stories.d.ts +19 -0
  13. package/dist/cjs/components/Input/Input.stories.js +134 -0
  14. package/dist/cjs/components/Input/Input.test.d.ts +1 -0
  15. package/dist/cjs/components/Input/Input.test.js +32 -0
  16. package/dist/cjs/components/LinkAdapter/LinkAdapter.js +1 -1
  17. package/dist/cjs/components/TextField/TextField.d.ts +29 -0
  18. package/dist/cjs/components/TextField/TextField.js +33 -0
  19. package/dist/cjs/components/TextField/TextField.stories.d.ts +10 -0
  20. package/dist/cjs/components/TextField/TextField.stories.js +135 -0
  21. package/dist/cjs/components/TextField/TextField.test.d.ts +1 -0
  22. package/dist/cjs/components/TextField/TextField.test.js +77 -0
  23. package/dist/cjs/components/ThemeProvider/ThemeProvider.js +0 -16
  24. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.js +1 -1
  25. package/dist/cjs/components/ThemeProvider/Typography.stories.d.ts +2 -0
  26. package/dist/cjs/components/ThemeProvider/Typography.stories.js +3 -1
  27. package/dist/cjs/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  28. package/dist/cjs/components/internal/FormHelpers/FormHelpers.js +78 -0
  29. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  30. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.js +93 -0
  31. package/dist/cjs/index.d.ts +4 -2
  32. package/dist/cjs/index.js +3 -2
  33. package/dist/cjs/jest-setup.d.ts +1 -0
  34. package/dist/cjs/jest-setup.js +2 -0
  35. package/dist/cjs/story-utils/index.d.ts +3 -20
  36. package/dist/cjs/story-utils/index.js +2 -22
  37. package/dist/esm/components/Button/ActionButton.d.ts +30 -0
  38. package/dist/esm/components/Button/ActionButton.js +68 -0
  39. package/dist/esm/components/Button/ActionButton.stories.d.ts +1 -4
  40. package/dist/esm/components/Button/ActionButton.stories.js +2 -12
  41. package/dist/esm/components/Button/Button.d.ts +13 -27
  42. package/dist/esm/components/Button/Button.js +12 -58
  43. package/dist/esm/components/Button/Button.stories.js +2 -32
  44. package/dist/esm/components/Button/Button.test.js +7 -4
  45. package/dist/esm/components/Input/Input.d.ts +115 -0
  46. package/dist/esm/components/Input/Input.js +214 -0
  47. package/dist/esm/components/Input/Input.stories.d.ts +19 -0
  48. package/dist/esm/components/Input/Input.stories.js +131 -0
  49. package/dist/esm/components/Input/Input.test.d.ts +1 -0
  50. package/dist/esm/components/Input/Input.test.js +30 -0
  51. package/dist/esm/components/LinkAdapter/LinkAdapter.js +1 -1
  52. package/dist/esm/components/TextField/TextField.d.ts +29 -0
  53. package/dist/esm/components/TextField/TextField.js +30 -0
  54. package/dist/esm/components/TextField/TextField.stories.d.ts +10 -0
  55. package/dist/esm/components/TextField/TextField.stories.js +132 -0
  56. package/dist/esm/components/TextField/TextField.test.d.ts +1 -0
  57. package/dist/esm/components/TextField/TextField.test.js +75 -0
  58. package/dist/esm/components/ThemeProvider/ThemeProvider.js +0 -16
  59. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.js +1 -1
  60. package/dist/esm/components/ThemeProvider/Typography.stories.d.ts +2 -0
  61. package/dist/esm/components/ThemeProvider/Typography.stories.js +3 -1
  62. package/dist/esm/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  63. package/dist/esm/components/internal/FormHelpers/FormHelpers.js +73 -0
  64. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  65. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.js +91 -0
  66. package/dist/esm/index.d.ts +4 -2
  67. package/dist/esm/index.js +2 -1
  68. package/dist/esm/jest-setup.d.ts +1 -0
  69. package/dist/esm/jest-setup.js +1 -1
  70. package/dist/esm/story-utils/index.d.ts +3 -20
  71. package/dist/esm/story-utils/index.js +2 -21
  72. package/dist/tsconfig.tsbuildinfo +1 -1
  73. package/dist/type-augmentation/theme.d.ts +0 -2
  74. package/package.json +5 -4
package/README.md CHANGED
@@ -11,3 +11,17 @@ To trigger a release, run the "Release" github action. Using [semantic-release](
11
11
  1. Inspect the commit history since previous release for [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) an
12
12
  2. Determine whether the version bump should be major, minor, or patch based on commit types. Breaking changes (e.g., `feat!: remove Button variant 'outlined'`) will result in major version bumps.
13
13
  3. Publish the package to NPM and the repository's [Github Releases](https://github.com/mitodl/smoot-design/releases).
14
+
15
+ ## Documentation
16
+
17
+ Documentation for `smoot-design` components is available at https://mitodl.github.io/smoot-design.
18
+
19
+ ### Storybook
20
+
21
+ Components in `smoot-design` are documented using Storybook's [autodocs](https://storybook.js.org/docs/writing-docs/autodocs) feature.
22
+
23
+ Autodocs _should_ infer props and comments from Typescript + JSDoc comments. However, autodocs can be a bit finnicky. Tips:
24
+
25
+ - **Filename should match Component Name:** If you're documenting `Button`, it must be exported from a file called `Button.tsx`.
26
+ - **Component `displayName`:** Some components may need an explicit `displayName`, this can be set by `Button.displayName="Button"`.
27
+ - _React component display names are not visible to end users; they are used in React's Dev Tools. React automatically adds display names for most components while transpiling, but autodocs uses un-transpiled code to generate documentation._
@@ -0,0 +1,30 @@
1
+ import * as React from "react";
2
+ import { DEFAULT_PROPS } from "./Button";
3
+ import type { ButtonStyleProps } from "./Button";
4
+ import type { LinkAdapterPropsOverrides } from "../LinkAdapter/LinkAdapter";
5
+ type ActionButtonStyleProps = Omit<ButtonStyleProps, "startIcon" | "endIcon">;
6
+ type ActionButtonProps = ActionButtonStyleProps & React.ComponentProps<"button">;
7
+ /**
8
+ * A button that should contain a remixicon icon and nothing else.
9
+ * See [ActionButton docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs).
10
+ *
11
+ * See also:
12
+ * - [ActionButtonLink](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
13
+ * - [Button](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs) for text buttons
14
+ */
15
+ declare const ActionButton: import("@emotion/styled").StyledComponent<Omit<ActionButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement> & {
16
+ theme?: import("@emotion/react").Theme;
17
+ }, {}, {}>;
18
+ type ActionButtonLinkProps = ActionButtonStyleProps & React.ComponentProps<"a"> & {
19
+ Component?: React.ElementType;
20
+ } & LinkAdapterPropsOverrides;
21
+ /**
22
+ * See [ActionButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
23
+ */
24
+ declare const ActionButtonLink: import("@emotion/styled").StyledComponent<Omit<ActionButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement> & {
25
+ theme?: import("@emotion/react").Theme;
26
+ } & ActionButtonStyleProps & React.ClassAttributes<HTMLAnchorElement> & React.AnchorHTMLAttributes<HTMLAnchorElement> & {
27
+ Component?: React.ElementType;
28
+ } & LinkAdapterPropsOverrides, {}, {}>;
29
+ export { ActionButton, ActionButtonLink, DEFAULT_PROPS };
30
+ export type { ActionButtonProps, ActionButtonLinkProps };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.DEFAULT_PROPS = exports.ActionButtonLink = exports.ActionButton = void 0;
15
+ const React = require("react");
16
+ const styled_1 = require("@emotion/styled");
17
+ const typography_1 = require("../ThemeProvider/typography");
18
+ const Button_1 = require("./Button");
19
+ Object.defineProperty(exports, "DEFAULT_PROPS", { enumerable: true, get: function () { return Button_1.DEFAULT_PROPS; } });
20
+ const actionStyles = (size) => {
21
+ return {
22
+ minWidth: "auto",
23
+ padding: 0,
24
+ height: {
25
+ small: "32px",
26
+ medium: "40px",
27
+ large: "48px",
28
+ }[size],
29
+ width: {
30
+ small: "32px",
31
+ medium: "40px",
32
+ large: "48px",
33
+ }[size],
34
+ "& svg, & .MuiSvgIcon-root": {
35
+ width: "1em",
36
+ height: "1em",
37
+ fontSize: (0, typography_1.pxToRem)({
38
+ small: 20,
39
+ medium: 24,
40
+ large: 32,
41
+ }[size]),
42
+ },
43
+ };
44
+ };
45
+ /**
46
+ * A button that should contain a remixicon icon and nothing else.
47
+ * See [ActionButton docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs).
48
+ *
49
+ * See also:
50
+ * - [ActionButtonLink](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
51
+ * - [Button](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs) for text buttons
52
+ */
53
+ const ActionButton = (0, styled_1.default)(React.forwardRef(function Root(props, ref) {
54
+ return React.createElement(Button_1.ButtonRoot, Object.assign({ ref: ref, type: "button" }, props));
55
+ }))(({ size = Button_1.DEFAULT_PROPS.size, responsive, theme }) => {
56
+ return [
57
+ actionStyles(size),
58
+ responsive && {
59
+ [theme.breakpoints.down("sm")]: actionStyles(Button_1.RESPONSIVE_SIZES[size]),
60
+ },
61
+ ];
62
+ });
63
+ exports.ActionButton = ActionButton;
64
+ ActionButton.displayName = "ActionButton";
65
+ /**
66
+ * See [ActionButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
67
+ */
68
+ const ActionButtonLink = ActionButton.withComponent((_a) => {
69
+ var { Component } = _a, props = __rest(_a, ["Component"]);
70
+ return React.createElement(Button_1.ButtonLinkRoot, Object.assign({ Component: Component }, props));
71
+ });
72
+ exports.ActionButtonLink = ActionButtonLink;
73
+ ActionButtonLink.displayName = "ActionButtonLink";
@@ -1,8 +1,5 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
- import { ActionButton } from "./Button";
3
- /**
4
- * A button that should contain a remixicon icon and nothing else.
5
- */
2
+ import { ActionButton } from "./ActionButton";
6
3
  declare const meta: Meta<typeof ActionButton>;
7
4
  export default meta;
8
5
  type Story = StoryObj<typeof ActionButton>;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Links = exports.Showcase = exports.VariantsAndEdge = void 0;
4
4
  const React = require("react");
5
- const Button_1 = require("./Button");
5
+ const ActionButton_1 = require("./ActionButton");
6
6
  const Grid2_1 = require("@mui/material/Grid2");
7
7
  const Stack_1 = require("@mui/material/Stack");
8
8
  const react_1 = require("@remixicon/react");
@@ -34,61 +34,51 @@ const EDGES = (0, story_utils_1.enumValues)({
34
34
  rounded: true,
35
35
  none: true,
36
36
  });
37
- /**
38
- * A button that should contain a remixicon icon and nothing else.
39
- */
40
37
  const meta = {
41
38
  title: "smoot-design/ActionButton",
42
- component: Button_1.ActionButton,
39
+ component: ActionButton_1.ActionButton,
43
40
  argTypes: {
44
41
  variant: {
45
- options: VARIANTS,
46
42
  control: { type: "select" },
47
43
  table: {
48
- type: { summary: (0, story_utils_1.docsEnum)(VARIANTS) },
49
- defaultValue: { summary: Button_1.DEFAULT_PROPS.variant },
44
+ defaultValue: { summary: ActionButton_1.DEFAULT_PROPS.variant },
50
45
  },
51
46
  },
52
47
  size: {
53
- options: SIZES,
54
48
  control: { type: "select" },
55
49
  table: {
56
- type: { summary: (0, story_utils_1.docsEnum)(SIZES) },
57
- defaultValue: { summary: Button_1.DEFAULT_PROPS.size },
50
+ defaultValue: { summary: ActionButton_1.DEFAULT_PROPS.size },
58
51
  },
59
52
  },
60
53
  edge: {
61
- options: EDGES,
62
54
  control: { type: "select" },
63
55
  table: {
64
- type: { summary: (0, story_utils_1.docsEnum)(EDGES) },
65
- defaultValue: { summary: Button_1.DEFAULT_PROPS.edge },
56
+ defaultValue: { summary: ActionButton_1.DEFAULT_PROPS.edge },
66
57
  },
67
58
  },
68
59
  },
69
60
  args: {
70
61
  onClick: (0, test_1.fn)(),
71
62
  },
72
- tags: ["autodocs"],
73
63
  };
74
64
  exports.default = meta;
75
65
  exports.VariantsAndEdge = {
76
66
  render: (args) => (React.createElement(React.Fragment, null,
77
67
  React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
78
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "primary" }), ICONS.DeleteIcon),
79
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "secondary" }), ICONS.DeleteIcon),
80
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "tertiary" }), ICONS.DeleteIcon),
81
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "text" }), ICONS.DeleteIcon)),
68
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "primary" }), ICONS.DeleteIcon),
69
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "secondary" }), ICONS.DeleteIcon),
70
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "tertiary" }), ICONS.DeleteIcon),
71
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "none", variant: "text" }), ICONS.DeleteIcon)),
82
72
  React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
83
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "primary" }), ICONS.DeleteIcon),
84
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "secondary" }), ICONS.DeleteIcon),
85
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "tertiary" }), ICONS.DeleteIcon),
86
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "text" }), ICONS.DeleteIcon)),
73
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "primary" }), ICONS.DeleteIcon),
74
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "secondary" }), ICONS.DeleteIcon),
75
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "tertiary" }), ICONS.DeleteIcon),
76
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "rounded", variant: "text" }), ICONS.DeleteIcon)),
87
77
  React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
88
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "primary" }), ICONS.DeleteIcon),
89
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "secondary" }), ICONS.DeleteIcon),
90
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "tertiary" }), ICONS.DeleteIcon),
91
- React.createElement(Button_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "text" }), ICONS.DeleteIcon)))),
78
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "primary" }), ICONS.DeleteIcon),
79
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "secondary" }), ICONS.DeleteIcon),
80
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "tertiary" }), ICONS.DeleteIcon),
81
+ React.createElement(ActionButton_1.ActionButton, Object.assign({}, args, { edge: "circular", variant: "text" }), ICONS.DeleteIcon)))),
92
82
  tags: ["main"],
93
83
  };
94
84
  exports.Showcase = {
@@ -103,7 +93,7 @@ exports.Showcase = {
103
93
  SIZES.flatMap((size) => Object.entries(ICONS)
104
94
  .filter(([_key, icon]) => icon)
105
95
  .map(([iconKey, icon]) => (React.createElement(Grid2_1.default, { size: { xs: 4, sm: 1 }, key: `${size}-${iconKey}` },
106
- React.createElement(Button_1.ActionButton, Object.assign({ variant: variant, edge: edge, size: size }, args), icon))))))))))),
96
+ React.createElement(ActionButton_1.ActionButton, Object.assign({ variant: variant, edge: edge, size: size }, args), icon))))))))))),
107
97
  };
108
98
  /**
109
99
  * `ActionButtonLink` is styled as a `ActionButton` that renders an anchor tag.
@@ -114,8 +104,8 @@ exports.Showcase = {
114
104
  */
115
105
  exports.Links = {
116
106
  render: () => (React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
117
- React.createElement(Button_1.ActionButtonLink, { href: "#fake", variant: "primary" }, ICONS.DeleteIcon),
118
- React.createElement(Button_1.ActionButtonLink, { href: "#fake", variant: "secondary" }, ICONS.DeleteIcon),
119
- React.createElement(Button_1.ActionButtonLink, { href: "#fake", variant: "tertiary" }, ICONS.DeleteIcon),
120
- React.createElement(Button_1.ActionButtonLink, { href: "#fake", variant: "text" }, ICONS.DeleteIcon))),
107
+ React.createElement(ActionButton_1.ActionButtonLink, { href: "#fake", variant: "primary" }, ICONS.DeleteIcon),
108
+ React.createElement(ActionButton_1.ActionButtonLink, { href: "#fake", variant: "secondary" }, ICONS.DeleteIcon),
109
+ React.createElement(ActionButton_1.ActionButtonLink, { href: "#fake", variant: "tertiary" }, ICONS.DeleteIcon),
110
+ React.createElement(ActionButton_1.ActionButtonLink, { href: "#fake", variant: "text" }, ICONS.DeleteIcon))),
121
111
  };
@@ -8,7 +8,7 @@ type ButtonStyleProps = {
8
8
  size?: ButtonSize;
9
9
  edge?: ButtonEdge;
10
10
  /**
11
- * Display an icon before the button text.
11
+ * Display an icon before the button text
12
12
  */
13
13
  startIcon?: React.ReactNode;
14
14
  /**
@@ -26,6 +26,16 @@ type ButtonStyleProps = {
26
26
  color?: "secondary";
27
27
  };
28
28
  declare const DEFAULT_PROPS: Required<Omit<ButtonStyleProps, "startIcon" | "endIcon" | "color">>;
29
+ declare const RESPONSIVE_SIZES: Record<ButtonSize, ButtonSize>;
30
+ declare const ButtonRoot: import("@emotion/styled").StyledComponent<{
31
+ theme?: import("@emotion/react").Theme;
32
+ as?: React.ElementType;
33
+ } & ButtonStyleProps, React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
34
+ declare const ButtonLinkRoot: import("@emotion/styled").StyledComponent<Omit<React.ClassAttributes<HTMLAnchorElement> & React.AnchorHTMLAttributes<HTMLAnchorElement> & {
35
+ Component?: React.ElementType;
36
+ } & LinkAdapterPropsOverrides, "ref"> & React.RefAttributes<HTMLAnchorElement> & {
37
+ theme?: import("@emotion/react").Theme;
38
+ } & ButtonStyleProps, {}, {}>;
29
39
  type ButtonProps = ButtonStyleProps & React.ComponentProps<"button">;
30
40
  /**
31
41
  * Our standard button component. See [Button Docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs).
@@ -42,29 +52,5 @@ type ButtonLinkProps = ButtonStyleProps & React.ComponentProps<"a"> & {
42
52
  * See [ButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs#links)
43
53
  */
44
54
  declare const ButtonLink: React.ForwardRefExoticComponent<Omit<ButtonLinkProps, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
45
- type ActionButtonStyleProps = Omit<ButtonStyleProps, "startIcon" | "endIcon">;
46
- type ActionButtonProps = ActionButtonStyleProps & React.ComponentProps<"button">;
47
- /**
48
- * A button that should contain a remixicon icon and nothing else.
49
- * See [ActionButton docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs).
50
- *
51
- * See also:
52
- * - [ActionButtonLink](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs#links)
53
- * - [Button](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs) for text buttons
54
- */
55
- declare const ActionButton: import("@emotion/styled").StyledComponent<Omit<ActionButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement> & {
56
- theme?: import("@emotion/react").Theme;
57
- }, {}, {}>;
58
- type ActionButtonLinkProps = ActionButtonStyleProps & React.ComponentProps<"a"> & {
59
- Component?: React.ElementType;
60
- } & LinkAdapterPropsOverrides;
61
- /**
62
- * See [ActionButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
63
- */
64
- declare const ActionButtonLink: import("@emotion/styled").StyledComponent<Omit<ActionButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement> & {
65
- theme?: import("@emotion/react").Theme;
66
- } & ButtonStyleProps & React.ClassAttributes<HTMLAnchorElement> & React.AnchorHTMLAttributes<HTMLAnchorElement> & {
67
- Component?: React.ElementType;
68
- } & LinkAdapterPropsOverrides, {}, {}>;
69
- export { Button, ButtonLink, ActionButton, ActionButtonLink, DEFAULT_PROPS };
70
- export type { ButtonProps, ButtonLinkProps, ActionButtonProps, ActionButtonLinkProps, };
55
+ export { Button, ButtonLink, ButtonRoot, DEFAULT_PROPS, ButtonLinkRoot, RESPONSIVE_SIZES, };
56
+ export type { ButtonProps, ButtonLinkProps, ButtonStyleProps, ButtonSize };
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.DEFAULT_PROPS = exports.ActionButtonLink = exports.ActionButton = exports.ButtonLink = exports.Button = void 0;
14
+ exports.RESPONSIVE_SIZES = exports.ButtonLinkRoot = exports.DEFAULT_PROPS = exports.ButtonRoot = exports.ButtonLink = exports.Button = void 0;
15
15
  const React = require("react");
16
16
  const styled_1 = require("@emotion/styled");
17
17
  const react_1 = require("@emotion/react");
@@ -26,7 +26,7 @@ const styleProps = {
26
26
  responsive: true,
27
27
  color: true,
28
28
  };
29
- const shouldForwardProp = (prop) => !styleProps[prop];
29
+ const shouldForwardButtonProp = (prop) => !styleProps[prop];
30
30
  const DEFAULT_PROPS = {
31
31
  variant: "primary",
32
32
  size: "medium",
@@ -44,6 +44,7 @@ const RESPONSIVE_SIZES = {
44
44
  medium: "small",
45
45
  large: "medium",
46
46
  };
47
+ exports.RESPONSIVE_SIZES = RESPONSIVE_SIZES;
47
48
  const sizeStyles = (size, hasBorder, theme) => {
48
49
  const paddingAdjust = hasBorder ? BORDER_WIDTHS[size] : 0;
49
50
  return [
@@ -56,7 +57,7 @@ const sizeStyles = (size, hasBorder, theme) => {
56
57
  size === "small" && Object.assign({ padding: `${8 - paddingAdjust}px 12px` }, theme.typography.buttonSmall),
57
58
  ];
58
59
  };
59
- const buildStyles = (props) => {
60
+ const buttonStyles = (props) => {
60
61
  const { size, variant, edge, theme, color, responsive } = Object.assign(Object.assign({}, DEFAULT_PROPS), props);
61
62
  const { colors } = theme.custom;
62
63
  const hasBorder = variant === "secondary";
@@ -193,10 +194,14 @@ const buildStyles = (props) => {
193
194
  },
194
195
  ]);
195
196
  };
196
- const ButtonStyled = (0, styled_1.default)("button", { shouldForwardProp })(buildStyles);
197
- const LinkStyled = (0, styled_1.default)(LinkAdapter_1.LinkAdapter, {
198
- shouldForwardProp,
199
- })(buildStyles);
197
+ const ButtonRoot = (0, styled_1.default)("button", {
198
+ shouldForwardProp: shouldForwardButtonProp,
199
+ })(buttonStyles);
200
+ exports.ButtonRoot = ButtonRoot;
201
+ const ButtonLinkRoot = (0, styled_1.default)(LinkAdapter_1.LinkAdapter, {
202
+ shouldForwardProp: shouldForwardButtonProp,
203
+ })(buttonStyles);
204
+ exports.ButtonLinkRoot = ButtonLinkRoot;
200
205
  const IconContainer = styled_1.default.span(({ size, side }) => [
201
206
  {
202
207
  height: "1em",
@@ -244,68 +249,18 @@ const ButtonInner = (props) => {
244
249
  */
245
250
  const Button = React.forwardRef((_a, ref) => {
246
251
  var { children } = _a, props = __rest(_a, ["children"]);
247
- return (React.createElement(ButtonStyled, Object.assign({ ref: ref, type: "button" }, props),
252
+ return (React.createElement(ButtonRoot, Object.assign({ ref: ref, type: "button" }, props),
248
253
  React.createElement(ButtonInner, Object.assign({}, props), children)));
249
254
  });
250
255
  exports.Button = Button;
256
+ Button.displayName = "Button";
251
257
  /**
252
258
  * See [ButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs#links)
253
259
  */
254
260
  const ButtonLink = React.forwardRef((_a, ref) => {
255
261
  var { children, Component } = _a, props = __rest(_a, ["children", "Component"]);
256
- return (React.createElement(LinkStyled, Object.assign({ Component: Component, ref: ref }, props),
262
+ return (React.createElement(ButtonLinkRoot, Object.assign({ Component: Component, ref: ref }, props),
257
263
  React.createElement(ButtonInner, Object.assign({}, props), children)));
258
264
  });
259
265
  exports.ButtonLink = ButtonLink;
260
266
  ButtonLink.displayName = "ButtonLink";
261
- const actionStyles = (size) => {
262
- return {
263
- minWidth: "auto",
264
- padding: 0,
265
- height: {
266
- small: "32px",
267
- medium: "40px",
268
- large: "48px",
269
- }[size],
270
- width: {
271
- small: "32px",
272
- medium: "40px",
273
- large: "48px",
274
- }[size],
275
- "& svg, & .MuiSvgIcon-root": {
276
- width: "1em",
277
- height: "1em",
278
- fontSize: (0, typography_1.pxToRem)({
279
- small: 20,
280
- medium: 24,
281
- large: 32,
282
- }[size]),
283
- },
284
- };
285
- };
286
- /**
287
- * A button that should contain a remixicon icon and nothing else.
288
- * See [ActionButton docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs).
289
- *
290
- * See also:
291
- * - [ActionButtonLink](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs#links)
292
- * - [Button](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-button--docs) for text buttons
293
- */
294
- const ActionButton = (0, styled_1.default)(React.forwardRef((props, ref) => (React.createElement(ButtonStyled, Object.assign({ ref: ref, type: "button" }, props)))))(({ size = DEFAULT_PROPS.size, responsive, theme }) => {
295
- return [
296
- actionStyles(size),
297
- responsive && {
298
- [theme.breakpoints.down("sm")]: actionStyles(RESPONSIVE_SIZES[size]),
299
- },
300
- ];
301
- });
302
- exports.ActionButton = ActionButton;
303
- /**
304
- * See [ActionButtonLink docs](https://mitodl.github.io/smoot-design/?path=/docs/smoot-design-actionbutton--docs#links)
305
- */
306
- const ActionButtonLink = ActionButton.withComponent((_a) => {
307
- var { Component } = _a, props = __rest(_a, ["Component"]);
308
- return React.createElement(LinkStyled, Object.assign({ Component: Component }, props));
309
- });
310
- exports.ActionButtonLink = ActionButtonLink;
311
- ActionButtonLink.displayName = "ActionButtonLink";
@@ -38,30 +38,6 @@ const meta = {
38
38
  title: "smoot-design/Button",
39
39
  component: Button_1.Button,
40
40
  argTypes: {
41
- variant: {
42
- options: VARIANTS,
43
- control: { type: "select" },
44
- table: {
45
- type: { summary: (0, story_utils_1.docsEnum)(VARIANTS) },
46
- defaultValue: { summary: Button_1.DEFAULT_PROPS.variant },
47
- },
48
- },
49
- size: {
50
- options: SIZES,
51
- control: { type: "select" },
52
- table: {
53
- type: { summary: (0, story_utils_1.docsEnum)(SIZES) },
54
- defaultValue: { summary: Button_1.DEFAULT_PROPS.size },
55
- },
56
- },
57
- edge: {
58
- options: ["circular", "rounded"],
59
- control: { type: "select" },
60
- table: {
61
- type: { summary: (0, story_utils_1.docsEnum)(EDGES) },
62
- defaultValue: { summary: Button_1.DEFAULT_PROPS.edge },
63
- },
64
- },
65
41
  startIcon: {
66
42
  options: Object.keys(ICONS),
67
43
  mapping: ICONS,
@@ -70,16 +46,10 @@ const meta = {
70
46
  options: Object.keys(ICONS),
71
47
  mapping: ICONS,
72
48
  },
73
- responsive: {
74
- table: {
75
- defaultValue: { summary: Button_1.DEFAULT_PROPS.responsive.toString() },
76
- },
77
- },
78
49
  },
79
50
  args: {
80
51
  onClick: (0, test_1.fn)(),
81
52
  },
82
- tags: ["autodocs"],
83
53
  };
84
54
  exports.default = meta;
85
55
  exports.VariantsAndEdge = {
@@ -4,17 +4,20 @@ const React = require("react");
4
4
  const react_1 = require("@testing-library/react");
5
5
  const ThemeProvider_1 = require("../ThemeProvider/ThemeProvider");
6
6
  const Button_1 = require("./Button");
7
+ const ActionButton_1 = require("./ActionButton");
7
8
  const withLinkOverride = (0, ThemeProvider_1.createTheme)({
8
9
  custom: {
9
- LinkAdapter: React.forwardRef((props, ref) => (
10
- // eslint-disable-next-line jsx-a11y/anchor-has-content
11
- React.createElement("a", Object.assign({ ref: ref, "data-custom": "theme-default" }, props)))),
10
+ LinkAdapter: React.forwardRef(function LinkAdapter(props, ref) {
11
+ return (
12
+ // eslint-disable-next-line jsx-a11y/anchor-has-content
13
+ React.createElement("a", Object.assign({ ref: ref, "data-custom": "theme-default" }, props)));
14
+ }),
12
15
  },
13
16
  });
14
17
  describe.each([
15
18
  //
16
19
  { ButtonComponent: Button_1.ButtonLink },
17
- { ButtonComponent: Button_1.ActionButtonLink },
20
+ { ButtonComponent: ActionButton_1.ActionButtonLink },
18
21
  ])("$ButtonComponent.displayName overrides", ({ ButtonComponent }) => {
19
22
  test("Uses anchor by default", () => {
20
23
  (0, react_1.render)(React.createElement(ButtonComponent, { href: "/test" }, "Link text here"), {
@@ -0,0 +1,115 @@
1
+ import * as React from "react";
2
+ import type { InputBaseProps } from "@mui/material/InputBase";
3
+ import type { Theme } from "@mui/material/styles";
4
+ type Size = "small" | "medium" | "large" | "hero";
5
+ type CustomInputProps = {
6
+ /**
7
+ * If true, the input will display one size smaller at mobile breakpoint.
8
+ */
9
+ responsive?: boolean;
10
+ };
11
+ type MuiDocOverride = {
12
+ size?: Size;
13
+ /**
14
+ * Slot for icon adornments.
15
+ *
16
+ * If the icon is a button, use `AdornmentButton` component.
17
+ */
18
+ startAdornment?: React.ReactNode;
19
+ /**
20
+ * Slot for icon adornments.
21
+ *
22
+ * If the icon is a button, use `AdornmentButton` component.
23
+ */
24
+ endAdornment?: React.ReactNode;
25
+ };
26
+ type InputProps = CustomInputProps & MuiDocOverride & Omit<InputBaseProps, "color" | keyof MuiDocOverride>;
27
+ /**
28
+ * Base styles for Input and Select components. Includes border, color, hover effects.
29
+ */
30
+ declare const baseInputStyles: (theme: Theme) => {
31
+ backgroundColor: string;
32
+ color: string;
33
+ borderColor: string;
34
+ borderWidth: string;
35
+ borderStyle: string;
36
+ borderRadius: string;
37
+ "&.Mui-disabled": {
38
+ backgroundColor: string;
39
+ };
40
+ "&:hover:not(.Mui-disabled):not(.Mui-focused)": {
41
+ borderColor: string;
42
+ };
43
+ "&.Mui-focused": {
44
+ /**
45
+ * When change border width, it affects either the elements outside of it or
46
+ * inside based on the border-box setting.
47
+ *
48
+ * Instead of changing the border width, we hide the border and change width
49
+ * using outline.
50
+ */
51
+ borderColor: string;
52
+ outline: string;
53
+ outlineOffset: string;
54
+ };
55
+ "&.Mui-error": {
56
+ borderColor: string;
57
+ outlineColor: string;
58
+ };
59
+ "& input::placeholder, textarea::placeholder": {
60
+ color: string;
61
+ opacity: number;
62
+ };
63
+ "& input:placeholder-shown, textarea:placeholder-shown": {
64
+ textOverflow: string;
65
+ };
66
+ "& textarea": {
67
+ paddingTop: string;
68
+ paddingBottom: string;
69
+ };
70
+ "&.MuiInputBase-adornedStart": {
71
+ paddingLeft: string;
72
+ input: {
73
+ paddingLeft: string;
74
+ };
75
+ };
76
+ "&.MuiInputBase-adornedEnd": {
77
+ paddingRight: string;
78
+ input: {
79
+ paddingRight: string;
80
+ };
81
+ };
82
+ };
83
+ /**
84
+ * Use `Input` for a visually unlabelled input field. If used, it should still
85
+ * have an accessible label, e.g., provided via `aria-label`.
86
+ * For a labeled input field, use `TextField`. instead.
87
+ *
88
+ * **Note:** This component is a styled version of MUI's `InputBase`. See
89
+ * MUI's documentation for full info.
90
+ *
91
+ * - [Smoot Design Input Documentation](https://mitodl.github.io/smoot-design/https://mitodl.github.io/smoot-design/)
92
+ * - [InputBase Documentation](https://mui.com/api/input-base/)
93
+ */
94
+ declare const Input: React.FC<InputProps>;
95
+ declare const AdornmentButtonStyled: import("@emotion/styled").StyledComponent<{
96
+ theme?: import("@emotion/react").Theme;
97
+ as?: React.ElementType;
98
+ }, React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
99
+ type AdornmentButtonProps = React.ComponentProps<typeof AdornmentButtonStyled>;
100
+ /**
101
+ * Button to be used with `startAdornment` and `endAdornment` props on Input and
102
+ * TextField components. AdornmentButton takes care of positioning and other
103
+ * styling concerns.
104
+ *
105
+ * NOTES:
106
+ * - It is generally expected that the content of the AdornmentButton is a
107
+ * Remix Icon component. https://remixicon.com/
108
+ * - By default, the AdornmentButton calls `preventDefault` on `mouseDown`
109
+ * events. This prevents the button from stealing focus from the input on
110
+ * click. The button is still focusable via keyboard events. You can override
111
+ * this behavior by passing your own `onMouseDown` handler.
112
+ */
113
+ declare const AdornmentButton: React.FC<AdornmentButtonProps>;
114
+ export { AdornmentButton, Input, baseInputStyles };
115
+ export type { InputProps, AdornmentButtonProps };