@teselagen/ui 0.0.11 → 0.0.13

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 (125) hide show
  1. package/README.md +7 -0
  2. package/cypress.config.ts +6 -0
  3. package/index.html +12 -0
  4. package/package.json +5 -11
  5. package/project.json +74 -0
  6. package/src/AdvancedOptions.js +33 -0
  7. package/src/AdvancedOptions.spec.js +24 -0
  8. package/src/AssignDefaultsModeContext.js +21 -0
  9. package/src/AsyncValidateFieldSpinner/index.js +12 -0
  10. package/src/BlueprintError/index.js +14 -0
  11. package/src/BounceLoader/index.js +16 -0
  12. package/src/BounceLoader/style.css +45 -0
  13. package/src/CollapsibleCard/index.js +92 -0
  14. package/src/CollapsibleCard/style.css +21 -0
  15. package/src/DNALoader/index.js +20 -0
  16. package/src/DNALoader/style.css +251 -0
  17. package/src/DataTable/CellDragHandle.js +130 -0
  18. package/src/DataTable/DisabledLoadingComponent.js +15 -0
  19. package/src/DataTable/DisplayOptions.js +218 -0
  20. package/src/DataTable/FilterAndSortMenu.js +397 -0
  21. package/src/DataTable/PagingTool.js +232 -0
  22. package/src/DataTable/SearchBar.js +57 -0
  23. package/src/DataTable/SortableColumns.js +53 -0
  24. package/src/DataTable/TableFormTrackerContext.js +10 -0
  25. package/src/DataTable/dataTableEnhancer.js +291 -0
  26. package/src/DataTable/defaultFormatters.js +32 -0
  27. package/src/DataTable/defaultProps.js +45 -0
  28. package/src/DataTable/defaultValidators.js +40 -0
  29. package/src/DataTable/editCellHelper.js +44 -0
  30. package/src/DataTable/getCellVal.js +20 -0
  31. package/src/DataTable/getVals.js +8 -0
  32. package/src/DataTable/index.js +3537 -0
  33. package/src/DataTable/isTruthy.js +12 -0
  34. package/src/DataTable/isValueEmpty.js +3 -0
  35. package/src/DataTable/style.css +600 -0
  36. package/src/DataTable/utils/computePresets.js +42 -0
  37. package/src/DataTable/utils/convertSchema.js +69 -0
  38. package/src/DataTable/utils/getIdOrCodeOrIndex.js +9 -0
  39. package/src/DataTable/utils/getTableConfigFromStorage.js +5 -0
  40. package/src/DataTable/utils/queryParams.js +1032 -0
  41. package/src/DataTable/utils/rowClick.js +156 -0
  42. package/src/DataTable/utils/selection.js +8 -0
  43. package/src/DataTable/utils/withSelectedEntities.js +65 -0
  44. package/src/DataTable/utils/withTableParams.js +328 -0
  45. package/src/DataTable/validateTableWideErrors.js +135 -0
  46. package/src/DataTable/viewColumn.js +37 -0
  47. package/src/DialogFooter/index.js +79 -0
  48. package/src/DialogFooter/style.css +9 -0
  49. package/src/DropdownButton.js +36 -0
  50. package/src/FillWindow.css +6 -0
  51. package/src/FillWindow.js +69 -0
  52. package/src/FormComponents/Uploader.js +1197 -0
  53. package/src/FormComponents/getNewName.js +31 -0
  54. package/src/FormComponents/index.js +1384 -0
  55. package/src/FormComponents/itemUpload.js +84 -0
  56. package/src/FormComponents/sortify.js +73 -0
  57. package/src/FormComponents/style.css +247 -0
  58. package/src/FormComponents/tryToMatchSchemas.js +222 -0
  59. package/src/FormComponents/utils.js +6 -0
  60. package/src/HotkeysDialog/index.js +79 -0
  61. package/src/HotkeysDialog/style.css +54 -0
  62. package/src/InfoHelper/index.js +83 -0
  63. package/src/InfoHelper/style.css +7 -0
  64. package/src/IntentText/index.js +18 -0
  65. package/src/Loading/index.js +74 -0
  66. package/src/Loading/style.css +4 -0
  67. package/src/MatchHeaders.js +223 -0
  68. package/src/MenuBar/index.js +416 -0
  69. package/src/MenuBar/style.css +45 -0
  70. package/src/PromptUnsavedChanges/index.js +40 -0
  71. package/src/ResizableDraggableDialog/index.js +138 -0
  72. package/src/ResizableDraggableDialog/style.css +42 -0
  73. package/src/ScrollToTop/index.js +72 -0
  74. package/src/SimpleStepViz.js +26 -0
  75. package/src/TgSelect/index.js +465 -0
  76. package/src/TgSelect/style.css +34 -0
  77. package/src/TgSuggest/index.js +121 -0
  78. package/src/Timeline/TimelineEvent.js +31 -0
  79. package/src/Timeline/index.js +22 -0
  80. package/src/Timeline/style.css +29 -0
  81. package/src/UploadCsvWizard.css +4 -0
  82. package/src/UploadCsvWizard.js +731 -0
  83. package/src/autoTooltip.js +89 -0
  84. package/src/constants.js +1 -0
  85. package/src/customIcons.js +361 -0
  86. package/src/enhancers/withDialog/index.js +196 -0
  87. package/src/enhancers/withDialog/tg_modalState.js +46 -0
  88. package/src/enhancers/withField.js +20 -0
  89. package/src/enhancers/withFields.js +11 -0
  90. package/src/enhancers/withLocalStorage.js +11 -0
  91. package/src/index.js +76 -0
  92. package/src/rerenderOnWindowResize.js +27 -0
  93. package/src/showAppSpinner.js +12 -0
  94. package/src/showConfirmationDialog/index.js +116 -0
  95. package/src/showDialogOnDocBody.js +37 -0
  96. package/src/style.css +214 -0
  97. package/src/toastr.js +92 -0
  98. package/src/typeToCommonType.js +6 -0
  99. package/src/useDialog.js +64 -0
  100. package/src/utils/S3Download.js +14 -0
  101. package/src/utils/adHoc.js +10 -0
  102. package/src/utils/basicHandleActionsWithFullState.js +14 -0
  103. package/src/utils/combineReducersWithFullState.js +14 -0
  104. package/src/utils/commandControls.js +83 -0
  105. package/src/utils/commandUtils.js +112 -0
  106. package/src/utils/determineBlackOrWhiteTextColor.js +4 -0
  107. package/src/utils/getDayjsFormatter.js +35 -0
  108. package/src/utils/getTextFromEl.js +28 -0
  109. package/src/utils/handlerHelpers.js +30 -0
  110. package/src/utils/hotkeyUtils.js +129 -0
  111. package/src/utils/menuUtils.js +402 -0
  112. package/src/utils/popoverOverflowModifiers.js +11 -0
  113. package/src/utils/pureNoFunc.js +31 -0
  114. package/src/utils/renderOnDoc.js +29 -0
  115. package/src/utils/showProgressToast.js +22 -0
  116. package/src/utils/tagUtils.js +45 -0
  117. package/src/utils/tgFormValues.js +32 -0
  118. package/src/utils/withSelectTableRecords.js +38 -0
  119. package/src/utils/withStore.js +10 -0
  120. package/src/wrapDialog.js +112 -0
  121. package/tsconfig.json +4 -0
  122. package/vite.config.ts +7 -0
  123. package/index.mjs +0 -109378
  124. package/index.umd.js +0 -109381
  125. package/style.css +0 -10421
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # ui
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Running unit tests
6
+
7
+ Run `nx test ui` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,6 @@
1
+ import cypress from "../../cypress.config";
2
+
3
+ export default cypress({
4
+ name: "ui",
5
+ projectId: "gwixeq"
6
+ });
package/index.html ADDED
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>ui demo</title>
6
+ <script src="./demo/index.js" type="module"></script>
7
+ </head>
8
+ <body>
9
+ <link rel="stylesheet" href="/style.css" />
10
+ <div id="app"><div id="demo"></div></div>
11
+ </body>
12
+ </html>
package/package.json CHANGED
@@ -1,13 +1,7 @@
1
1
  {
2
2
  "name": "@teselagen/ui",
3
- "version": "0.0.11",
4
- "main": "./index.js",
5
- "types": "./index.d.ts",
6
- "type": "commonjs",
7
- "exports": {
8
- ".": {
9
- "import": "./index.mjs",
10
- "require": "./index.js"
11
- }
12
- }
13
- }
3
+ "version": "0.0.13",
4
+ "main": "./src/index.js",
5
+ "type": "module"
6
+
7
+ }
package/project.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "ui",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/ui/src",
5
+ "projectType": "library",
6
+ "tags": [],
7
+ "targets": {
8
+ "lint": {
9
+ "executor": "@nx/linter:eslint",
10
+ "outputs": ["{options.outputFile}"],
11
+ "options": {
12
+ "lintFilePatterns": ["packages/ui/**/*.{ts,tsx,js,jsx}"]
13
+ }
14
+ },
15
+ "publish": {
16
+ "command": "node tools/scripts/publish.mjs ui {args.ver} {args.tag}",
17
+ "dependsOn": ["test", "build"]
18
+ },
19
+ "build": {
20
+ "command": "cd packages/ui && vite build --mode={args.mode}",
21
+ "configurations": {
22
+ "demo": {
23
+ "args": "--mode=demo"
24
+ }
25
+ }
26
+ },
27
+ "pushToGhPages": {
28
+ //tnw: waiting for https://github.com/nrwl/nx/issues/15064 to be able to work with "build:demo"
29
+ "dependsOn": ["build:demo"],
30
+ "command": "yarn gh-pages -a -d demo-dist"
31
+ },
32
+ "start": {
33
+ "executor": "nx:run-commands",
34
+ "options": {
35
+ "commands": ["cd packages/ui && yarn vite"]
36
+ },
37
+ "configurations": {
38
+ "ci": {
39
+ "readyWhen": "ready in"
40
+ }
41
+ }
42
+ },
43
+ "launch-e2e": {
44
+ "executor": "@nx/cypress:cypress",
45
+ "options": {
46
+ "watch": true,
47
+ "headed": true,
48
+ "browser": "chrome",
49
+ "cypressConfig": "packages/ui/cypress.config.ts",
50
+ "devServerTarget": "ui:start:ci",
51
+ "testingType": "e2e"
52
+ }
53
+ },
54
+ "e2e": {
55
+ "executor": "@nx/cypress:cypress",
56
+ "options": {
57
+ "parallel": true,
58
+ "key": "1ced39be-1a3a-4fd8-b2d5-a88951d9b766",
59
+ "record": true,
60
+ "cypressConfig": "packages/ui/cypress.config.ts",
61
+ "devServerTarget": "ui:start:ci",
62
+ "testingType": "e2e"
63
+ },
64
+ "configurations": {
65
+ "dev": {
66
+ "parallel": false
67
+ }
68
+ }
69
+ },
70
+ "test": {
71
+ "command": "cd packages/ui && yarn vitest run --changed --config vite.config.ts"
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,33 @@
1
+ import React, { useState } from "react";
2
+ import { Icon } from "@blueprintjs/core";
3
+
4
+ export default function AdvancedOptions({
5
+ children,
6
+ content,
7
+ label,
8
+ style,
9
+ isOpenByDefault
10
+ }) {
11
+ const [isOpen, setOpen] = useState(isOpenByDefault);
12
+ if (!(content || children)) {
13
+ return null;
14
+ }
15
+ return (
16
+ <div style={{ marginTop: 5, ...style }}>
17
+ <div
18
+ onClick={() => {
19
+ setOpen(!isOpen);
20
+ }}
21
+ style={{ cursor: "pointer", display: "flex", alignItems: "flex-end" }}
22
+ className="tg-toggle-advanced-options"
23
+ >
24
+ {label || "Advanced"}{" "}
25
+ <Icon
26
+ icon={isOpen ? "caret-down" : "caret-right"}
27
+ style={{ marginLeft: 5 }}
28
+ ></Icon>
29
+ </div>
30
+ {isOpen && <div style={{ marginTop: 10 }}>{content || children}</div>}
31
+ </div>
32
+ );
33
+ }
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { render, fireEvent } from "@testing-library/react";
3
+ import AdvancedOptions from "./AdvancedOptions";
4
+
5
+ describe("AdvancedOptions", () => {
6
+ test("renders correctly with given props and default state", () => {
7
+ const { queryByText, container } = render(
8
+ <AdvancedOptions label="Test Label" content="Test Content" />
9
+ );
10
+ expect(queryByText("Test Label")).toBeInTheDocument();
11
+ expect(queryByText("Test Content")).not.toBeInTheDocument();
12
+
13
+ expect(container.querySelector(".bp3-icon-caret-right")).toBeInTheDocument();
14
+ });
15
+
16
+ test("toggles content when clicked", () => {
17
+ const { getByText, queryByText, container } = render(
18
+ <AdvancedOptions label="Test Label" content="Test Content" />
19
+ );
20
+ fireEvent.click(getByText("Test Label"));
21
+ expect(queryByText("Test Content")).toBeInTheDocument();
22
+ expect(container.querySelector(".bp3-icon-caret-down")).toBeInTheDocument();
23
+ });
24
+ });
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+
3
+ export const AssignDefaultsModeContext = React.createContext({
4
+ inAssignDefaultsMode: false,
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
6
+ setAssignDefaultsMode: () => {}
7
+ });
8
+
9
+ export const workflowDefaultParamsObj = {
10
+ taskNumber: undefined,
11
+ workflowDefinitionName: undefined,
12
+ workflowDefinitionId: undefined,
13
+ workflowRunName: undefined,
14
+ workflowRunId: undefined,
15
+ toolName: undefined,
16
+ workflowToolTitle: undefined,
17
+ workflowTaskCode: undefined
18
+ };
19
+ export const WorkflowDefaultParamsContext = React.createContext(
20
+ workflowDefaultParamsObj
21
+ );
@@ -0,0 +1,12 @@
1
+ /* Copyright (C) 2018 TeselaGen Biotechnology, Inc. */
2
+
3
+ import React from "react";
4
+ import { Spinner } from "@blueprintjs/core";
5
+
6
+ export default function AsyncValidateFieldSpinner({ validating }) {
7
+ if (validating) {
8
+ return <Spinner size="18" />;
9
+ } else {
10
+ return null;
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { Classes } from "@blueprintjs/core";
3
+ import classNames from "classnames";
4
+
5
+ export default function BlueprintError({ error }) {
6
+ if (!error) return null;
7
+ return (
8
+ <div className={classNames(Classes.FORM_GROUP, Classes.INTENT_DANGER)}>
9
+ <div className={classNames(Classes.FORM_HELPER_TEXT, "preserve-newline")}>
10
+ {error}
11
+ </div>
12
+ </div>
13
+ );
14
+ }
@@ -0,0 +1,16 @@
1
+ /* taken from http://tobiasahlin.com/spinkit/ */
2
+ import React from "react";
3
+ import classNames from "classnames";
4
+ import "./style.css";
5
+
6
+ export default function BounceLoader({ style, className }) {
7
+ return (
8
+ <div className={classNames("tg-bounce-loader", className)} style={style}>
9
+ <div className="rect1" />
10
+ <div className="rect2" />
11
+ <div className="rect3" />
12
+ <div className="rect4" />
13
+ <div className="rect5" />
14
+ </div>
15
+ );
16
+ }
@@ -0,0 +1,45 @@
1
+ .tg-bounce-loader {
2
+ width: 50px;
3
+ height: 40px;
4
+ text-align: center;
5
+ font-size: 10px;
6
+ display: flex;
7
+ align-items: center;
8
+ }
9
+
10
+ .tg-bounce-loader > div {
11
+ background-color: #006cab;
12
+ height: 100%;
13
+ max-height: 30px;
14
+ width: 6px;
15
+ display: inline-block;
16
+ margin-right: 3px;
17
+ animation: sk-stretchdelay 1.2s infinite ease-in-out;
18
+ }
19
+
20
+ .tg-bounce-loader .rect2 {
21
+ animation-delay: -1.1s;
22
+ }
23
+
24
+ .tg-bounce-loader .rect3 {
25
+ animation-delay: -1s;
26
+ }
27
+
28
+ .tg-bounce-loader .rect4 {
29
+ animation-delay: -0.9s;
30
+ }
31
+
32
+ .tg-bounce-loader .rect5 {
33
+ animation-delay: -0.8s;
34
+ }
35
+
36
+ @keyframes sk-stretchdelay {
37
+ 0%,
38
+ 40%,
39
+ 100% {
40
+ transform: scaleY(0.4);
41
+ }
42
+ 20% {
43
+ transform: scaleY(1);
44
+ }
45
+ }
@@ -0,0 +1,92 @@
1
+ import React, { Component } from "react";
2
+ import { Button, Classes, Icon } from "@blueprintjs/core";
3
+ import classNames from "classnames";
4
+ import "./style.css";
5
+
6
+ export default class CollapsibleCard extends Component {
7
+ state = {
8
+ open: true
9
+ };
10
+
11
+ constructor(props) {
12
+ super(props);
13
+ this.state = {
14
+ open: !props.initialClosed
15
+ };
16
+ }
17
+
18
+ renderOpenCard() {
19
+ return this.props.children;
20
+ }
21
+
22
+ toggleCardInfo = () => {
23
+ if (this.props.toggle) this.props.toggle();
24
+ else {
25
+ this.setState({
26
+ open: !this.state.open
27
+ });
28
+ }
29
+ };
30
+
31
+ getIsOpen = () => {
32
+ if (this.props.isOpen !== undefined) {
33
+ return this.props.isOpen;
34
+ } else {
35
+ return this.state.open;
36
+ }
37
+ };
38
+
39
+ render() {
40
+ const open = this.getIsOpen();
41
+ const {
42
+ title,
43
+ icon,
44
+ openTitleElements,
45
+ noCard = false,
46
+ className,
47
+ style
48
+ } = this.props;
49
+
50
+ // blueprintjs card will match our table color. which looks really bad when a table is in a card.
51
+ return (
52
+ <div
53
+ className={classNames({ "tg-card": !noCard, open }, className)}
54
+ style={{
55
+ paddingTop: 10,
56
+ paddingBottom: 10,
57
+ paddingLeft: 15,
58
+ paddingRight: 15,
59
+ ...style
60
+ }}
61
+ >
62
+ <div className="tg-card-header" style={{ marginBottom: 8 }}>
63
+ <div className="tg-card-header-title">
64
+ {icon && <Icon icon={icon} />}
65
+ <h6
66
+ style={{
67
+ marginBottom: 0,
68
+ marginRight: 10,
69
+ marginLeft: 10
70
+ }}
71
+ >
72
+ {title}
73
+ </h6>
74
+ <div>{open && openTitleElements}</div>
75
+ </div>
76
+ <div>
77
+ <Button
78
+ icon={open ? "minimize" : "maximize"}
79
+ className={classNames(
80
+ Classes.MINIMAL,
81
+ "info-btn",
82
+ "tg-collapse-toggle"
83
+ )}
84
+ onClick={this.toggleCardInfo}
85
+ />
86
+ </div>
87
+ </div>
88
+ {open && this.renderOpenCard()}
89
+ </div>
90
+ );
91
+ }
92
+ }
@@ -0,0 +1,21 @@
1
+ /* Use in the place of .bp3-card */
2
+ .tg-card {
3
+ padding: 20px;
4
+ margin-bottom: 20px;
5
+ border-radius: 5px;
6
+ background: white;
7
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.18);
8
+ }
9
+
10
+ .tg-card-header {
11
+ display: flex;
12
+ flex-direction: row;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ }
16
+
17
+ .tg-card-header-title {
18
+ display: flex;
19
+ flex-direction: row;
20
+ align-items: center;
21
+ }
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import classNames from "classnames";
3
+ import "./style.css";
4
+
5
+ export default function DNALoader({ style, className }) {
6
+ return (
7
+ <div className={classNames("dna-loader", className)} style={style}>
8
+ <div className="nucleobase" />
9
+ <div className="nucleobase" />
10
+ <div className="nucleobase" />
11
+ <div className="nucleobase" />
12
+ <div className="nucleobase" />
13
+ <div className="nucleobase" />
14
+ <div className="nucleobase" />
15
+ <div className="nucleobase" />
16
+ <div className="nucleobase" />
17
+ <div className="nucleobase" />
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1,251 @@
1
+ .dna-loader {
2
+ display: inline-block;
3
+ position: relative;
4
+ transform: scale(0.45);
5
+ }
6
+
7
+ .nucleobase {
8
+ display: inline-block;
9
+ position: relative;
10
+ vertical-align: middle;
11
+ }
12
+
13
+ .nucleobase:not(:last-child) {
14
+ margin-right: 4.86vh;
15
+ }
16
+
17
+ .nucleobase:before,
18
+ .nucleobase:after {
19
+ content: "";
20
+ display: inline-block;
21
+ width: 3vh;
22
+ height: 3vh;
23
+ border-radius: 50%;
24
+ position: absolute;
25
+ }
26
+
27
+ .nucleobase:nth-child(10) {
28
+ animation-delay: -1.869s;
29
+ }
30
+
31
+ .nucleobase:nth-child(10):before {
32
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
33
+ animation-delay: -1.869s;
34
+ background-color: #339bb9;
35
+ }
36
+
37
+ .nucleobase:nth-child(10):after {
38
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
39
+ animation-delay: -1.869s;
40
+ background-color: #006cab;
41
+ }
42
+
43
+ .nucleobase:nth-child(9) {
44
+ animation-delay: -3.738s;
45
+ }
46
+
47
+ .nucleobase:nth-child(9):before {
48
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
49
+ animation-delay: -3.738s;
50
+ background-color: #339bb9;
51
+ }
52
+
53
+ .nucleobase:nth-child(9):after {
54
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
55
+ animation-delay: -3.738s;
56
+ background-color: #006cab;
57
+ }
58
+
59
+ .nucleobase:nth-child(8) {
60
+ animation-delay: -5.607s;
61
+ }
62
+
63
+ .nucleobase:nth-child(8):before {
64
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
65
+ animation-delay: -5.607s;
66
+ background-color: #339bb9;
67
+ }
68
+
69
+ .nucleobase:nth-child(8):after {
70
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
71
+ animation-delay: -5.607s;
72
+ background-color: #006cab;
73
+ }
74
+
75
+ .nucleobase:nth-child(7) {
76
+ animation-delay: -7.476s;
77
+ }
78
+
79
+ .nucleobase:nth-child(7):before {
80
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
81
+ animation-delay: -7.476s;
82
+ background-color: #339bb9;
83
+ }
84
+
85
+ .nucleobase:nth-child(7):after {
86
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
87
+ animation-delay: -7.476s;
88
+ background-color: #006cab;
89
+ }
90
+
91
+ .nucleobase:nth-child(6) {
92
+ animation-delay: -9.345s;
93
+ }
94
+
95
+ .nucleobase:nth-child(6):before {
96
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
97
+ animation-delay: -9.345s;
98
+ background-color: #339bb9;
99
+ }
100
+
101
+ .nucleobase:nth-child(6):after {
102
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
103
+ animation-delay: -9.345s;
104
+ background-color: #006cab;
105
+ }
106
+
107
+ .nucleobase:nth-child(5) {
108
+ animation-delay: -11.214s;
109
+ }
110
+
111
+ .nucleobase:nth-child(5):before {
112
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
113
+ animation-delay: -11.214s;
114
+ background-color: #339bb9;
115
+ }
116
+
117
+ .nucleobase:nth-child(5):after {
118
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
119
+ animation-delay: -11.214s;
120
+ background-color: #006cab;
121
+ }
122
+
123
+ .nucleobase:nth-child(4) {
124
+ animation-delay: -13.083s;
125
+ }
126
+
127
+ .nucleobase:nth-child(4):before {
128
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
129
+ animation-delay: -13.083s;
130
+ background-color: #339bb9;
131
+ }
132
+
133
+ .nucleobase:nth-child(4):after {
134
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
135
+ animation-delay: -13.083s;
136
+ background-color: #006cab;
137
+ }
138
+
139
+ .nucleobase:nth-child(3) {
140
+ animation-delay: -14.952s;
141
+ }
142
+
143
+ .nucleobase:nth-child(3):before {
144
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
145
+ animation-delay: -14.952s;
146
+ background-color: #339bb9;
147
+ }
148
+
149
+ .nucleobase:nth-child(3):after {
150
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
151
+ animation-delay: -14.952s;
152
+ background-color: #006cab;
153
+ }
154
+
155
+ .nucleobase:nth-child(2) {
156
+ animation-delay: -16.821s;
157
+ }
158
+
159
+ .nucleobase:nth-child(2):before {
160
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
161
+ animation-delay: -16.821s;
162
+ background-color: #339bb9;
163
+ }
164
+
165
+ .nucleobase:nth-child(2):after {
166
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
167
+ animation-delay: -16.821s;
168
+ background-color: #006cab;
169
+ }
170
+
171
+ .nucleobase:nth-child(1) {
172
+ animation-delay: -18.69s;
173
+ }
174
+
175
+ .nucleobase:nth-child(1):before {
176
+ animation: animBefore 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
177
+ animation-delay: -18.69s;
178
+ background-color: #339bb9;
179
+ }
180
+
181
+ .nucleobase:nth-child(1):after {
182
+ animation: animAfter 2.1s cubic-bezier(0.42, 0, 0.58, 1) infinite;
183
+ animation-delay: -18.69s;
184
+ background-color: #006cab;
185
+ }
186
+
187
+ @keyframes animBefore {
188
+ 0% {
189
+ top: -6vh;
190
+ z-index: 1;
191
+ }
192
+ 25% {
193
+ transform: scale(1.2);
194
+ z-index: 1;
195
+ }
196
+ 50% {
197
+ top: 6vh;
198
+ z-index: -1;
199
+ }
200
+ 75% {
201
+ background-color: #5bc0de;
202
+ transform: scale(0.8);
203
+ z-index: -1;
204
+ }
205
+ 100% {
206
+ top: -6vh;
207
+ z-index: -1;
208
+ }
209
+ }
210
+
211
+ @keyframes animAfter {
212
+ 0% {
213
+ top: 6vh;
214
+ z-index: -1;
215
+ }
216
+ 25% {
217
+ background-color: #055e75;
218
+ transform: scale(0.8);
219
+ z-index: -1;
220
+ }
221
+ 50% {
222
+ top: -6vh;
223
+ z-index: 1;
224
+ }
225
+ 75% {
226
+ transform: scale(1.2);
227
+ z-index: 1;
228
+ }
229
+ 100% {
230
+ top: 6vh;
231
+ z-index: 1;
232
+ }
233
+ }
234
+
235
+ @keyframes animDotBar {
236
+ 0% {
237
+ height: 8.25vh;
238
+ }
239
+ 25% {
240
+ height: 0;
241
+ }
242
+ 50% {
243
+ height: 8.25vh;
244
+ }
245
+ 75% {
246
+ height: 0;
247
+ }
248
+ 100% {
249
+ height: 8.25vh;
250
+ }
251
+ }