@grantbii/design-system 1.0.65 → 1.0.67

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 (40) hide show
  1. package/README.md +3 -0
  2. package/core/atoms/Badge.js +1 -0
  3. package/core/atoms/BrandLogo.js +1 -0
  4. package/core/atoms/Button.js +1 -0
  5. package/core/atoms/Checkbox.js +1 -0
  6. package/core/atoms/LinkButton.js +1 -0
  7. package/core/atoms/PageLoader.js +1 -0
  8. package/core/atoms/RadioButton.js +1 -0
  9. package/core/atoms/Textarea.js +1 -0
  10. package/core/foundations/icons.d.ts +0 -4
  11. package/core/foundations/icons.js +0 -4
  12. package/core/foundations/index.d.ts +2 -1
  13. package/core/foundations/index.js +2 -1
  14. package/core/foundations/responsive.d.ts +3 -0
  15. package/core/foundations/responsive.js +3 -0
  16. package/core/foundations/types.d.ts +1 -0
  17. package/core/foundations/typography.d.ts +10 -0
  18. package/core/foundations/typography.js +20 -0
  19. package/core/global/GlobalStyle.js +0 -9
  20. package/core/global/index.d.ts +1 -0
  21. package/core/global/index.js +1 -0
  22. package/core/molecules/FileDrop.js +28 -16
  23. package/core/molecules/Modal.d.ts +1 -2
  24. package/core/molecules/Modal.js +26 -15
  25. package/core/molecules/RadioButtons.js +1 -0
  26. package/core/organisms/GrantMatch.d.ts +9 -11
  27. package/core/organisms/GrantMatch.js +130 -77
  28. package/core/organisms/TallyModal.js +1 -0
  29. package/core/organisms/YesNoOptions.js +1 -0
  30. package/index.d.ts +1 -1
  31. package/index.js +1 -1
  32. package/package.json +2 -2
  33. package/stories/molecules/Modal.stories.d.ts +2 -5
  34. package/stories/molecules/Modal.stories.js +4 -17
  35. package/stories/organisms/GrantMatch.stories.d.ts +2 -6
  36. package/stories/organisms/GrantMatch.stories.js +15 -18
  37. package/tsconfig.tsbuildinfo +1 -1
  38. package/core/assets/icons/grant_match.webp +0 -0
  39. package/core/foundations/breakpoints.d.ts +0 -1
  40. package/core/foundations/breakpoints.js +0 -1
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Grantbii's Design System
2
2
 
3
+ Storybook's viewport triggers media query for small screen (e.g. mobile) by default.
4
+ View in full screen to see components for big screen (e.g. desktop).
5
+
3
6
  Based on Grantbii's Global Design Library in Figma.
4
7
 
5
8
  Approach: Atomic Design
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import styled from "styled-components";
3
4
  import { Colors, Icons } from "../foundations";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import Image from "next/image";
3
4
  import darkLogo from "../assets/logos/brand_logo-dark.webp";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { BaseButton as ButtonContent } from "./shared";
3
4
  import styled from "styled-components";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import styled from "styled-components";
2
3
  import { Colors } from "../foundations";
3
4
  const Textarea = styled.textarea `
@@ -1,5 +1 @@
1
1
  export * from "@phosphor-icons/react";
2
- type GrantMatchIconProps = {
3
- size?: number;
4
- };
5
- export declare const GrantMatchIcon: ({ size }: GrantMatchIconProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
1
  export * from "@phosphor-icons/react";
3
- import Image from "next/image";
4
- import grantMatchIcon from "../assets/icons/grant_match.webp";
5
- export const GrantMatchIcon = ({ size = 20 }) => (_jsx(Image, { src: grantMatchIcon, alt: "Grant Match", width: size, height: size }));
@@ -1,5 +1,6 @@
1
- export * as Breakpoints from "./breakpoints";
1
+ export * as Responsive from "./responsive";
2
2
  export * as Colors from "./colors";
3
3
  export * as Flags from "./flags";
4
4
  export * as Icons from "./icons";
5
5
  export type * from "./types";
6
+ export * as Typography from "./typography";
@@ -1,4 +1,5 @@
1
- export * as Breakpoints from "./breakpoints";
1
+ export * as Responsive from "./responsive";
2
2
  export * as Colors from "./colors";
3
3
  export * as Flags from "./flags";
4
4
  export * as Icons from "./icons";
5
+ export * as Typography from "./typography";
@@ -0,0 +1,3 @@
1
+ export declare const WIDTH_BREAKPOINTS: {
2
+ laptop: string;
3
+ };
@@ -0,0 +1,3 @@
1
+ export const WIDTH_BREAKPOINTS = {
2
+ laptop: "1024px",
3
+ };
@@ -1,3 +1,4 @@
1
+ export type ScreenSize = "big" | "small";
1
2
  export type Option = {
2
3
  label: string;
3
4
  value: string;
@@ -0,0 +1,10 @@
1
+ import { ScreenSize } from "./types";
2
+ type FontSizes = {
3
+ [screenSize in ScreenSize]: string;
4
+ };
5
+ export declare const TITLE_FONT_SIZES: FontSizes;
6
+ export declare const HEADER_FONT_SIZES: FontSizes;
7
+ export declare const SUBHEADER_FONT_SIZES: FontSizes;
8
+ export declare const BODY_FONT_SIZES: FontSizes;
9
+ export declare const HELPER_FONT_SIZES: FontSizes;
10
+ export {};
@@ -0,0 +1,20 @@
1
+ export const TITLE_FONT_SIZES = {
2
+ big: "24px",
3
+ small: "22px",
4
+ };
5
+ export const HEADER_FONT_SIZES = {
6
+ big: "22px",
7
+ small: "20px",
8
+ };
9
+ export const SUBHEADER_FONT_SIZES = {
10
+ big: "20px",
11
+ small: "18px",
12
+ };
13
+ export const BODY_FONT_SIZES = {
14
+ big: "16px",
15
+ small: "14px",
16
+ };
17
+ export const HELPER_FONT_SIZES = {
18
+ big: "14px",
19
+ small: "12px",
20
+ };
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { createGlobalStyle } from "styled-components";
3
3
  import "../assets/fonts/satoshi/css/satoshi.css";
4
- import { LAPTOP_WIDTH_PIXELS } from "../foundations/breakpoints";
5
4
  import * as Colors from "../foundations/colors";
6
5
  const GlobalStyle = createGlobalStyle `
7
6
  html,
@@ -62,13 +61,5 @@ const GlobalStyle = createGlobalStyle `
62
61
  -moz-appearance: textfield;
63
62
  appearance: textfield;
64
63
  }
65
-
66
- @media (width < ${LAPTOP_WIDTH_PIXELS}px) {
67
- font-size: 14px;
68
- }
69
-
70
- @media (width >= ${LAPTOP_WIDTH_PIXELS}px) {
71
- font-size: 16px;
72
- }
73
64
  `;
74
65
  export default GlobalStyle;
@@ -0,0 +1 @@
1
+ export { default as GlobalStyle } from "./GlobalStyle";
@@ -0,0 +1 @@
1
+ export { default as GlobalStyle } from "./GlobalStyle";
@@ -1,9 +1,10 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
3
  import { useState } from "react";
3
4
  import { useDropzone } from "react-dropzone";
4
5
  import styled from "styled-components";
5
6
  import { Badge } from "../atoms";
6
- import { Colors, Icons } from "../foundations";
7
+ import { Colors, Icons, Responsive, Typography } from "../foundations";
7
8
  const DEFAULT_MAX_FILE_SIZE_MB = 5;
8
9
  const DEFAULT_MAX_FILES = 5;
9
10
  const FileDrop = ({ uploadedFiles, uploadFiles, removeFile, errorMessage, maxFiles = DEFAULT_MAX_FILES, maxSizeMB = DEFAULT_MAX_FILE_SIZE_MB, }) => {
@@ -35,36 +36,47 @@ const Dropzone = styled.div `
35
36
  cursor: ${({ $reachedMaxUploads }) => $reachedMaxUploads ? "not-allowed" : "pointer"};
36
37
  }
37
38
  `;
38
- const DropzoneContent = ({ maxFiles, maxSizeMB }) => (_jsxs(BaseDropzoneContent, { children: [_jsx(Icons.FileDashedIcon, { weight: "thin", size: 48, color: Colors.neutral.grey1 }), _jsxs(DropzoneText, { children: [_jsx(DropzoneTitle, { children: `Drop up to ${maxFiles} files here ( ${maxSizeMB}MB each)` }), _jsx(DropzoneHighlightedSubtitle, { children: DROPZONE_BROWSE_TEXT }), _jsx(DropzoneSubtitle, { children: FILE_FORMAT_TEXT })] })] }));
39
+ const DropzoneContent = ({ maxFiles, maxSizeMB }) => (_jsxs(BaseDropzoneContent, { children: [_jsx(Icons.FileDashedIcon, { weight: "thin", size: 48, color: Colors.neutral.grey1 }), _jsxs(AllDropzoneText, { children: [_jsx(DropzoneText, { children: `Drop up to ${maxFiles} files here ( ${maxSizeMB}MB each)` }), _jsx(DropzoneSubtitle, { "$isHighlighted": true, children: DROPZONE_BROWSE_TEXT }), _jsx(DropzoneSubtitle, { children: FILE_FORMAT_TEXT })] })] }));
39
40
  const DROPZONE_BROWSE_TEXT = "or click to browse with your file explorer";
40
- const FILE_FORMAT_TEXT = "Accepted file formats: .pdf (Coming soon: .doc, .ppt, .csv)";
41
+ const FILE_FORMAT_TEXT = "Accepted file formats: .pdf (more coming soon)";
41
42
  const BaseDropzoneContent = styled.div `
42
43
  display: flex;
43
44
  flex-direction: column;
44
45
  gap: 24px;
45
46
  align-items: center;
46
47
  `;
47
- const DropzoneText = styled.div `
48
+ const AllDropzoneText = styled.div `
48
49
  display: flex;
49
50
  flex-direction: column;
50
51
  gap: 4px;
51
52
  `;
52
- const DropzoneTitle = styled.h3 `
53
- font-weight: 500;
54
- font-size: 14px;
53
+ const DropzoneText = styled.p `
55
54
  text-align: center;
56
- `;
57
- const DropzoneHighlightedSubtitle = styled.p `
58
- font-weight: 400;
59
- font-size: 12px;
60
- text-align: center;
61
- color: ${Colors.accent.yellow1};
55
+
56
+ font-weight: 500;
57
+
58
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
59
+ font-size: ${Typography.BODY_FONT_SIZES.small};
60
+ }
61
+
62
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
63
+ font-size: ${Typography.BODY_FONT_SIZES.big};
64
+ }
62
65
  `;
63
66
  const DropzoneSubtitle = styled.p `
64
- font-weight: 400;
65
- font-size: 12px;
66
67
  text-align: center;
67
- color: ${Colors.typography.blackLow};
68
+
69
+ font-weight: 400;
70
+
71
+ color: ${({ $isHighlighted = false }) => $isHighlighted ? Colors.accent.yellow1 : Colors.typography.blackLow};
72
+
73
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
74
+ font-size: ${Typography.HELPER_FONT_SIZES.small};
75
+ }
76
+
77
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
78
+ font-size: ${Typography.HELPER_FONT_SIZES.big};
79
+ }
68
80
  `;
69
81
  const ErrorMessage = styled.p `
70
82
  color: ${Colors.accent.red1};
@@ -5,10 +5,9 @@ type ModalProps = {
5
5
  footer?: ReactNode;
6
6
  width?: string;
7
7
  height?: string;
8
- isFullScreen?: boolean;
9
8
  onClickCancel: MouseEventHandler<HTMLButtonElement>;
10
9
  };
11
- declare const Modal: ({ header, content, footer, width, height, isFullScreen, onClickCancel, }: ModalProps) => import("react/jsx-runtime").JSX.Element;
10
+ declare const Modal: ({ header, content, footer, width, height, onClickCancel, }: ModalProps) => import("react/jsx-runtime").JSX.Element;
12
11
  export default Modal;
13
12
  export declare const useModal: () => {
14
13
  showModal: boolean;
@@ -1,9 +1,10 @@
1
+ "use client";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useCallback, useState } from "react";
3
- import styled, { css } from "styled-components";
4
+ import styled from "styled-components";
4
5
  import { Button } from "../atoms";
5
- import { Colors } from "../foundations";
6
- const Modal = ({ header, content, footer, width, height, isFullScreen, onClickCancel, }) => (_jsx(Overlay, { "$isFullScreen": isFullScreen, children: _jsxs(ModalWindow, { "$isFullScreen": isFullScreen, "$width": width, "$height": height, children: [header ? _jsx(ModalHeader, { children: header }) : _jsx(_Fragment, {}), _jsx(ModalBody, { children: content }), _jsxs(ModalFooter, { children: [_jsx(CancelButton, { onClick: onClickCancel }), footer ? footer : _jsx(_Fragment, {})] })] }) }));
6
+ import { Colors, Responsive } from "../foundations";
7
+ const Modal = ({ header, content, footer, width, height, onClickCancel, }) => (_jsx(Overlay, { children: _jsxs(ModalWindow, { "$width": width, "$height": height, children: [header ? _jsx(ModalHeader, { children: header }) : _jsx(_Fragment, {}), _jsx(ModalBody, { children: content }), _jsxs(ModalFooter, { children: [_jsx(CancelButton, { onClick: onClickCancel }), footer ? footer : _jsx(_Fragment, {})] })] }) }));
7
8
  export default Modal;
8
9
  export const useModal = () => {
9
10
  const [showModal, setShowModal] = useState(false);
@@ -30,7 +31,7 @@ export const useModal = () => {
30
31
  const Overlay = styled.div `
31
32
  background-color: ${Colors.semantic.overlay};
32
33
 
33
- z-index: ${({ $isFullScreen }) => $isFullScreen ? Number.MAX_SAFE_INTEGER - 1 : Number.MAX_SAFE_INTEGER};
34
+ z-index: ${Number.MAX_SAFE_INTEGER};
34
35
  position: fixed;
35
36
  top: 0px;
36
37
  left: 0px;
@@ -48,21 +49,31 @@ const ModalWindow = styled.div `
48
49
  flex-direction: column;
49
50
 
50
51
  background-color: ${Colors.base.white};
51
- border-radius: ${({ $isFullScreen }) => ($isFullScreen ? 0 : 6)}px;
52
-
53
- width: ${({ $isFullScreen, $width = "auto" }) => $isFullScreen ? "100%" : $width};
54
- height: ${({ $isFullScreen, $height = "auto" }) => $isFullScreen ? "100%" : $height};
55
52
 
56
53
  min-height: 100px;
57
54
  max-height: 100vh;
58
55
 
59
- ${({ $isFullScreen = false }) => $isFullScreen
60
- ? css `
61
- position: fixed;
62
- bottom: 0px;
63
- left: 0px;
64
- `
65
- : ""}
56
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
57
+ position: fixed;
58
+ bottom: 0px;
59
+ left: 0px;
60
+
61
+ width: 100%;
62
+ height: 100%;
63
+
64
+ border-radius: 0px;
65
+ }
66
+
67
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
68
+ position: static;
69
+ bottom: auto;
70
+ left: auto;
71
+
72
+ width: ${({ $width }) => $width};
73
+ height: ${({ $height }) => $height};
74
+
75
+ border-radius: 6px;
76
+ }
66
77
  `;
67
78
  const ModalHeader = styled.div `
68
79
  font-weight: 500;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,14 +1,12 @@
1
+ import { GrantFilters } from "@grantbii/ui-base/grant/models";
1
2
  import { GrantMatchQuery } from "@grantbii/ui-base/match/models";
2
- type GrantMatchProps = GrantMatchQueryProps & {
3
- isSmallerThanLaptop?: boolean;
3
+ type GrantMatchProps = {
4
+ activeQuery: GrantMatchQuery;
5
+ updateActiveQuery: (newQuery: GrantMatchQuery) => void;
6
+ removeActiveQueryFile: (fileName: string) => void;
7
+ removeActiveQueryText: () => void;
8
+ resetActiveQuery: () => void;
4
9
  };
5
- declare const GrantMatch: ({ query, updateQuery, removeQueryFile, removeQueryText, resetQuery, isSmallerThanLaptop, }: GrantMatchProps) => import("react/jsx-runtime").JSX.Element;
10
+ declare const GrantMatch: ({ activeQuery, updateActiveQuery, removeActiveQueryFile, removeActiveQueryText, resetActiveQuery, }: GrantMatchProps) => import("react/jsx-runtime").JSX.Element;
6
11
  export default GrantMatch;
7
- type GrantMatchQueryProps = {
8
- query: GrantMatchQuery;
9
- updateQuery: (newQuery: GrantMatchQuery) => void;
10
- removeQueryFile: (fileName: string) => void;
11
- removeQueryText: () => void;
12
- resetQuery: () => void;
13
- };
14
- export declare const useGrantMatchQueryItems: (performGrantMatch: (newQuery: GrantMatchQuery) => void, resetGrantMatch: () => void) => GrantMatchQueryProps;
12
+ export declare const useGrantMatchActiveQuery: (filters: GrantFilters, performGrantMatch: (newQuery: GrantMatchQuery, filters: GrantFilters) => void, resetGrantMatch: () => void) => GrantMatchProps;
@@ -1,64 +1,50 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
3
  import { isGrantMatchActive } from "@grantbii/ui-base/match/mappings";
3
4
  import { useState } from "react";
4
5
  import styled from "styled-components";
5
6
  import { Badge, Button, Textarea } from "../atoms";
6
- import { Colors, Icons } from "../foundations";
7
+ import { Colors, Icons, Responsive, Typography } from "../foundations";
7
8
  import { FileDrop, Modal, useFileDrop, useModal } from "../molecules";
8
- const GrantMatch = ({ query, updateQuery, removeQueryFile, removeQueryText, resetQuery, isSmallerThanLaptop, }) => {
9
+ const GrantMatch = ({ activeQuery, updateActiveQuery, removeActiveQueryFile, removeActiveQueryText, resetActiveQuery, }) => {
9
10
  const { showModal, openModal, closeModal } = useModal();
10
- const isActive = isGrantMatchActive(query);
11
- const updateActiveQuery = (newQuery) => {
12
- updateQuery(newQuery);
13
- closeModal();
14
- };
15
- return (_jsxs(BaseGrantMatch, { children: [_jsx(GrantMatchButtons, { isActive: isActive, onClickMatch: () => openModal(), onClickReset: () => resetQuery(), isSmallerThanLaptop: isSmallerThanLaptop }), isActive ? (_jsxs(QueryItemsRow, { children: [_jsx(QueryItems, { activeQuery: query, removeQueryFile: removeQueryFile, removeQueryText: removeQueryText }), isSmallerThanLaptop ? (_jsx(ResetButton, { onClick: () => resetQuery() })) : (_jsx(_Fragment, {}))] })) : (_jsx(_Fragment, {})), showModal ? (_jsx(GrantMatchModal, { activeQuery: query, updateActiveQuery: updateActiveQuery, onClickCancel: () => closeModal(), isFullScreen: isSmallerThanLaptop })) : (_jsx(_Fragment, {}))] }));
11
+ const isActive = isGrantMatchActive(activeQuery);
12
+ const [queryText, setQueryText] = useState(activeQuery.text);
13
+ const updateQueryText = (newText) => setQueryText(newText);
14
+ const onClickSearch = () => updateActiveQuery(Object.assign(Object.assign({}, activeQuery), { text: queryText }));
15
+ return (_jsxs(BaseGrantMatch, { children: [_jsx(GrantMatchActions, { queryText: queryText, updateQueryText: updateQueryText, onClickSearch: onClickSearch, onClickFileDrop: () => openModal(), onClickReset: () => resetActiveQuery(), isActive: isActive }), isActive ? (_jsxs(ActiveQueryRow, { children: [_jsx(ActiveQueryFiles, { activeQuery: activeQuery, removeQueryFile: removeActiveQueryFile, removeQueryText: removeActiveQueryText }), _jsx(SmallScreenResetButton, { onClick: () => resetActiveQuery() })] })) : (_jsx(_Fragment, {})), showModal ? (_jsx(GrantMatchModal, { activeQuery: activeQuery, updateActiveQuery: updateActiveQuery, queryText: queryText, updateQueryText: updateQueryText, closeModal: closeModal })) : (_jsx(_Fragment, {}))] }));
16
16
  };
17
17
  export default GrantMatch;
18
- export const useGrantMatchQueryItems = (performGrantMatch, resetGrantMatch) => {
19
- const [query, setQuery] = useState(() => (Object.assign({}, BLANK_GRANT_MATCH_QUERY)));
20
- const updateQuery = (newQuery) => {
21
- setQuery(Object.assign({}, newQuery));
22
- if (isGrantMatchActive(newQuery)) {
23
- performGrantMatch(newQuery);
18
+ // TODO: refactor
19
+ export const useGrantMatchActiveQuery = (filters, performGrantMatch, resetGrantMatch) => {
20
+ const [activeQuery, setActiveQuery] = useState(() => (Object.assign({}, BLANK_GRANT_MATCH_QUERY)));
21
+ const updateActiveQuery = (query) => {
22
+ setActiveQuery(Object.assign({}, query));
23
+ if (isGrantMatchActive(query)) {
24
+ performGrantMatch(query, filters);
24
25
  }
25
26
  else {
26
27
  resetGrantMatch();
27
28
  }
28
29
  };
29
- const removeQueryFile = (fileName) => {
30
+ const removeActiveQueryFile = (fileName) => {
30
31
  const newQuery = {
31
- files: query.files.filter((file) => file.name !== fileName),
32
- text: query.text,
32
+ files: activeQuery.files.filter((file) => file.name !== fileName),
33
+ text: activeQuery.text,
33
34
  };
34
- updateQuery(newQuery);
35
- if (isGrantMatchActive(newQuery)) {
36
- performGrantMatch(newQuery);
37
- }
38
- else {
39
- resetGrantMatch();
40
- }
41
- };
42
- const removeQueryText = () => {
43
- const newQuery = { files: query.files, text: "" };
44
- updateQuery(newQuery);
45
- if (isGrantMatchActive(newQuery)) {
46
- performGrantMatch(newQuery);
47
- }
48
- else {
49
- resetGrantMatch();
50
- }
35
+ updateActiveQuery(newQuery);
51
36
  };
52
- const resetQuery = () => {
53
- setQuery(Object.assign({}, BLANK_GRANT_MATCH_QUERY));
54
- resetGrantMatch();
37
+ const removeActiveQueryText = () => {
38
+ const newQuery = { files: activeQuery.files, text: "" };
39
+ updateActiveQuery(newQuery);
55
40
  };
41
+ const resetActiveQuery = () => updateActiveQuery(Object.assign({}, BLANK_GRANT_MATCH_QUERY));
56
42
  return {
57
- query,
58
- updateQuery,
59
- removeQueryFile,
60
- removeQueryText,
61
- resetQuery,
43
+ activeQuery,
44
+ updateActiveQuery,
45
+ removeActiveQueryFile,
46
+ removeActiveQueryText,
47
+ resetActiveQuery,
62
48
  };
63
49
  };
64
50
  const BLANK_GRANT_MATCH_QUERY = { files: [], text: "" };
@@ -70,50 +56,120 @@ const BaseGrantMatch = styled.div `
70
56
  width: 100%;
71
57
  max-width: 100vw;
72
58
  `;
73
- const GrantMatchButtons = ({ isActive, onClickMatch, onClickReset, isSmallerThanLaptop, }) => (_jsxs(Buttons, { children: [_jsx(GrantMatchButton, { isActive: isActive, isSmallerThanLaptop: isSmallerThanLaptop, onClick: onClickMatch }), !isSmallerThanLaptop && isActive ? (_jsx(ResetButton, { onClick: onClickReset })) : (_jsx(_Fragment, {}))] }));
74
- const Buttons = styled.div `
59
+ const GrantMatchActions = ({ queryText, updateQueryText, onClickSearch, onClickFileDrop, onClickReset, isActive, }) => (_jsxs(Actions, { children: [_jsxs(SearchBar, { "$isActive": isActive, children: [_jsx(Input, { value: queryText, onChange: (event) => updateQueryText(event.target.value), placeholder: "Find grants that match your needs" }), _jsx(SearchButton, { onClick: onClickSearch }), _jsx(FileDropButton, { onClick: onClickFileDrop })] }), isActive ? _jsx(BigScreenResetButton, { onClick: onClickReset }) : _jsx(_Fragment, {})] }));
60
+ const Actions = styled.div `
75
61
  display: flex;
76
62
  align-items: center;
77
63
  gap: 8px;
78
64
  `;
79
- const GrantMatchButton = ({ isActive, onClick, isSmallerThanLaptop, }) => (_jsxs(BaseGrantMatchButton, { type: "button", "$isSmallerThanLaptop": isSmallerThanLaptop, "$isActive": isActive, onClick: onClick, children: [_jsxs(GrantMatchButtonContent, { children: [_jsx(Icons.GrantMatchIcon, { size: 20 }), _jsx("p", { children: "Find grants that match your needs" })] }), _jsx(Icons.MagnifyingGlassIcon, { size: 20 })] }));
80
- const BaseGrantMatchButton = styled.button `
65
+ const SearchBar = styled.div `
81
66
  display: flex;
82
67
  align-items: center;
83
- justify-content: space-between;
84
- gap: 16px;
85
-
86
- padding: 10px 16px;
87
-
88
- height: 20px;
89
- width: ${({ $isSmallerThanLaptop = false }) => $isSmallerThanLaptop ? "100%" : "auto"};
90
68
 
91
- font-size: 14px;
92
- font-weight: 500;
69
+ padding: 6px 16px;
93
70
 
94
71
  background-color: ${Colors.base.white};
95
- color: ${Colors.typography.blackMedium};
72
+ color: ${Colors.typography.blackHigh};
96
73
 
97
74
  border: 1px solid
98
75
  ${({ $isActive }) => $isActive ? Colors.accent.yellow1 : Colors.neutral.grey3};
99
- border-radius: 200px;
76
+ border-radius: 12px;
77
+
78
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
79
+ gap: 8px;
80
+ width: 100%;
81
+ }
82
+
83
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
84
+ gap: 16px;
85
+ width: auto;
86
+ }
100
87
  `;
101
- const GrantMatchButtonContent = styled.div `
88
+ const Input = styled.input `
89
+ width: 300px;
90
+ border: none;
91
+ outline: none;
92
+ `;
93
+ const SearchButton = ({ onClick }) => (_jsx(BaseSearchButton, { type: "button", onClick: onClick, children: _jsx(Icons.MagnifyingGlassIcon, { size: 16, color: Colors.neutral.grey1 }) }));
94
+ const BaseSearchButton = styled.button `
102
95
  display: flex;
103
96
  align-items: center;
104
- gap: 8px;
97
+ justify-content: center;
98
+
99
+ height: 32px;
100
+ width: 32px;
101
+ min-width: 32px;
102
+
103
+ background-color: ${Colors.neutral.grey3};
104
+
105
+ border-radius: 8px;
106
+ `;
107
+ const FileDropButton = ({ onClick }) => (_jsxs(BaseFileDropButton, { onClick: onClick, children: [_jsx(Icons.FileArrowUpIcon, { size: 16 }), _jsx(FileDropButtonText, { children: "File Drop" })] }));
108
+ const BaseFileDropButton = styled.button `
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ gap: 4px;
113
+
114
+ height: 31px;
115
+ min-width: 31px;
116
+
117
+ background-color: ${Colors.base.white};
118
+ color: ${Colors.accent.blue1};
119
+
120
+ border: 1px solid ${Colors.accent.blue1};
121
+ border-radius: 8px;
122
+
123
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
124
+ padding: 0px;
125
+ font-size: ${Typography.HELPER_FONT_SIZES.small};
126
+ }
127
+
128
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
129
+ padding: 0px 8px;
130
+ font-size: ${Typography.HELPER_FONT_SIZES.big};
131
+ }
132
+ `;
133
+ const FileDropButtonText = styled.p `
134
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
135
+ display: none;
136
+ }
137
+
138
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
139
+ display: inline;
140
+ }
141
+ `;
142
+ const SmallScreenResetButton = ({ onClick }) => (_jsx(SmallScreenReset, { children: _jsx(ResetButton, { onClick: onClick }) }));
143
+ const SmallScreenReset = styled.div `
144
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
145
+ display: inline;
146
+ }
147
+
148
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
149
+ display: none;
150
+ }
151
+ `;
152
+ const BigScreenResetButton = ({ onClick }) => (_jsx(BigScreenReset, { children: _jsx(ResetButton, { onClick: onClick }) }));
153
+ const BigScreenReset = styled.div `
154
+ @media (width < ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
155
+ display: inline;
156
+ }
157
+
158
+ @media (width >= ${Responsive.WIDTH_BREAKPOINTS.laptop}) {
159
+ display: none;
160
+ }
105
161
  `;
106
162
  const ResetButton = ({ onClick }) => (_jsx(Button, { text: "Reset", onClick: onClick, color: Colors.typography.blackMedium, underline: true }));
107
- const QueryItemsRow = styled.div `
163
+ const ActiveQueryRow = styled.div `
108
164
  display: flex;
109
165
  align-items: center;
110
166
  justify-content: space-between;
111
167
  `;
112
- const QueryItems = ({ activeQuery, removeQueryFile, removeQueryText, }) => (_jsxs(BaseQueryItems, { children: [activeQuery.files.map((file) => {
113
- var _a;
114
- return (_jsx(Badge, { text: file.name, Icon: (_a = FILE_TYPE_ICON_MAP[file.type]) !== null && _a !== void 0 ? _a : Icons.FileIcon, onClickClose: () => removeQueryFile(file.name), textWidthPixels: 160 }, file.name));
115
- }), activeQuery.text === "" ? (_jsx(_Fragment, {})) : (_jsx(Badge, { text: "Additional Information", Icon: Icons.TextAaIcon, onClickClose: () => removeQueryText(), textWidthPixels: 180 }, "additional-information-query-item"))] }));
116
- const BaseQueryItems = styled.div `
168
+ const ActiveQueryFiles = ({ activeQuery, removeQueryFile, }) => (_jsx(BaseActiveQueryFiles, { children: activeQuery.files.map((file) => {
169
+ var _a;
170
+ return (_jsx(Badge, { text: file.name, Icon: (_a = FILE_TYPE_ICON_MAP[file.type]) !== null && _a !== void 0 ? _a : Icons.FileIcon, onClickClose: () => removeQueryFile(file.name), textWidthPixels: 160 }, file.name));
171
+ }) }));
172
+ const BaseActiveQueryFiles = styled.div `
117
173
  display: flex;
118
174
  align-items: center;
119
175
  gap: 8px;
@@ -134,19 +190,16 @@ const BaseQueryItems = styled.div `
134
190
  const FILE_TYPE_ICON_MAP = {
135
191
  "application/pdf": Icons.FilePdfIcon,
136
192
  };
137
- const GrantMatchModal = ({ activeQuery, updateActiveQuery, onClickCancel, isFullScreen, }) => {
193
+ const GrantMatchModal = ({ activeQuery, updateActiveQuery, queryText, updateQueryText, closeModal, }) => {
138
194
  const { files, uploadFiles, removeFile } = useFileDrop(activeQuery.files);
139
- const [text, setText] = useState(activeQuery.text);
140
- return (_jsx(Modal, { header: _jsx(Header, {}), content: _jsx(Content, { files: files, uploadFiles: uploadFiles, removeFile: removeFile, queryText: text, updateQueryText: (newText) => setText(newText) }), footer: _jsx(Button, { text: "Find My Grants", onClick: () => updateActiveQuery({ files, text }), backgroundColor: Colors.accent.yellow1 }), onClickCancel: onClickCancel, isFullScreen: isFullScreen, width: "480px", height: "600px" }));
195
+ const onClickFind = () => {
196
+ updateActiveQuery({ files, text: queryText });
197
+ closeModal();
198
+ };
199
+ return (_jsx(Modal, { header: _jsx("div", { children: "Grant Match" }), content: _jsx(Content, { files: files, uploadFiles: uploadFiles, removeFile: removeFile, queryText: queryText, updateQueryText: updateQueryText }), footer: _jsx(Button, { text: "Find My Grants", onClick: onClickFind, backgroundColor: Colors.accent.yellow1 }), onClickCancel: () => closeModal(), width: "480px", height: "600px" }));
141
200
  };
142
- const Header = () => (_jsxs(BaseHeader, { children: [_jsx(Icons.GrantMatchIcon, { size: 24 }), _jsx("div", { children: "Grant Match" })] }));
143
- const BaseHeader = styled.div `
144
- display: flex;
145
- align-items: center;
146
- gap: 12px;
147
- `;
148
- const Content = ({ files, uploadFiles, removeFile, queryText, updateQueryText, }) => (_jsxs(BaseContent, { children: [_jsx(FileDrop, { uploadedFiles: files, uploadFiles: uploadFiles, removeFile: removeFile }), _jsxs(QueryText, { children: [_jsx("label", { htmlFor: ADDITIONAL_INFORMATION_ID, children: "Additional Information" }), _jsx(Textarea, { id: ADDITIONAL_INFORMATION_ID, value: queryText, onChange: (event) => updateQueryText(event.target.value) })] })] }));
149
- const ADDITIONAL_INFORMATION_ID = "grant-match-additional-information";
201
+ const Content = ({ files, uploadFiles, removeFile, queryText, updateQueryText, }) => (_jsxs(BaseContent, { children: [_jsx(FileDrop, { uploadedFiles: files, uploadFiles: uploadFiles, removeFile: removeFile }), _jsxs(QueryText, { children: [_jsx("label", { htmlFor: QUERY_TEXTAREA_ID, children: "Search Grants Opportunities" }), _jsx(Textarea, { id: QUERY_TEXTAREA_ID, value: queryText, onChange: (event) => updateQueryText(event.target.value), placeholder: "Explore by grant name or share what your project is about..." })] })] }));
202
+ const QUERY_TEXTAREA_ID = "query-textarea";
150
203
  const BaseContent = styled.div `
151
204
  display: flex;
152
205
  flex-direction: column;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __rest = (this && this.__rest) || function (s, e) {
2
3
  var t = {};
3
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { LogicOption } from "@grantbii/ui-base/grant/enums";
3
4
  import styled from "styled-components";
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./core/atoms";
2
2
  export * from "./core/foundations";
3
- export { default as GlobalStyle } from "./core/global/GlobalStyle";
3
+ export * from "./core/global";
4
4
  export * from "./core/integrations";
5
5
  export * from "./core/molecules";
6
6
  export * from "./core/organisms";