@mitodl/smoot-design 0.0.0-preview215f7ae3fa

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 (190) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +27 -0
  3. package/dist/bundles/aiChat.es.js +24812 -0
  4. package/dist/bundles/aiChat.umd.js +161 -0
  5. package/dist/cjs/ai.d.ts +2 -0
  6. package/dist/cjs/ai.js +5 -0
  7. package/dist/cjs/bundles/aiChat.d.ts +6 -0
  8. package/dist/cjs/bundles/aiChat.js +13 -0
  9. package/dist/cjs/components/AiChat/AiChat.d.ts +5 -0
  10. package/dist/cjs/components/AiChat/AiChat.js +150 -0
  11. package/dist/cjs/components/AiChat/AiChat.stories.d.ts +11 -0
  12. package/dist/cjs/components/AiChat/AiChat.stories.js +76 -0
  13. package/dist/cjs/components/AiChat/AiChat.test.d.ts +1 -0
  14. package/dist/cjs/components/AiChat/AiChat.test.js +130 -0
  15. package/dist/cjs/components/AiChat/story-utils.d.ts +3 -0
  16. package/dist/cjs/components/AiChat/story-utils.js +100 -0
  17. package/dist/cjs/components/AiChat/types.d.ts +45 -0
  18. package/dist/cjs/components/AiChat/types.js +3 -0
  19. package/dist/cjs/components/AiChat/utils.d.ts +9 -0
  20. package/dist/cjs/components/AiChat/utils.js +31 -0
  21. package/dist/cjs/components/Button/ActionButton.d.ts +30 -0
  22. package/dist/cjs/components/Button/ActionButton.js +73 -0
  23. package/dist/cjs/components/Button/ActionButton.stories.d.ts +15 -0
  24. package/dist/cjs/components/Button/ActionButton.stories.js +116 -0
  25. package/dist/cjs/components/Button/Button.d.ts +56 -0
  26. package/dist/cjs/components/Button/Button.js +273 -0
  27. package/dist/cjs/components/Button/Button.stories.d.ts +17 -0
  28. package/dist/cjs/components/Button/Button.stories.js +138 -0
  29. package/dist/cjs/components/Button/Button.test.d.ts +1 -0
  30. package/dist/cjs/components/Button/Button.test.js +46 -0
  31. package/dist/cjs/components/Input/Input.d.ts +115 -0
  32. package/dist/cjs/components/Input/Input.js +219 -0
  33. package/dist/cjs/components/Input/Input.stories.d.ts +19 -0
  34. package/dist/cjs/components/Input/Input.stories.js +134 -0
  35. package/dist/cjs/components/Input/Input.test.d.ts +1 -0
  36. package/dist/cjs/components/Input/Input.test.js +32 -0
  37. package/dist/cjs/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  38. package/dist/cjs/components/LinkAdapter/LinkAdapter.js +34 -0
  39. package/dist/cjs/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  40. package/dist/cjs/components/ScrollSnap/ScrollSnap.js +59 -0
  41. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  42. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.js +43 -0
  43. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  44. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.js +43 -0
  45. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  46. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.js +44 -0
  47. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  48. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.js +62 -0
  49. package/dist/cjs/components/TextField/TextField.d.ts +29 -0
  50. package/dist/cjs/components/TextField/TextField.js +33 -0
  51. package/dist/cjs/components/TextField/TextField.stories.d.ts +10 -0
  52. package/dist/cjs/components/TextField/TextField.stories.js +135 -0
  53. package/dist/cjs/components/TextField/TextField.test.d.ts +1 -0
  54. package/dist/cjs/components/TextField/TextField.test.js +77 -0
  55. package/dist/cjs/components/ThemeProvider/ThemeProvider.d.ts +23 -0
  56. package/dist/cjs/components/ThemeProvider/ThemeProvider.js +90 -0
  57. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.d.ts +58 -0
  58. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.js +97 -0
  59. package/dist/cjs/components/ThemeProvider/Typography.stories.d.ts +39 -0
  60. package/dist/cjs/components/ThemeProvider/Typography.stories.js +65 -0
  61. package/dist/cjs/components/ThemeProvider/breakpoints.d.ts +4 -0
  62. package/dist/cjs/components/ThemeProvider/breakpoints.js +20 -0
  63. package/dist/cjs/components/ThemeProvider/buttons.d.ts +7 -0
  64. package/dist/cjs/components/ThemeProvider/buttons.js +20 -0
  65. package/dist/cjs/components/ThemeProvider/chips.d.ts +3 -0
  66. package/dist/cjs/components/ThemeProvider/chips.js +154 -0
  67. package/dist/cjs/components/ThemeProvider/colors.d.ts +32 -0
  68. package/dist/cjs/components/ThemeProvider/colors.js +35 -0
  69. package/dist/cjs/components/ThemeProvider/typography.d.ts +18 -0
  70. package/dist/cjs/components/ThemeProvider/typography.js +174 -0
  71. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  72. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.js +33 -0
  73. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  74. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.js +13 -0
  75. package/dist/cjs/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  76. package/dist/cjs/components/internal/FormHelpers/FormHelpers.js +78 -0
  77. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  78. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.js +93 -0
  79. package/dist/cjs/index.d.ts +16 -0
  80. package/dist/cjs/index.js +28 -0
  81. package/dist/cjs/jest-setup.d.ts +1 -0
  82. package/dist/cjs/jest-setup.js +18 -0
  83. package/dist/cjs/jsdom-extended.d.ts +6 -0
  84. package/dist/cjs/jsdom-extended.js +14 -0
  85. package/dist/cjs/story-utils/index.d.ts +6 -0
  86. package/dist/cjs/story-utils/index.js +17 -0
  87. package/dist/cjs/utils/composeRefs.d.ts +7 -0
  88. package/dist/cjs/utils/composeRefs.js +20 -0
  89. package/dist/cjs/utils/composeRefs.test.d.ts +1 -0
  90. package/dist/cjs/utils/composeRefs.test.js +19 -0
  91. package/dist/cjs/utils/useDevCheckStable.d.ts +8 -0
  92. package/dist/cjs/utils/useDevCheckStable.js +29 -0
  93. package/dist/cjs/utils/useInterval.d.ts +7 -0
  94. package/dist/cjs/utils/useInterval.js +25 -0
  95. package/dist/esm/ai.d.ts +2 -0
  96. package/dist/esm/ai.js +1 -0
  97. package/dist/esm/bundles/aiChat.d.ts +6 -0
  98. package/dist/esm/bundles/aiChat.js +10 -0
  99. package/dist/esm/components/AiChat/AiChat.d.ts +5 -0
  100. package/dist/esm/components/AiChat/AiChat.js +147 -0
  101. package/dist/esm/components/AiChat/AiChat.stories.d.ts +11 -0
  102. package/dist/esm/components/AiChat/AiChat.stories.js +73 -0
  103. package/dist/esm/components/AiChat/AiChat.test.d.ts +1 -0
  104. package/dist/esm/components/AiChat/AiChat.test.js +128 -0
  105. package/dist/esm/components/AiChat/story-utils.d.ts +3 -0
  106. package/dist/esm/components/AiChat/story-utils.js +96 -0
  107. package/dist/esm/components/AiChat/types.d.ts +45 -0
  108. package/dist/esm/components/AiChat/types.js +2 -0
  109. package/dist/esm/components/AiChat/utils.d.ts +9 -0
  110. package/dist/esm/components/AiChat/utils.js +28 -0
  111. package/dist/esm/components/Button/ActionButton.d.ts +30 -0
  112. package/dist/esm/components/Button/ActionButton.js +68 -0
  113. package/dist/esm/components/Button/ActionButton.stories.d.ts +15 -0
  114. package/dist/esm/components/Button/ActionButton.stories.js +113 -0
  115. package/dist/esm/components/Button/Button.d.ts +56 -0
  116. package/dist/esm/components/Button/Button.js +265 -0
  117. package/dist/esm/components/Button/Button.stories.d.ts +17 -0
  118. package/dist/esm/components/Button/Button.stories.js +135 -0
  119. package/dist/esm/components/Button/Button.test.d.ts +1 -0
  120. package/dist/esm/components/Button/Button.test.js +44 -0
  121. package/dist/esm/components/Input/Input.d.ts +115 -0
  122. package/dist/esm/components/Input/Input.js +214 -0
  123. package/dist/esm/components/Input/Input.stories.d.ts +19 -0
  124. package/dist/esm/components/Input/Input.stories.js +131 -0
  125. package/dist/esm/components/Input/Input.test.d.ts +1 -0
  126. package/dist/esm/components/Input/Input.test.js +30 -0
  127. package/dist/esm/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  128. package/dist/esm/components/LinkAdapter/LinkAdapter.js +31 -0
  129. package/dist/esm/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  130. package/dist/esm/components/ScrollSnap/ScrollSnap.js +56 -0
  131. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  132. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.js +40 -0
  133. package/dist/esm/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  134. package/dist/esm/components/SrAnnouncer/SrAnnouncer.js +40 -0
  135. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  136. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.js +41 -0
  137. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  138. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.js +60 -0
  139. package/dist/esm/components/TextField/TextField.d.ts +29 -0
  140. package/dist/esm/components/TextField/TextField.js +30 -0
  141. package/dist/esm/components/TextField/TextField.stories.d.ts +10 -0
  142. package/dist/esm/components/TextField/TextField.stories.js +132 -0
  143. package/dist/esm/components/TextField/TextField.test.d.ts +1 -0
  144. package/dist/esm/components/TextField/TextField.test.js +75 -0
  145. package/dist/esm/components/ThemeProvider/ThemeProvider.d.ts +23 -0
  146. package/dist/esm/components/ThemeProvider/ThemeProvider.js +86 -0
  147. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.d.ts +58 -0
  148. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.js +94 -0
  149. package/dist/esm/components/ThemeProvider/Typography.stories.d.ts +39 -0
  150. package/dist/esm/components/ThemeProvider/Typography.stories.js +62 -0
  151. package/dist/esm/components/ThemeProvider/breakpoints.d.ts +4 -0
  152. package/dist/esm/components/ThemeProvider/breakpoints.js +16 -0
  153. package/dist/esm/components/ThemeProvider/buttons.d.ts +7 -0
  154. package/dist/esm/components/ThemeProvider/buttons.js +17 -0
  155. package/dist/esm/components/ThemeProvider/chips.d.ts +3 -0
  156. package/dist/esm/components/ThemeProvider/chips.js +151 -0
  157. package/dist/esm/components/ThemeProvider/colors.d.ts +32 -0
  158. package/dist/esm/components/ThemeProvider/colors.js +32 -0
  159. package/dist/esm/components/ThemeProvider/typography.d.ts +18 -0
  160. package/dist/esm/components/ThemeProvider/typography.js +168 -0
  161. package/dist/esm/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  162. package/dist/esm/components/VisuallyHidden/VisuallyHidden.js +30 -0
  163. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  164. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.js +10 -0
  165. package/dist/esm/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  166. package/dist/esm/components/internal/FormHelpers/FormHelpers.js +73 -0
  167. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  168. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.js +91 -0
  169. package/dist/esm/index.d.ts +16 -0
  170. package/dist/esm/index.js +11 -0
  171. package/dist/esm/jest-setup.d.ts +1 -0
  172. package/dist/esm/jest-setup.js +16 -0
  173. package/dist/esm/jsdom-extended.d.ts +6 -0
  174. package/dist/esm/jsdom-extended.js +12 -0
  175. package/dist/esm/story-utils/index.d.ts +6 -0
  176. package/dist/esm/story-utils/index.js +13 -0
  177. package/dist/esm/utils/composeRefs.d.ts +7 -0
  178. package/dist/esm/utils/composeRefs.js +17 -0
  179. package/dist/esm/utils/composeRefs.test.d.ts +1 -0
  180. package/dist/esm/utils/composeRefs.test.js +17 -0
  181. package/dist/esm/utils/useDevCheckStable.d.ts +8 -0
  182. package/dist/esm/utils/useDevCheckStable.js +26 -0
  183. package/dist/esm/utils/useInterval.d.ts +7 -0
  184. package/dist/esm/utils/useInterval.js +22 -0
  185. package/dist/tsconfig.tsbuildinfo +1 -0
  186. package/dist/type-augmentation/TypescriptDocs.mdx +17 -0
  187. package/dist/type-augmentation/index.d.ts +2 -0
  188. package/dist/type-augmentation/theme.d.ts +103 -0
  189. package/dist/type-augmentation/typography.d.ts +54 -0
  190. package/package.json +141 -0
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Showcase = exports.Links = exports.WithIcons = exports.Sizes = exports.VariantsAndEdge = void 0;
4
+ const React = require("react");
5
+ const Button_1 = require("./Button");
6
+ const Grid2_1 = require("@mui/material/Grid2");
7
+ const Stack_1 = require("@mui/material/Stack");
8
+ const react_1 = require("@remixicon/react");
9
+ const test_1 = require("@storybook/test");
10
+ const story_utils_1 = require("../../story-utils");
11
+ const ICONS = {
12
+ None: undefined,
13
+ ArrowBackIcon: React.createElement(react_1.RiArrowLeftLine, null),
14
+ DeleteIcon: React.createElement(react_1.RiDeleteBinLine, null),
15
+ TestTubeIcon: React.createElement(react_1.RiTestTubeLine, null),
16
+ };
17
+ const VARIANTS = (0, story_utils_1.enumValues)({
18
+ primary: true,
19
+ secondary: true,
20
+ tertiary: true,
21
+ bordered: true,
22
+ text: true,
23
+ unstable_noBorder: true,
24
+ unstable_inverted: true,
25
+ unstable_success: true,
26
+ });
27
+ const STABLE_VARIANTS = VARIANTS.filter((v) => !v.startsWith("unstable"));
28
+ const SIZES = (0, story_utils_1.enumValues)({
29
+ small: true,
30
+ medium: true,
31
+ large: true,
32
+ });
33
+ const EDGES = (0, story_utils_1.enumValues)({
34
+ circular: true,
35
+ rounded: true,
36
+ none: true,
37
+ });
38
+ const meta = {
39
+ title: "smoot-design/Button",
40
+ component: Button_1.Button,
41
+ argTypes: {
42
+ startIcon: {
43
+ options: Object.keys(ICONS),
44
+ mapping: ICONS,
45
+ },
46
+ endIcon: {
47
+ options: Object.keys(ICONS),
48
+ mapping: ICONS,
49
+ },
50
+ },
51
+ args: {
52
+ onClick: (0, test_1.fn)(),
53
+ },
54
+ };
55
+ exports.default = meta;
56
+ exports.VariantsAndEdge = {
57
+ render: (args) => (React.createElement(React.Fragment, null,
58
+ React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
59
+ React.createElement(Button_1.Button, Object.assign({ edge: "none", variant: "primary" }, args), "Primary"),
60
+ React.createElement(Button_1.Button, Object.assign({ edge: "none", variant: "secondary" }, args), "Secondary"),
61
+ React.createElement(Button_1.Button, Object.assign({ edge: "none", variant: "tertiary" }, args), "Tertiary"),
62
+ React.createElement(Button_1.Button, Object.assign({ edge: "none", variant: "bordered" }, args), "Bordered"),
63
+ React.createElement(Button_1.Button, Object.assign({ edge: "none", variant: "text" }, args), "Text")),
64
+ React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
65
+ React.createElement(Button_1.Button, Object.assign({ edge: "rounded", variant: "primary" }, args), "Primary"),
66
+ React.createElement(Button_1.Button, Object.assign({ edge: "rounded", variant: "secondary" }, args), "Secondary"),
67
+ React.createElement(Button_1.Button, Object.assign({ edge: "rounded", variant: "tertiary" }, args), "Tertiary"),
68
+ React.createElement(Button_1.Button, Object.assign({ edge: "rounded", variant: "bordered" }, args), "Bordered"),
69
+ React.createElement(Button_1.Button, Object.assign({ edge: "rounded", variant: "text" }, args), "Text")),
70
+ React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
71
+ React.createElement(Button_1.Button, Object.assign({ edge: "circular", variant: "primary" }, args), "Primary"),
72
+ React.createElement(Button_1.Button, Object.assign({ edge: "circular", variant: "secondary" }, args), "Secondary"),
73
+ React.createElement(Button_1.Button, Object.assign({ edge: "circular", variant: "tertiary" }, args), "Tertiary"),
74
+ React.createElement(Button_1.Button, Object.assign({ edge: "circular", variant: "bordered" }, args), "Bordered"),
75
+ React.createElement(Button_1.Button, Object.assign({ edge: "circular", variant: "text" }, args), "Text")))),
76
+ tags: ["main"],
77
+ };
78
+ const RESPONSIVE = [true, false];
79
+ exports.Sizes = {
80
+ argTypes: {
81
+ size: { table: { disable: true } },
82
+ },
83
+ render: (args) => (React.createElement(Grid2_1.default, { container: true, sx: { my: 2, maxWidth: "600px" }, alignItems: "center" }, RESPONSIVE.flatMap((responsive) => {
84
+ return (React.createElement(React.Fragment, { key: String(responsive) },
85
+ React.createElement(Grid2_1.default, { size: { xs: 12 } },
86
+ React.createElement("code", null, `responsive={${responsive.toString()}}`)),
87
+ SIZES.map((size) => (React.createElement(Grid2_1.default, { size: { xs: 4 }, gap: 2, display: "flex", alignItems: "center", key: size },
88
+ React.createElement(Button_1.Button, Object.assign({}, args, { size: size, responsive: responsive }), size))))));
89
+ }))),
90
+ };
91
+ exports.WithIcons = {
92
+ render: (args) => (React.createElement(Stack_1.default, { direction: "column", alignItems: "start", gap: 2, sx: { my: 2 } }, Object.entries(ICONS).map(([key, icon]) => (React.createElement(Button_1.Button, Object.assign({}, args, { startIcon: icon, key: key }), key))))),
93
+ };
94
+ const EXTRA_PROPS = [
95
+ {},
96
+ /**
97
+ * Show RiTestTubeLine because it is a fairly thin icon
98
+ */
99
+ { startIcon: React.createElement(react_1.RiTestTubeLine, null) },
100
+ /**
101
+ * Show RiTestTubeLine because it is a fairly thick icon
102
+ */
103
+ { startIcon: React.createElement(react_1.RiMailLine, null) },
104
+ { endIcon: React.createElement(react_1.RiTestTubeLine, null) },
105
+ { endIcon: React.createElement(react_1.RiMailLine, null) },
106
+ ];
107
+ /**
108
+ * `ButtonLink` is a styled `Button` that renders an anchor tag.
109
+ *
110
+ * To use a custom link component (E.g. `Link` from `react-router` or `next/link`),
111
+ * pass it as the `Component` prop. Alternatively, customize the project-wide
112
+ * default link adapter via [Theme's LinkAdapter](../?path=/docs/smoot-design-themeprovider--docs)
113
+ */
114
+ exports.Links = {
115
+ render: () => (React.createElement(Stack_1.default, { direction: "row", gap: 2, sx: { my: 2 } },
116
+ React.createElement(Button_1.ButtonLink, { href: "#fake", variant: "primary" }, "Link"),
117
+ React.createElement(Button_1.ButtonLink, { href: "#fake", variant: "secondary" }, "Link"),
118
+ React.createElement(Button_1.ButtonLink, { href: "#fake", variant: "tertiary" }, "Link"),
119
+ React.createElement(Button_1.ButtonLink, { href: "#fake", variant: "bordered" }, "Link"),
120
+ React.createElement(Button_1.ButtonLink, { href: "#fake", variant: "text" }, "Link"))),
121
+ };
122
+ exports.Showcase = {
123
+ render: (args) => (React.createElement(Grid2_1.default, { container: true, rowGap: 2, sx: { maxWidth: "600px" } }, STABLE_VARIANTS.flatMap((variant) => EDGES.flatMap((edge) => EXTRA_PROPS.map((extraProps, i) => {
124
+ return (React.createElement(React.Fragment, { key: `${variant}-${edge}-${i}` },
125
+ React.createElement(Grid2_1.default, { size: { xs: 3 } },
126
+ React.createElement("pre", null,
127
+ "variant=",
128
+ variant,
129
+ React.createElement("br", null),
130
+ "edge=",
131
+ edge)),
132
+ SIZES.map((size) => (React.createElement(Grid2_1.default, { size: { xs: 3 }, display: "flex", alignItems: "center", key: `${size}` },
133
+ React.createElement(Button_1.Button, Object.assign({}, args, { variant: variant, edge: edge, size: size }, extraProps), args.children))))));
134
+ }))))),
135
+ args: {
136
+ children: "Click me",
137
+ },
138
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const React = require("react");
4
+ const react_1 = require("@testing-library/react");
5
+ const ThemeProvider_1 = require("../ThemeProvider/ThemeProvider");
6
+ const Button_1 = require("./Button");
7
+ const ActionButton_1 = require("./ActionButton");
8
+ const withLinkOverride = (0, ThemeProvider_1.createTheme)({
9
+ custom: {
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
+ }),
15
+ },
16
+ });
17
+ describe.each([
18
+ //
19
+ { ButtonComponent: Button_1.ButtonLink },
20
+ { ButtonComponent: ActionButton_1.ActionButtonLink },
21
+ ])("$ButtonComponent.displayName overrides", ({ ButtonComponent }) => {
22
+ test("Uses anchor by default", () => {
23
+ (0, react_1.render)(React.createElement(ButtonComponent, { href: "/test" }, "Link text here"), {
24
+ wrapper: ThemeProvider_1.ThemeProvider,
25
+ });
26
+ const link = react_1.screen.getByRole("link");
27
+ expect(link.dataset.custom).toBe(undefined);
28
+ });
29
+ test("Uses theme's override if supplied", () => {
30
+ (0, react_1.render)(React.createElement(ButtonComponent, { href: "/test" }, "Link text here"), {
31
+ wrapper: (props) => React.createElement(ThemeProvider_1.ThemeProvider, Object.assign({ theme: withLinkOverride }, props)),
32
+ });
33
+ const link = react_1.screen.getByRole("link");
34
+ expect(link.dataset.custom).toBe("theme-default");
35
+ });
36
+ test("Uses component's override if supplied", () => {
37
+ const LinkImplementation = (props) => (
38
+ // eslint-disable-next-line jsx-a11y/anchor-has-content
39
+ React.createElement("a", Object.assign({ "data-custom": "anchor-override" }, props)));
40
+ (0, react_1.render)(React.createElement(ButtonComponent, { Component: LinkImplementation, href: "/test" }, "Link text here"), {
41
+ wrapper: (props) => (React.createElement(ThemeProvider_1.ThemeProvider, Object.assign({ theme: withLinkOverride }, props))),
42
+ });
43
+ const link = react_1.screen.getByRole("link");
44
+ expect(link.dataset.custom).toBe("anchor-override");
45
+ });
46
+ });
@@ -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 };
@@ -0,0 +1,219 @@
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.baseInputStyles = exports.Input = exports.AdornmentButton = void 0;
15
+ const React = require("react");
16
+ const styled_1 = require("@emotion/styled");
17
+ const react_1 = require("@emotion/react");
18
+ const InputBase_1 = require("@mui/material/InputBase");
19
+ const classnames_1 = require("classnames");
20
+ const defaultProps = {
21
+ size: "medium",
22
+ multiline: false,
23
+ };
24
+ const responsiveSize = {
25
+ small: "small",
26
+ medium: "small",
27
+ large: "medium",
28
+ hero: "large",
29
+ };
30
+ const sizeStyles = ({ size, theme, multiline }) => (0, react_1.css)([
31
+ (size === "small" || size === "medium") && Object.assign({}, theme.typography.body2),
32
+ (size === "large" || size === "hero") && Object.assign({ ".remixicon": {
33
+ width: "24px",
34
+ height: "24px",
35
+ } }, theme.typography.body1),
36
+ size === "medium" && {
37
+ paddingLeft: "12px",
38
+ paddingRight: "12px",
39
+ },
40
+ size === "small" &&
41
+ !multiline && {
42
+ height: "32px",
43
+ },
44
+ size === "medium" &&
45
+ !multiline && {
46
+ height: "40px",
47
+ },
48
+ size === "large" &&
49
+ !multiline && {
50
+ height: "48px",
51
+ },
52
+ size === "hero" &&
53
+ !multiline && {
54
+ height: "72px",
55
+ },
56
+ size === "small" && {
57
+ padding: "0 8px",
58
+ ".Mit-AdornmentButton": {
59
+ width: "32px",
60
+ ".remixicon": {
61
+ width: "16px",
62
+ height: "16px",
63
+ },
64
+ },
65
+ },
66
+ size === "medium" && {
67
+ padding: "0 12px",
68
+ ".Mit-AdornmentButton": {
69
+ width: "40px",
70
+ ".remixicon": {
71
+ width: "20px",
72
+ height: "20px",
73
+ },
74
+ },
75
+ },
76
+ size === "large" && {
77
+ padding: "0 16px",
78
+ ".Mit-AdornmentButton": {
79
+ width: "48px",
80
+ },
81
+ },
82
+ size === "hero" && {
83
+ padding: "0 24px",
84
+ ".Mit-AdornmentButton": {
85
+ width: "72px",
86
+ },
87
+ },
88
+ ]);
89
+ /**
90
+ * Base styles for Input and Select components. Includes border, color, hover effects.
91
+ */
92
+ const baseInputStyles = (theme) => ({
93
+ backgroundColor: "white",
94
+ color: theme.custom.colors.darkGray2,
95
+ borderColor: theme.custom.colors.silverGrayLight,
96
+ borderWidth: "1px",
97
+ borderStyle: "solid",
98
+ borderRadius: "4px",
99
+ "&.Mui-disabled": {
100
+ backgroundColor: theme.custom.colors.lightGray1,
101
+ },
102
+ "&:hover:not(.Mui-disabled):not(.Mui-focused)": {
103
+ borderColor: theme.custom.colors.darkGray2,
104
+ },
105
+ "&.Mui-focused": {
106
+ /**
107
+ * When change border width, it affects either the elements outside of it or
108
+ * inside based on the border-box setting.
109
+ *
110
+ * Instead of changing the border width, we hide the border and change width
111
+ * using outline.
112
+ */
113
+ borderColor: "transparent",
114
+ outline: "2px solid currentcolor",
115
+ outlineOffset: "-2px",
116
+ },
117
+ "&.Mui-error": {
118
+ borderColor: theme.custom.colors.red,
119
+ outlineColor: theme.custom.colors.red,
120
+ },
121
+ "& input::placeholder, textarea::placeholder": {
122
+ color: theme.custom.colors.silverGrayDark,
123
+ opacity: 1, // some browsers apply opacity to placeholder text
124
+ },
125
+ "& input:placeholder-shown, textarea:placeholder-shown": {
126
+ textOverflow: "ellipsis",
127
+ },
128
+ "& textarea": {
129
+ paddingTop: "8px",
130
+ paddingBottom: "8px",
131
+ },
132
+ "&.MuiInputBase-adornedStart": {
133
+ paddingLeft: "0",
134
+ input: {
135
+ paddingLeft: "8px",
136
+ },
137
+ },
138
+ "&.MuiInputBase-adornedEnd": {
139
+ paddingRight: "0",
140
+ input: {
141
+ paddingRight: "8px",
142
+ },
143
+ },
144
+ });
145
+ exports.baseInputStyles = baseInputStyles;
146
+ const noForward = Object.keys({
147
+ responsive: true,
148
+ });
149
+ /**
150
+ * Use `Input` for a visually unlabelled input field. If used, it should still
151
+ * have an accessible label, e.g., provided via `aria-label`.
152
+ * For a labeled input field, use `TextField`. instead.
153
+ *
154
+ * **Note:** This component is a styled version of MUI's `InputBase`. See
155
+ * MUI's documentation for full info.
156
+ *
157
+ * - [Smoot Design Input Documentation](https://mitodl.github.io/smoot-design/https://mitodl.github.io/smoot-design/)
158
+ * - [InputBase Documentation](https://mui.com/api/input-base/)
159
+ */
160
+ const Input = (0, styled_1.default)(InputBase_1.default, {
161
+ shouldForwardProp: (prop) => !noForward.includes(prop),
162
+ })(({ theme, size = defaultProps.size, multiline, responsive }) => [
163
+ baseInputStyles(theme),
164
+ sizeStyles({ size, theme, multiline }),
165
+ responsive && {
166
+ [theme.breakpoints.down("sm")]: sizeStyles({
167
+ size: responsiveSize[size],
168
+ theme,
169
+ multiline,
170
+ }),
171
+ },
172
+ ]);
173
+ exports.Input = Input;
174
+ const AdornmentButtonStyled = styled_1.default.button(({ theme }) => (Object.assign(Object.assign({}, theme.typography.button), {
175
+ // display
176
+ display: "flex", flexShrink: 0, justifyContent: "center", alignItems: "center",
177
+ // background and border
178
+ border: "none", background: "transparent", transition: `background ${theme.transitions.duration.short}ms`,
179
+ // cursor
180
+ cursor: "pointer", ":disabled": {
181
+ cursor: "default",
182
+ }, ":hover": {
183
+ background: "rgba(0, 0, 0, 0.06)",
184
+ }, color: theme.custom.colors.silverGray, ".MuiInputBase-root:hover &": {
185
+ color: "inherit",
186
+ }, ".MuiInputBase-root.Mui-focused &": {
187
+ color: "inherit",
188
+ }, ".MuiInputBase-root.Mui-disabled &": {
189
+ color: "inherit",
190
+ }, height: "100%" })));
191
+ const noFocus = (e) => e.preventDefault();
192
+ /**
193
+ * Button to be used with `startAdornment` and `endAdornment` props on Input and
194
+ * TextField components. AdornmentButton takes care of positioning and other
195
+ * styling concerns.
196
+ *
197
+ * NOTES:
198
+ * - It is generally expected that the content of the AdornmentButton is a
199
+ * Remix Icon component. https://remixicon.com/
200
+ * - By default, the AdornmentButton calls `preventDefault` on `mouseDown`
201
+ * events. This prevents the button from stealing focus from the input on
202
+ * click. The button is still focusable via keyboard events. You can override
203
+ * this behavior by passing your own `onMouseDown` handler.
204
+ */
205
+ const AdornmentButton = (_a) => {
206
+ var { className } = _a, others = __rest(_a, ["className"]);
207
+ return (React.createElement(AdornmentButtonStyled
208
+ /**
209
+ * If the input is focused and user clicks the AdornmentButton, we don't
210
+ * want to steal focus from the input.
211
+ */
212
+ , Object.assign({
213
+ /**
214
+ * If the input is focused and user clicks the AdornmentButton, we don't
215
+ * want to steal focus from the input.
216
+ */
217
+ onMouseDown: noFocus, className: (0, classnames_1.default)("Mit-AdornmentButton", className) }, others)));
218
+ };
219
+ exports.AdornmentButton = AdornmentButton;
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Input } from "./Input";
3
+ declare const meta: Meta<typeof Input>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Input>;
6
+ export declare const Sizes: Story;
7
+ /**
8
+ * **Note:** Adornments should be wrapped in an `AdornmentButton` component.
9
+ *
10
+ * ```tsx
11
+ * <Input startAdornment={
12
+ * <AdornmentButton>
13
+ * <RiSearchLine />
14
+ * </AdornmentButton>
15
+ * } {...otherProps} />
16
+ * ```
17
+ */
18
+ export declare const Adornments: Story;
19
+ export declare const States: Story;
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.States = exports.Adornments = exports.Sizes = void 0;
4
+ const React = require("react");
5
+ const Input_1 = require("./Input");
6
+ const Stack_1 = require("@mui/material/Stack");
7
+ const Grid2_1 = require("@mui/material/Grid2");
8
+ const react_1 = require("@remixicon/react");
9
+ const test_1 = require("@storybook/test");
10
+ const story_utils_1 = require("../../story-utils");
11
+ const Typography_1 = require("@mui/material/Typography");
12
+ const SIZES = (0, story_utils_1.enumValues)({
13
+ small: true,
14
+ medium: true,
15
+ large: true,
16
+ hero: true,
17
+ });
18
+ const ADORNMENTS = {
19
+ None: undefined,
20
+ SearchIcon: (React.createElement(Input_1.AdornmentButton, null,
21
+ React.createElement(react_1.RiSearchLine, null))),
22
+ CalendarTodayIcon: (React.createElement(Input_1.AdornmentButton, null,
23
+ React.createElement(react_1.RiCalendarLine, null))),
24
+ CloseIcon: (React.createElement(Input_1.AdornmentButton, null,
25
+ React.createElement(react_1.RiCloseLine, null))),
26
+ "Close and Calendar": (React.createElement(React.Fragment, null,
27
+ React.createElement(Input_1.AdornmentButton, null,
28
+ React.createElement(react_1.RiCloseLine, null)),
29
+ React.createElement(Input_1.AdornmentButton, null,
30
+ React.createElement(react_1.RiCalendarLine, null)))),
31
+ };
32
+ const meta = {
33
+ title: "smoot-design/Input",
34
+ component: Input_1.Input,
35
+ argTypes: {
36
+ startAdornment: {
37
+ options: Object.keys(ADORNMENTS),
38
+ mapping: ADORNMENTS,
39
+ control: { type: "select" },
40
+ },
41
+ endAdornment: {
42
+ options: Object.keys(ADORNMENTS),
43
+ mapping: ADORNMENTS,
44
+ control: { type: "select" },
45
+ },
46
+ },
47
+ args: {
48
+ onChange: (0, test_1.fn)(),
49
+ value: "some value",
50
+ placeholder: "placeholder",
51
+ },
52
+ };
53
+ exports.default = meta;
54
+ exports.Sizes = {
55
+ render: (args) => {
56
+ return (React.createElement(Stack_1.default, { direction: "row", gap: 1 },
57
+ React.createElement(Input_1.Input, Object.assign({ size: "small" }, args)),
58
+ React.createElement(Input_1.Input, Object.assign({ size: "medium" }, args)),
59
+ React.createElement(Input_1.Input, Object.assign({ size: "large" }, args)),
60
+ React.createElement(Input_1.Input, Object.assign({ size: "hero" }, args))));
61
+ },
62
+ };
63
+ /**
64
+ * **Note:** Adornments should be wrapped in an `AdornmentButton` component.
65
+ *
66
+ * ```tsx
67
+ * <Input startAdornment={
68
+ * <AdornmentButton>
69
+ * <RiSearchLine />
70
+ * </AdornmentButton>
71
+ * } {...otherProps} />
72
+ * ```
73
+ */
74
+ exports.Adornments = {
75
+ render: (args) => {
76
+ const adornments = [
77
+ { startAdornment: ADORNMENTS.SearchIcon },
78
+ { endAdornment: ADORNMENTS.CloseIcon },
79
+ {
80
+ startAdornment: ADORNMENTS.SearchIcon,
81
+ endAdornment: ADORNMENTS["Close and Calendar"],
82
+ },
83
+ ];
84
+ return (React.createElement(Grid2_1.default, { container: true, maxWidth: "1400px", spacing: 2 }, Object.values(adornments).flatMap((props, i) => SIZES.map((size) => {
85
+ return (React.createElement(Grid2_1.default, { size: { xs: 3 }, key: `${i}-${size}` },
86
+ React.createElement(Input_1.Input, Object.assign({}, args, { size: size }, props))));
87
+ }))));
88
+ },
89
+ argTypes: {
90
+ startAdornment: { table: { disable: true } },
91
+ endAdornment: { table: { disable: true } },
92
+ },
93
+ };
94
+ exports.States = {
95
+ render: (args) => {
96
+ return (React.createElement(Grid2_1.default, { container: true, spacing: 2, alignItems: "center", maxWidth: "400px" },
97
+ React.createElement(Grid2_1.default, { size: { xs: 4 } },
98
+ React.createElement(Typography_1.default, null, "Placeholder")),
99
+ React.createElement(Grid2_1.default, { size: { xs: 8 } },
100
+ React.createElement(Input_1.Input, Object.assign({}, args, { value: "" }))),
101
+ React.createElement(Grid2_1.default, { size: { xs: 4 } },
102
+ React.createElement(Typography_1.default, null, "Default")),
103
+ React.createElement(Grid2_1.default, { size: { xs: 8 } },
104
+ React.createElement(Input_1.Input, Object.assign({}, args))),
105
+ React.createElement(Grid2_1.default, { size: { xs: 4 } },
106
+ React.createElement(Typography_1.default, null, "Initially Focused")),
107
+ React.createElement(Grid2_1.default, { size: { xs: 8 } },
108
+ React.createElement(Input_1.Input
109
+ // This is a story just demonstrating the autofocus prop
110
+ // eslint-disable-next-line jsx-a11y/no-autofocus
111
+ , Object.assign({
112
+ // This is a story just demonstrating the autofocus prop
113
+ // eslint-disable-next-line jsx-a11y/no-autofocus
114
+ autoFocus: true }, args))),
115
+ React.createElement(Grid2_1.default, { size: { xs: 4 } },
116
+ React.createElement(Typography_1.default, null, "Error")),
117
+ React.createElement(Grid2_1.default, { size: { xs: 8 } },
118
+ React.createElement(Input_1.Input, Object.assign({}, args, { error: true }))),
119
+ React.createElement(Grid2_1.default, { size: { xs: 4 } },
120
+ React.createElement(Typography_1.default, null, "Disabled")),
121
+ React.createElement(Grid2_1.default, { size: { xs: 8 } },
122
+ React.createElement(Input_1.Input, Object.assign({}, args, { disabled: true })))));
123
+ },
124
+ args: {
125
+ placeholder: "This is placeholder text.",
126
+ value: "Some value",
127
+ },
128
+ argTypes: {
129
+ placeholder: { table: { disable: true } },
130
+ value: { table: { disable: true } },
131
+ error: { table: { disable: true } },
132
+ disabled: { table: { disable: true } },
133
+ },
134
+ };
@@ -0,0 +1 @@
1
+ export {};