@yourdash/uikit 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. package/components/box/box.module.scss +1 -1
  2. package/components/box/box.tsx +3 -3
  3. package/components/button/button.module.scss +3 -3
  4. package/components/button/button.tsx +2 -1
  5. package/components/buttonLink/buttonLink.module.scss +5 -1
  6. package/components/buttonLink/buttonLink.tsx +13 -12
  7. package/components/buttonWithIcon/buttonWithIcon.module.scss +56 -0
  8. package/components/buttonWithIcon/buttonWithIcon.tsx +36 -0
  9. package/components/card/card.module.scss +6 -6
  10. package/components/card/card.tsx +23 -20
  11. package/components/container/container.module.scss +20 -0
  12. package/components/container/container.tsx +22 -0
  13. package/components/contextMenu/contextMenu.tsx +1 -1
  14. package/components/contextMenu/contextMenuRoot.module.scss +1 -1
  15. package/components/contextMenu/contextMenuRoot.tsx +83 -83
  16. package/components/flex/flex.module.scss +31 -19
  17. package/components/flex/flex.tsx +23 -2
  18. package/components/heading/heading.module.scss +1 -1
  19. package/components/heading/heading.tsx +1 -1
  20. package/components/icon/icon.tsx +1 -1
  21. package/components/iconButton/iconButton.module.scss +1 -1
  22. package/components/iconButton/iconButton.tsx +3 -3
  23. package/components/image/image.module.scss +72 -1
  24. package/components/image/image.tsx +65 -10
  25. package/components/link/link.module.scss +1 -1
  26. package/components/link/link.tsx +1 -1
  27. package/components/progressBar/progressBar.module.scss +25 -0
  28. package/components/progressBar/progressBar.tsx +21 -0
  29. package/components/redirect/redirect.tsx +1 -1
  30. package/components/separator/separator.module.scss +9 -4
  31. package/components/separator/separator.tsx +3 -3
  32. package/components/spinner/spinner.module.scss +1 -6
  33. package/components/spinner/spinner.tsx +1 -1
  34. package/components/subtext/subtext.module.scss +1 -1
  35. package/components/subtext/subtext.tsx +1 -1
  36. package/components/tag/tag.module.scss +13 -0
  37. package/components/tag/tag.tsx +21 -0
  38. package/components/text/text.module.scss +1 -1
  39. package/components/text/text.tsx +1 -1
  40. package/components/textButton/textButton.module.scss +1 -1
  41. package/components/textButton/textButton.tsx +1 -1
  42. package/components/textInput/textInput.module.scss +1 -1
  43. package/components/textInput/textInput.tsx +40 -10
  44. package/components/toast/toast.module.scss +71 -31
  45. package/components/toast/toast.ts +12 -0
  46. package/components/toast/toastAction.ts +12 -0
  47. package/components/toast/toastContext.ts +5 -3
  48. package/components/toast/toasts.tsx +99 -0
  49. package/core/decrementLevel.tsx +13 -13
  50. package/core/incrementLevel.tsx +1 -1
  51. package/core/level.tsx +1 -1
  52. package/core/remToPx.ts +8 -0
  53. package/core/root.tsx +26 -32
  54. package/core/toast.ts +18 -17
  55. package/imports.d.ts +81 -0
  56. package/package.json +9 -40
  57. package/theme/defaultTheme.module.scss +16 -4
  58. package/theme/themeValues.scss +8 -5
  59. package/tsconfig.json +19 -9
  60. package/utilityComponent/hasBeenShown/hasBeenShown.tsx +47 -0
  61. package/utilityComponent/onInView/onInView.tsx +83 -0
  62. package/views/carousel/carousel.module.scss +77 -0
  63. package/views/carousel/carousel.tsx +138 -0
  64. package/views/header/header.module.scss +16 -0
  65. package/views/header/header.tsx +28 -0
  66. package/views/infiniteScroll/infiniteScroll.module.scss +26 -0
  67. package/views/infiniteScroll/infiniteScroll.tsx +90 -0
  68. package/views/navBar/components/navImage/navImage.module.scss +7 -0
  69. package/views/navBar/components/navImage/navImage.tsx +15 -0
  70. package/views/navBar/components/navTitle/navTitle.tsx +13 -0
  71. package/views/navBar/navBar.module.scss +22 -0
  72. package/views/navBar/navBar.tsx +37 -0
  73. package/views/onBoarding/onBoarding.module.scss +84 -0
  74. package/views/onBoarding/onBoarding.tsx +138 -0
  75. package/views/panAndZoom/panAndZoom.tsx +121 -114
  76. package/views/sidebar/Sidebar.module.scss +49 -0
  77. package/views/sidebar/Sidebar.tsx +30 -0
  78. package/views/sidebar/SidebarContainer.module.scss +22 -0
  79. package/views/sidebar/SidebarContainer.tsx +38 -0
  80. package/views/sidebar/SidebarContext.tsx +15 -0
  81. package/views/sidebar/SidebarToggleButton.tsx +25 -0
  82. package/components/toast/toast.tsx +0 -65
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import { UKIcon } from "../icon/iconDictionary.ts";
7
+
8
+ export default interface IToastAction {
9
+ label: string;
10
+ icon?: UKIcon;
11
+ onClick: () => void;
12
+ }
@@ -1,12 +1,14 @@
1
1
  /*
2
- * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
- * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
4
  */
5
5
 
6
6
  import React from "react";
7
+ import Toast from "./toast.ts";
7
8
 
8
9
  const ToastContext = React.createContext({
9
- showToast: (data: { type: "success" | "error" | "warning" | "info"; content: string; persist?: boolean }) => {
10
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+ showToast: (data: Toast) => {
10
12
  /* empty */
11
13
  },
12
14
  });
@@ -0,0 +1,99 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import generateUUID from "@yourdash/shared/web/helpers/uuid.ts";
7
+ import Heading from "../heading/heading.tsx";
8
+ import Separator from "../separator/separator.tsx";
9
+ import type ToastInterface from "./toast.ts";
10
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
11
+ import { FC, useState } from "react";
12
+ import Card from "../card/card.tsx";
13
+ import { UKIcon } from "../icon/iconDictionary.ts";
14
+ import IconButton from "../iconButton/iconButton.tsx";
15
+ import Text from "../text/text.tsx";
16
+ import ToastContext from "./toastContext.ts";
17
+ import * as React from "react";
18
+ // @ts-ignore
19
+ import styles from "./toast.module.scss";
20
+
21
+ const TOAST_DISPLAY_TIME = 5000;
22
+
23
+ const Toasts: FC<{ children: React.ReactNode | React.ReactNode[] }> = ({ children }) => {
24
+ const [toasts, setToasts] = useState<(ToastInterface & { uuid: string; animatingOut: boolean })[]>([]);
25
+
26
+ return (
27
+ <>
28
+ <ToastContext.Provider
29
+ value={{
30
+ showToast: (data: ToastInterface) => {
31
+ const uuid = generateUUID();
32
+
33
+ setToasts((t) => [...t, { ...data, uuid: uuid, animatingOut: false }]);
34
+
35
+ if (!data.persist) {
36
+ setTimeout(() => {
37
+ setToasts((t) =>
38
+ t.map((toast) => {
39
+ if (uuid === toast.uuid) {
40
+ return {
41
+ ...toast,
42
+ animatingOut: true,
43
+ };
44
+ }
45
+
46
+ return toast;
47
+ }),
48
+ );
49
+ }, TOAST_DISPLAY_TIME - 500);
50
+
51
+ setTimeout(() => {
52
+ setToasts((t) => t.filter((toast) => toast.uuid !== uuid));
53
+ }, TOAST_DISPLAY_TIME);
54
+ }
55
+ },
56
+ }}
57
+ >
58
+ <div className={styles.container}>
59
+ {toasts.map((t) => {
60
+ return (
61
+ <Card
62
+ key={t.uuid}
63
+ actions={
64
+ t.persist ? (
65
+ <IconButton
66
+ accessibleLabel={"Close toast"}
67
+ icon={UKIcon.X}
68
+ onClick={() => setToasts((toasts) => toasts.filter((x) => x.uuid !== t.uuid))}
69
+ />
70
+ ) : null
71
+ }
72
+ className={clippy(styles.cardContent, t.type && styles[t.type])}
73
+ containerClassName={clippy(
74
+ styles.component,
75
+ t.persist && styles.pointerEvents,
76
+ t.animatingOut ? "animate__animated animate__fadeOutRightBig" : "animate__animated animate__fadeInDown",
77
+ )}
78
+ >
79
+ <Heading
80
+ className={styles.heading}
81
+ level={3}
82
+ text={t.content.title}
83
+ />
84
+ <Separator direction={"column"} />
85
+ <Text
86
+ className={styles.body}
87
+ text={t.content.body}
88
+ />
89
+ </Card>
90
+ );
91
+ })}
92
+ </div>
93
+ {children}
94
+ </ToastContext.Provider>
95
+ </>
96
+ );
97
+ };
98
+
99
+ export default Toasts;
@@ -1,13 +1,13 @@
1
- /*
2
- * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
- * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
- */
5
-
6
- import LevelContext, { useLevel } from "./level";
7
- import { FC } from "react";
8
-
9
- const DecrementLevel: FC<{ children: React.ReactNode | React.ReactNode[] }> = (props) => {
10
- return <LevelContext.Provider value={useLevel() - 1}>{props.children}</LevelContext.Provider>;
11
- };
12
-
13
- export default DecrementLevel;
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
+ * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
+ */
5
+
6
+ import LevelContext, { useLevel } from "./level.tsx";
7
+ import { FC } from "react";
8
+
9
+ const DecrementLevel: FC<{ children: React.ReactNode | React.ReactNode[] }> = (props) => {
10
+ return <LevelContext.Provider value={useLevel() - 1}>{props.children}</LevelContext.Provider>;
11
+ };
12
+
13
+ export default DecrementLevel;
@@ -3,7 +3,7 @@
3
3
  * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
4
  */
5
5
 
6
- import LevelContext, { useLevel } from "./level";
6
+ import LevelContext, { useLevel } from "./level.tsx";
7
7
  import { FC } from "react";
8
8
 
9
9
  const IncrementLevel: FC<{ children: React.ReactNode | React.ReactNode[] }> = (props) => {
package/core/level.tsx CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { createContext, useContext } from "react";
7
- import styles from "./../theme/defaultTheme.module.scss";
7
+ import styles from "../theme/defaultTheme.module.scss";
8
8
 
9
9
  const LevelContext = createContext(0);
10
10
  export default LevelContext;
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit <https://ewsgit.uk> and YourDash <https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ export default function remToPx(rem: number) {
7
+ return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
8
+ }
package/core/root.tsx CHANGED
@@ -1,32 +1,26 @@
1
- /*
2
- * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
- * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
- */
5
-
6
- import clippy from "@yourdash/shared/web/helpers/clippy.js";
7
- import isMobileDevice from "@yourdash/shared/web/helpers/isPhone.js";
8
- import ContextMenuRoot from "../components/contextMenu/contextMenuRoot.js";
9
- import Toast from "../components/toast/toast.js";
10
- import LevelContext from "./level.js";
11
- import styles from "./../theme/defaultTheme.module.scss";
12
- import React, { FC, useEffect, useState } from "react";
13
-
14
- const UIKitRoot: FC<{ children: React.ReactNode | React.ReactNode[] }> = (props) => {
15
- const [isMobile, setIsMobile] = useState<boolean>(false);
16
-
17
- useEffect(() => {
18
- setIsMobile(isMobileDevice());
19
- }, []);
20
-
21
- return (
22
- <div className={clippy(styles.theme, styles.level0, isMobile && styles.mobile)}>
23
- <ContextMenuRoot>
24
- <Toast>
25
- <LevelContext.Provider value={0}>{props.children}</LevelContext.Provider>
26
- </Toast>
27
- </ContextMenuRoot>
28
- </div>
29
- );
30
- };
31
-
32
- export default UIKitRoot;
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
7
+ import isMobileDevice from "@yourdash/shared/web/helpers/isPhone.ts";
8
+ import ContextMenuRoot from "../components/contextMenu/contextMenuRoot.tsx";
9
+ import Toasts from "../components/toast/toasts.tsx";
10
+ import styles from "../theme/defaultTheme.module.scss";
11
+ import React from "react";
12
+ import LevelContext from "./level.tsx";
13
+
14
+ const UIKitRoot: React.FC<{ children: React.ReactNode | React.ReactNode[] }> = (props) => {
15
+ return (
16
+ <div className={clippy(styles.theme, styles.level0, isMobileDevice() && styles.mobile)}>
17
+ <ContextMenuRoot>
18
+ <Toasts>
19
+ <LevelContext.Provider value={0}>{props.children}</LevelContext.Provider>
20
+ </Toasts>
21
+ </ContextMenuRoot>
22
+ </div>
23
+ );
24
+ };
25
+
26
+ export default UIKitRoot;
package/core/toast.ts CHANGED
@@ -1,17 +1,18 @@
1
- /*
2
- * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
- * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
- */
5
-
6
- import React from "react";
7
- import ToastContext from "../components/toast/toastContext.js";
8
-
9
- export default function useToast() {
10
- const toastCtx = React.useContext(ToastContext);
11
-
12
- return {
13
- create(data: { type: "success" | "error" | "warning" | "info"; content: string; persist?: boolean }) {
14
- toastCtx.showToast(data);
15
- },
16
- };
17
- }
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import React from "react";
7
+ import Toast from "../components/toast/toast.ts";
8
+ import ToastContext from "../components/toast/toastContext.ts";
9
+
10
+ export default function useToast() {
11
+ const toastCtx = React.useContext(ToastContext);
12
+
13
+ return {
14
+ create(data: Toast) {
15
+ toastCtx.showToast(data);
16
+ },
17
+ };
18
+ }
package/imports.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ /*
2
+ * Copyright ©2023 @Ewsgit and YourDash contributors.
3
+ * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
+ */
5
+
6
+ // Declare common file imports as shared for the Typescript Language Server
7
+
8
+ declare module "*.module.css" {
9
+ const content: { [className: string]: string };
10
+ export default content;
11
+ }
12
+
13
+ declare module "*.module.scss" {
14
+ const content: { [className: string]: string };
15
+ export default content;
16
+ }
17
+
18
+ declare module "*.jpg" {
19
+ const value: string;
20
+ export default value;
21
+ }
22
+
23
+ declare module "*.png" {
24
+ const value: string;
25
+ export default value;
26
+ }
27
+
28
+ declare module "*.svg" {
29
+ const value: string;
30
+ export default value;
31
+ }
32
+
33
+ declare module "*.avif" {
34
+ const value: string;
35
+ export default value;
36
+ }
37
+
38
+ declare module "*.css" {
39
+ const value: string;
40
+ export default value;
41
+ }
42
+
43
+ declare module "*.scss" {
44
+ const value: string;
45
+ export default value;
46
+ }
47
+
48
+ declare module "*.json" {
49
+ const content: { [className: string]: string };
50
+ export default content;
51
+ }
52
+
53
+ declare module "*.obj" {
54
+ const value: string;
55
+ export default value;
56
+ }
57
+
58
+ declare module "*.glb" {
59
+ const value: string;
60
+ export default value;
61
+ }
62
+
63
+ declare module "*.gltf" {
64
+ const value: string;
65
+ export default value;
66
+ }
67
+
68
+ declare module "*.md" {
69
+ const value: string;
70
+ export default value;
71
+ }
72
+
73
+ declare module "*.mdx" {
74
+ const value: string;
75
+ export default value;
76
+ }
77
+
78
+ declare module "*.wasm" {
79
+ const value: string;
80
+ export default value;
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yourdash/uikit",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "engines": {
@@ -8,44 +8,13 @@
8
8
  },
9
9
  "author": "Ewsgit <ewsgit@duck.com>",
10
10
  "dependencies": {
11
- "@loadable/component": "^5.15.3",
12
- "@remix-run/router": "^1.15.3",
13
- "@tailwindcss/container-queries": "^0.1.1",
14
- "@types/express": "^4.17.21",
15
- "@types/loadable__component": "^5.13.7",
16
- "@types/minimist": "^1.2.2",
17
- "@types/node": "^20.1.4",
18
- "@types/path-browserify": "^1.0.0",
19
- "@types/react": "^18.2.21",
20
- "@types/react-dom": "^18.2.7",
21
- "@typescript-eslint/eslint-plugin": "^5.59.11",
22
- "@typescript-eslint/parser": "^5.59.11",
23
- "@vitejs/plugin-react-swc": "^3.3.2",
24
- "animate.css": "^4.1.1",
25
- "autoprefixer": "^10.4.15",
26
- "clsx": "^2.0.0",
27
- "concurrently": "^8.2.2",
28
- "cross-env": "^7.0.3",
29
- "es-abstract": "^1.22.1",
30
- "eslint": "^8.47.0",
31
- "minimist": "^1.2.8",
32
- "path": "^0.12.7",
33
- "path-browserify": "^1.0.1",
34
- "path-to-regexp": "^6.2.1",
35
- "postcss": "^8.4.27",
36
11
  "react": "^18.3.1",
37
- "react-dom": "^18.2.0",
38
- "react-router": "^6.15.0",
39
- "react-router-dom": "^6.15.0",
40
- "sass": "^1.65.1",
41
- "socket.io-client": "^4.6.1",
42
- "type-fest": "^4.14.0",
43
- "typescript": "^5.0.4",
44
- "vite": "^4.4.9",
45
- "vite-plugin-dynamic-import": "^1.5.0",
46
- "web-tree-sitter": "^0.20.8",
47
- "xml2js": "^0.6.2",
48
- "yarn": "^1.22.19",
49
- "@yourdash/shared": "^1.0.0"
12
+ "react-dom": "^18.3.1",
13
+ "@types/react": "^18.3.5",
14
+ "@types/react-dom": "^18.3.0",
15
+ "typescript": "^5.6.2",
16
+ "sass": "^1.78.0",
17
+ "vite": "^5.4.5",
18
+ "@yourdash/shared": "workspace:*"
50
19
  }
51
- }
20
+ }
@@ -6,14 +6,23 @@
6
6
  @import "./themeValues";
7
7
 
8
8
  .theme {
9
+ overflow-x: hidden;
10
+ overflow-y: auto;
11
+ height: 100%;
12
+
13
+ background: var(#{$theme+$background});
9
14
  #{$theme}-author: "Ewsgit";
10
15
  #{$theme}-name: "YourDash Classic Dark";
11
16
  #{$theme}-version: "0.0.1";
12
17
 
13
- background: var(#{$theme+$background});
14
- height: 100%;
15
- overflow-x: hidden;
16
- overflow-y: auto;
18
+ ::-webkit-scrollbar {
19
+ width: var(#{$theme+$scrollbar+$width});
20
+ border-radius: 0;
21
+ }
22
+
23
+ ::-webkit-scrollbar-thumb {
24
+ border-radius: var(#{$theme+$scrollbar+$radius});
25
+ }
17
26
  }
18
27
 
19
28
  .level0 {
@@ -28,8 +37,11 @@
28
37
  #{$theme+$padding}: 1rem;
29
38
  #{$theme+$gap}: 0.5rem;
30
39
  #{$theme+$transition}: all 200ms ease-in-out;
40
+ #{$theme+$transition+$transition}: 200ms ease-in-out;
31
41
  #{$theme+$separator+$size}: 0.125rem;
32
42
  #{$theme+$separator+$color}: #444444;
43
+ #{$theme+$scrollbar+$width}: 0.4rem;
44
+ #{$theme+$scrollbar+$radius}: 0.1rem;
33
45
 
34
46
  // heading
35
47
  #{$theme+$heading+$h1+$weight}: 900;
@@ -15,16 +15,17 @@ $subcolor: "scl";
15
15
  $color: "col";
16
16
  $background: "bgn";
17
17
  $gap: "gap";
18
- $transition: "trn";
19
- $font: "fnt";
20
- $size: "siz";
18
+ $transition: "trans";
19
+ $font: "font";
20
+ $size: "size";
21
21
  $weight: "wgt";
22
22
  $family: "fam";
23
- $vertical: "vrt";
24
- $horizontal: "hrt";
23
+ $vertical: "vert";
24
+ $horizontal: "horiz";
25
25
  $header: "hed";
26
26
  $separator: "sep";
27
27
  $height: "hei";
28
+ $width: "wid";
28
29
  $heading: "hed";
29
30
  $input: "inp";
30
31
  $focus: "foc";
@@ -35,6 +36,8 @@ $h3: "he3";
35
36
  $h4: "he4";
36
37
  $h5: "he5";
37
38
  $h6: "he6";
39
+ $scrollbar: "scrlbr";
40
+
38
41
 
39
42
  $sizeMobile: 440px;
40
43
  $sizeLargeMobile: 560px;
package/tsconfig.json CHANGED
@@ -1,20 +1,30 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "strict": true,
4
3
  "target": "ESNext",
5
4
  "module": "ESNext",
6
- "moduleResolution": "node",
5
+ "useDefineForClassFields": true,
6
+ "lib": [
7
+ "DOM",
8
+ "DOM.Iterable",
9
+ "ESNext"
10
+ ],
11
+ "allowJs": false,
12
+ "skipLibCheck": true,
13
+ "esModuleInterop": false,
7
14
  "allowSyntheticDefaultImports": true,
8
- "esModuleInterop": true,
9
- "jsx": "preserve",
10
- "jsxImportSource": "react",
11
- "types": ["vite/client"],
12
- "noEmit": true,
15
+ "strict": true,
16
+ "forceConsistentCasingInFileNames": true,
17
+ "resolveJsonModule": true,
18
+ "moduleResolution": "bundler",
19
+ "allowImportingTsExtensions": true,
13
20
  "isolatedModules": true,
21
+ "moduleDetection": "force",
22
+ "noEmit": true,
23
+ "jsx": "react-jsx"
14
24
  },
15
25
  "include": [
16
26
  "./**/*",
17
- "../applications/**/frontend/**/*",
18
- "../shared/**/*"
27
+ "../shared/**/*",
28
+ "../web"
19
29
  ]
20
30
  }
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
+ * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
+ */
5
+
6
+ import { FC, useEffect, useRef, useState } from "react";
7
+
8
+ const HasBeenShown: FC<{
9
+ className?: string;
10
+ onSeen: () => void;
11
+ }> = ({ className, onSeen }) => {
12
+ const [hasBeenSeen, setHasBeenSeen] = useState(false);
13
+ const ref = useRef<HTMLDivElement>(null);
14
+
15
+ useEffect(() => {
16
+ if (!ref.current) return;
17
+
18
+ const current = ref.current;
19
+
20
+ const observer = new IntersectionObserver((interaction) => {
21
+ if (interaction[0].isIntersecting) {
22
+ onSeen();
23
+ observer.disconnect();
24
+ setHasBeenSeen(true);
25
+ }
26
+ });
27
+
28
+ observer.observe(current);
29
+
30
+ return () => {
31
+ observer.disconnect();
32
+ };
33
+ }, []);
34
+
35
+ if (hasBeenSeen) {
36
+ return null;
37
+ }
38
+
39
+ return (
40
+ <div
41
+ ref={ref}
42
+ className={className}
43
+ />
44
+ );
45
+ };
46
+
47
+ export default HasBeenShown;
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://github.com/ewsgit> and YourDash<https://github.com/yourdash> contributors.
3
+ * YourDash is licensed under the MIT License. (https://ewsgit.mit-license.org)
4
+ */
5
+
6
+ import { FC, useEffect, useRef } from "react";
7
+
8
+ const OnInView: FC<{
9
+ className?: string;
10
+ onEnterView?: (direction: "up" | "down" | "left" | "right") => void;
11
+ onLeaveView?: (direction: "up" | "down" | "left" | "right") => void;
12
+ }> = ({ className, onEnterView, onLeaveView }) => {
13
+ const isInView = useRef(false);
14
+ const ref = useRef<HTMLDivElement>(null);
15
+
16
+ useEffect(() => {
17
+ if (!ref.current) return;
18
+
19
+ const current = ref.current;
20
+
21
+ const handleScroll = () => {
22
+ const { top, bottom, left, right } = current.getBoundingClientRect();
23
+
24
+ if (!isInView.current) {
25
+ if (top < 0) {
26
+ onEnterView?.("up");
27
+ isInView.current = true;
28
+ return;
29
+ } else if (bottom > window.innerHeight) {
30
+ onEnterView?.("down");
31
+ isInView.current = true;
32
+ return;
33
+ } else if (left < 0) {
34
+ onEnterView?.("left");
35
+ isInView.current = true;
36
+ return;
37
+ } else if (right > window.innerWidth) {
38
+ onEnterView?.("right");
39
+ isInView.current = true;
40
+ return;
41
+ }
42
+ }
43
+
44
+ if (top > window.innerHeight) {
45
+ onLeaveView?.("down");
46
+ isInView.current = false;
47
+ return;
48
+ } else if (bottom < 0) {
49
+ onLeaveView?.("up");
50
+ isInView.current = false;
51
+ return;
52
+ } else if (left > window.innerWidth) {
53
+ onLeaveView?.("right");
54
+ isInView.current = false;
55
+ return;
56
+ } else if (right < 0) {
57
+ onLeaveView?.("left");
58
+ isInView.current = false;
59
+ return;
60
+ }
61
+ };
62
+
63
+ const observer = new IntersectionObserver(() => {
64
+ handleScroll();
65
+ });
66
+
67
+ observer.observe(current);
68
+
69
+ return () => {
70
+ observer.disconnect();
71
+ };
72
+ }, []);
73
+
74
+ return (
75
+ <div
76
+ ref={ref}
77
+ style={{ height: 1, width: 1 }}
78
+ className={className}
79
+ />
80
+ );
81
+ };
82
+
83
+ export default OnInView;