LucaVivona commited on
Commit
67a483e
1 Parent(s): 3115d41

Node Menu Frontend

Browse files
README.md CHANGED
@@ -104,8 +104,11 @@ def InterLauncher(name, interface, listen=2000, **kwargs):
104
 
105
 
106
  ### Frontend 🖥️
107
- - new logo
108
- - appedned colours
 
 
 
109
 
110
  ### In The Works 🚧
111
  - Appending streamlit into gradio-flow
 
104
 
105
 
106
  ### Frontend 🖥️
107
+ - Node Menu
108
+ - Dynamic adjust the size of node
109
+ - Link to gradio to host it in seprate tab
110
+
111
+ ![Node Menu](https://github.com/commune-ai/Gradio-Flow/blob/gradio-flow/gradio-only/new_feature.png)
112
 
113
  ### In The Works 🚧
114
  - Appending streamlit into gradio-flow
frontend/src/Components/Nodes/Custom.js CHANGED
@@ -1,70 +1,106 @@
1
  import React from "react"
2
-
 
 
 
 
3
  export default class CustomNodeIframe extends React.Component {
4
- constructor({data}){
5
  super()
6
  this.myRef = React.createRef()
 
7
  this.state = {
8
- reachable : true,
9
  selected : true,
10
- data : data
 
 
 
11
  }
 
12
  }
13
 
14
  handelSelected = () => {
 
 
 
 
15
  fetch(this.state.data.host, {mode: 'no-cors'}).then((re) => {
16
- this.setState({reachable : true, selected : !this.state.selected, data : this.state.data})
17
  }).catch(()=>{
18
- this.setState({reachable : false, selected : !this.state.selected, data : this.state.data})
19
  })
20
  }
21
 
22
- handelEvent = (e) => {
23
- console.log(e.type)
24
- if(e.type === "mousedown"){
25
- console.log("down")
26
- }
27
- else {
28
- console.log("up")
29
- }
30
 
 
 
31
 
32
  }
33
 
 
 
 
 
 
 
 
 
 
34
 
35
- render(){
36
-
37
- return (
38
- <>
39
- { this.state.selected && this.state.reachable ?
40
- <>
41
- <div className="w-full h-10 top-0 hover:bg-black" onClick={this.handelEvent} onMouseDown={this.handelEvent} onMouseUp={this.handelEvent}>
42
-
43
- </div>
44
 
45
- <div className='relative h-[540px] w-[600px] overflow-hidden m-0 p-0 shadow-2xl' onClick={()=>this.handelSelected()}>
46
- <div className={`absolute h-full w-full ${this.state.data.colour} border-1shadow-2xl shadow-black rounded-xl -z-20`}></div>
47
- <iframe
48
- id="iframe"
49
- ref={this.myRef}
50
- src={this.state.data.host}
51
- title={this.state.data.label}
52
- frameBorder="0" className=" -z-10 container h-full p-2 flex-grow space-iframe overflow-scroll " allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"></iframe>
 
 
53
  </div>
54
- </> :
55
- <>
56
- <div className='break-words'>
57
- <div className=' h-auto text-center pointer-events-none'>
58
- <div className='hexagon pointer-events-auto break-words text-center hover:animate-pulse dark:bg-black dark:text-white' onClick={()=>this.handelSelected()} >
59
- <p className='z-50 pointer-events-none break-words font-sans font-bold'>{this.state.data.label}</p>
60
- </div>
61
- </div>
62
- </div>
63
- </> }
64
-
65
- </>
66
- )
67
  }
 
 
 
 
 
 
 
68
 
69
- }
70
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import React from "react"
2
+ import {TbResize} from 'react-icons/tb'
3
+ import {BiCube} from 'react-icons/bi'
4
+ import {BsTrash} from 'react-icons/bs'
5
+ import {CgLayoutGridSmall} from 'react-icons/cg'
6
+ import '../../css/counter.css'
7
  export default class CustomNodeIframe extends React.Component {
8
+ constructor({id , data}){
9
  super()
10
  this.myRef = React.createRef()
11
+ this.id = id
12
  this.state = {
13
+ reachable : this.handelFetch,
14
  selected : true,
15
+ data : data,
16
+ width : 600,
17
+ height : 540,
18
+ size : false
19
  }
20
+
21
  }
22
 
23
  handelSelected = () => {
24
+ this.setState({reachable : this.state.reachable, selected : !this.state.selected, data : this.state.data, width : this.state.width, height : this.state.height, size : this.state.size})
25
+ }
26
+
27
+ handelFetch = () => {
28
  fetch(this.state.data.host, {mode: 'no-cors'}).then((re) => {
29
+ this.setState({reachable : true, selected : this.state.selected, data : this.state.data, width : this.state.width, height : this.state.height, size : this.state.size})
30
  }).catch(()=>{
31
+ this.setState({reachable : false, selected : this.state.selected, data : this.state.data, width : this.state.width, height : this.state.height, size : this.state.size})
32
  })
33
  }
34
 
35
+ handelSizeState = () => {
36
+ this.setState({reachable : this.state.reachable, selected : this.state.selected, data : this.state.data, width : this.state.width, height : this.state.height, size : !this.state.size})
37
+ }
38
+
39
+ onNodeClick = (id) => {
40
+ this.state.data.delete(id)
41
+ }
 
42
 
43
+ handelOnChange(evt, type){
44
+ this.setState({reachable : this.state.reachable, selected : this.state.selected, data : this.state.data, width : type === "width" ? parseInt(evt.target.value) : this.state.width, height : type === "height" ? parseInt(evt.target.value) : this.state.height, size : this.state.size})
45
 
46
  }
47
 
48
+ handelSize(evt, increment, change){
49
+ console.log(evt,increment)
50
+ if (evt === "Enter"){
51
+ this.setState({reachable : this.state.reachable, selected : this.state.selected, data : this.state.data, width : change === "width" ? increment : this.state.width, height : change === "height" ? increment : this.state.height, size : this.state.size})
52
+ change === "width" ? this.myRef.current.style.width = `${increment}px` : this.myRef.current.style.height = `${increment}px`
53
+ } else if (evt === "increment") {
54
+ this.setState({reachable : this.state.reachable, selected : this.state.selected, data : this.state.data, width : change === "width" ? this.state.width + increment : this.state.width, height : change === "height" ? this.state.height + increment : this.state.height, size : this.state.size})
55
+ change === "width" ? this.myRef.current.style.width = `${parseInt(this.state.width) + increment}px` : this.myRef.current.style.height = `${parseInt(this.state.height) + increment}px`
56
+ }
57
 
58
+ }
 
 
 
 
 
 
 
 
59
 
60
+ Counter(focus, count){
61
+ return (<div className="custom-number-input h-10 w-32 dark:text-white text-black ">
62
+ <div className="flex flex-row h-10 w-full rounded-lg relative bg-transparent">
63
+ <button data-action="decrement" className=" border-2 border-dotted border-fuchsia-300 hover:border-rose-600 rounded-l-xl hover:animate-pulse h-full w-20 cursor-pointer outline-none " onClick={(e)=> {this.handelSize("increment", -5, focus)}}>
64
+ <span className="m-auto text-2xl font-bold">−</span>
65
+ </button>
66
+ <input type="number" className="outline-none focus:outline-none border-fuchsia-300 border-y-2 border-dotted text-center w-full font-semibold text-md focus:from-fuchsia-200 md:text-basecursor-default flex items-cente outline-none bg-transparent" name="input-number" value={count} onChange={(e) => this.handelOnChange(e, focus)} onKeyDown={(e) => {this.handelSize(e.key, count, focus)}}></input>
67
+ <button data-action="increment" className="border-2 border-dotted border-fuchsia-300 hover:border-Green-Emerald rounded-r-xl hover:animate-pulse h-full w-20 cursor-pointer" onClick={(e)=> {this.handelSize("increment", 5, focus)}} >
68
+ <span className="m-auto text-2xl font-bold">+</span>
69
+ </button>
70
  </div>
71
+ </div>)
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
+
74
+ render(){
75
+ return (<>
76
+ { this.state.reachable &&
77
+ <>
78
+ <div className=" flex w-full h-10 top-0 cursor-pointer" onClick={this.handelEvent}>
79
+ <div title="Collaspse Node" className=" duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-black h-10 w-10 mr-2 -mt-3 bg-Warm-Blue rounded-xl" onClick={this.handelSelected}><CgLayoutGridSmall className="h-full w-full text-white p-1"/></div>
80
 
81
+
82
+ <div className={` flex ${this.state.selected ? '' : 'w-0 hidden'}`}>
83
+ <div title="Adjust Node Size" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-black h-10 w-10 mr-2 -mt-3 bg-Warm-Violet rounded-xl" onClick={this.handelSizeState}><TbResize className="h-full w-full text-white p-1"/></div>
84
+ <a href={this.state.data.host} target="_blank" rel="noopener noreferrer"><div title="Gradio Host Site" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-black h-10 w-10 mr-2 -mt-3 bg-Warm-Pink rounded-xl"><BiCube className="h-full w-full text-white p-1"/></div></a>
85
+ <div title="Delete Node" className="duration-300 cursor-pointer shadow-xl border-2 dark:border-white border-black h-10 w-10 mr-2 -mt-3 bg-Warm-Red rounded-xl" onClick={() => this.onNodeClick(this.id)}><BsTrash className="h-full w-full text-white p-1"/></div>
86
+
87
+ { this.state.size && <div className="duration-300 flex w-[60%] h-full mr-2 -mt-3 space-x-4">
88
+ {this.Counter("width", this.state.width)}
89
+ {this.Counter("height", this.state.height)}
90
+ </div>}
91
+ </div>
92
+
93
+ </div>
94
+
95
+ <div className={`relative w-[${this.state.width}px] h-[${this.state.height}px] overflow-hidden m-0 p-0 shadow-2xl`} ref={this.myRef}>
96
+ <div className={`absolute h-full w-full ${this.state.data.colour} border-1shadow-2xl shadow-black rounded-xl -z-20`}></div>
97
+ <iframe
98
+ id="iframe"
99
+ src={this.state.data.host}
100
+ title={this.state.data.label}
101
+ frameBorder="0" className=" -z-10 container h-full p-2 flex-grow space-iframe overflow-scroll " allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-downloads"></iframe>
102
+ </div>
103
+ </>
104
+ } </>)
105
+ }
106
+ }
frontend/src/Components/ReactFlow/ReactFlowEnv.js CHANGED
@@ -15,14 +15,15 @@ const types = {
15
  }
16
 
17
  export default function ReactEnviorment() {
18
-
19
  const [theme, setTheme] = useState(useThemeDetector())
20
  const [nodes, setNodes] = useState([]);
21
  const [edges, setEdges] = useState([]);
22
  const [reactFlowInstance, setReactFlowInstance] = useState(null);
23
  const reactFlowWrapper = useRef(null);
24
- console.log("theme",theme)
25
-
 
26
  const onNodesChange = useCallback(
27
  (changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
28
  [setNodes]
@@ -33,12 +34,13 @@ export default function ReactEnviorment() {
33
  [setEdges]
34
  );
35
 
36
-
37
  const onDragOver = useCallback((event) => {
38
  event.preventDefault();
39
  event.dataTransfer.dropEffect = 'move';
40
  }, []);
41
-
 
 
42
  const onDrop = useCallback(
43
  (event) => {
44
  event.preventDefault();
@@ -61,13 +63,13 @@ export default function ReactEnviorment() {
61
  id: `${name}-${nodes.length}`,
62
  type,
63
  position,
64
- data: { label: `${name}`, host : `${host}`, colour : `${colour}` },
65
  };
66
  setNodes((nds) => nds.concat(newNode));
67
  },
68
  [reactFlowInstance, nodes]);
69
 
70
-
71
  return (
72
  <>
73
  <div className=' absolute top-4 right-5 z-50' onClick={()=> setTheme(!theme)}>
@@ -77,7 +79,7 @@ export default function ReactEnviorment() {
77
  <Navbar/>
78
  <ReactFlowProvider>
79
  <div className="h-screen w-screen" ref={reactFlowWrapper}>
80
- <ReactFlow nodes={nodes} edges={edges} nodeTypes={types} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onDragOver={onDragOver} onDrop={onDrop} onInit={setReactFlowInstance} fitView>
81
  <Background variant='dots' size={1} className=" bg-white dark:bg-neutral-800"/>
82
  </ReactFlow>
83
  </div>
 
15
  }
16
 
17
  export default function ReactEnviorment() {
18
+
19
  const [theme, setTheme] = useState(useThemeDetector())
20
  const [nodes, setNodes] = useState([]);
21
  const [edges, setEdges] = useState([]);
22
  const [reactFlowInstance, setReactFlowInstance] = useState(null);
23
  const reactFlowWrapper = useRef(null);
24
+
25
+
26
+
27
  const onNodesChange = useCallback(
28
  (changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
29
  [setNodes]
 
34
  [setEdges]
35
  );
36
 
 
37
  const onDragOver = useCallback((event) => {
38
  event.preventDefault();
39
  event.dataTransfer.dropEffect = 'move';
40
  }, []);
41
+
42
+ const deleteNode = (id) =>{setNodes((nds) => nds.filter(n => n.id !== id ))}
43
+
44
  const onDrop = useCallback(
45
  (event) => {
46
  event.preventDefault();
 
63
  id: `${name}-${nodes.length}`,
64
  type,
65
  position,
66
+ data: { label: `${name}`, host : `${host}`, colour : `${colour}`, delete : deleteNode },
67
  };
68
  setNodes((nds) => nds.concat(newNode));
69
  },
70
  [reactFlowInstance, nodes]);
71
 
72
+
73
  return (
74
  <>
75
  <div className=' absolute top-4 right-5 z-50' onClick={()=> setTheme(!theme)}>
 
79
  <Navbar/>
80
  <ReactFlowProvider>
81
  <div className="h-screen w-screen" ref={reactFlowWrapper}>
82
+ <ReactFlow nodes={nodes} edges={edges} nodeTypes={types} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onNodesDelete={deleteNode} onDragOver={onDragOver} onDrop={onDrop} onInit={setReactFlowInstance} fitView>
83
  <Background variant='dots' size={1} className=" bg-white dark:bg-neutral-800"/>
84
  </ReactFlow>
85
  </div>
frontend/src/css/counter.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ input[type='number']::-webkit-inner-spin-button,
2
+ input[type='number']::-webkit-outer-spin-button {
3
+ -webkit-appearance: none;
4
+ margin: 0;
5
+ }
6
+
7
+ .custom-number-input input:focus {
8
+ outline: none !important;
9
+ }
10
+
11
+ .custom-number-input button:focus {
12
+ outline: none !important;
13
+ }
frontend/src/css/dist/output.css CHANGED
@@ -591,6 +591,10 @@ video {
591
  pointer-events: auto;
592
  }
593
 
 
 
 
 
594
  .absolute {
595
  position: absolute;
596
  }
@@ -620,6 +624,10 @@ video {
620
  bottom: 0px;
621
  }
622
 
 
 
 
 
623
  .top-4 {
624
  top: 1rem;
625
  }
@@ -628,34 +636,22 @@ video {
628
  right: 1.25rem;
629
  }
630
 
631
- .top-0 {
632
- top: 0px;
633
- }
634
-
635
  .z-10 {
636
  z-index: 10;
637
  }
638
 
639
- .-z-10 {
640
- z-index: -10;
641
  }
642
 
643
- .-z-0 {
644
- z-index: 0;
645
  }
646
 
647
  .z-50 {
648
  z-index: 50;
649
  }
650
 
651
- .-z-20 {
652
- z-index: -20;
653
- }
654
-
655
- .z-0 {
656
- z-index: 0;
657
- }
658
-
659
  .float-left {
660
  float: left;
661
  }
@@ -664,6 +660,10 @@ video {
664
  margin: 0px;
665
  }
666
 
 
 
 
 
667
  .mt-4 {
668
  margin-top: 1rem;
669
  }
@@ -688,6 +688,18 @@ video {
688
  margin-right: 0.5rem;
689
  }
690
 
 
 
 
 
 
 
 
 
 
 
 
 
691
  .block {
692
  display: block;
693
  }
@@ -720,12 +732,20 @@ video {
720
  height: auto;
721
  }
722
 
 
 
 
 
 
 
 
 
723
  .h-\[540px\] {
724
  height: 540px;
725
  }
726
 
727
- .h-full {
728
- height: 100%;
729
  }
730
 
731
  .h-5 {
@@ -744,14 +764,58 @@ video {
744
  width: 2.25rem;
745
  }
746
 
747
- .w-\[600px\] {
748
- width: 600px;
749
  }
750
 
751
  .w-screen {
752
  width: 100vw;
753
  }
754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  .flex-1 {
756
  flex: 1 1 0%;
757
  }
@@ -770,14 +834,6 @@ video {
770
  cursor: pointer;
771
  }
772
 
773
- .cursor-s-resize {
774
- cursor: s-resize;
775
- }
776
-
777
- .cursor-grab {
778
- cursor: grab;
779
- }
780
-
781
  .cursor-grabbing {
782
  cursor: grabbing;
783
  }
@@ -787,6 +843,10 @@ video {
787
  user-select: none;
788
  }
789
 
 
 
 
 
790
  .items-center {
791
  align-items: center;
792
  }
@@ -797,6 +857,18 @@ video {
797
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
798
  }
799
 
 
 
 
 
 
 
 
 
 
 
 
 
800
  .overflow-auto {
801
  overflow: auto;
802
  }
@@ -825,18 +897,59 @@ video {
825
  border-radius: 0.75rem;
826
  }
827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
828
  .border {
829
  border-width: 1px;
830
  }
831
 
 
 
 
 
 
 
 
 
 
832
  .border-r-\[1px\] {
833
  border-right-width: 1px;
834
  }
835
 
 
 
 
 
836
  .border-dashed {
837
  border-style: dashed;
838
  }
839
 
 
 
 
 
840
  .border-black {
841
  --tw-border-opacity: 1;
842
  border-color: rgb(0 0 0 / var(--tw-border-opacity));
@@ -852,6 +965,16 @@ video {
852
  border-color: rgb(220 38 38 / var(--tw-border-opacity));
853
  }
854
 
 
 
 
 
 
 
 
 
 
 
855
  .bg-white {
856
  --tw-bg-opacity: 1;
857
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -865,11 +988,51 @@ video {
865
  background-color: rgba(255,255,255, 0.18);
866
  }
867
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
  .bg-black {
869
  --tw-bg-opacity: 1;
870
  background-color: rgb(0 0 0 / var(--tw-bg-opacity));
871
  }
872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
873
  .bg-gradient-to-bl {
874
  background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
875
  }
@@ -1015,10 +1178,6 @@ video {
1015
  --tw-gradient-to: #319B72;
1016
  }
1017
 
1018
- .p-7 {
1019
- padding: 1.75rem;
1020
- }
1021
-
1022
  .p-5 {
1023
  padding: 1.25rem;
1024
  }
@@ -1027,6 +1186,10 @@ video {
1027
  padding: 1rem;
1028
  }
1029
 
 
 
 
 
1030
  .p-0 {
1031
  padding: 0px;
1032
  }
@@ -1120,6 +1283,11 @@ video {
1120
  line-height: 2.5rem;
1121
  }
1122
 
 
 
 
 
 
1123
  .font-medium {
1124
  font-weight: 500;
1125
  }
@@ -1128,11 +1296,49 @@ video {
1128
  font-weight: 700;
1129
  }
1130
 
 
 
 
 
 
 
 
 
1131
  .text-white {
1132
  --tw-text-opacity: 1;
1133
  color: rgb(255 255 255 / var(--tw-text-opacity));
1134
  }
1135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1136
  .shadow-lg {
1137
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1138
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -1151,11 +1357,22 @@ video {
1151
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1152
  }
1153
 
 
 
 
 
 
 
1154
  .shadow-black {
1155
  --tw-shadow-color: #000;
1156
  --tw-shadow: var(--tw-shadow-colored);
1157
  }
1158
 
 
 
 
 
 
1159
  .filter {
1160
  -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1161
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
@@ -1167,6 +1384,14 @@ video {
1167
  transition-duration: 150ms;
1168
  }
1169
 
 
 
 
 
 
 
 
 
1170
  .duration-300 {
1171
  transition-duration: 300ms;
1172
  }
@@ -1215,9 +1440,39 @@ video {
1215
  border-color: rgb(151 0 204 / var(--tw-border-opacity));
1216
  }
1217
 
1218
- .hover\:bg-black:hover {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1219
  --tw-bg-opacity: 1;
1220
- background-color: rgb(0 0 0 / var(--tw-bg-opacity));
 
 
 
 
 
 
 
 
 
 
1221
  }
1222
 
1223
  .focus\:border-sky-500:focus {
@@ -1225,6 +1480,17 @@ video {
1225
  border-color: rgb(14 165 233 / var(--tw-border-opacity));
1226
  }
1227
 
 
 
 
 
 
 
 
 
 
 
 
1228
  .focus\:outline-none:focus {
1229
  outline: 2px solid transparent;
1230
  outline-offset: 2px;
@@ -1266,6 +1532,11 @@ video {
1266
  color: rgb(255 255 255 / var(--tw-text-opacity));
1267
  }
1268
 
 
 
 
 
 
1269
  @media (min-width: 640px) {
1270
  .sm\:w-60 {
1271
  width: 15rem;
 
591
  pointer-events: auto;
592
  }
593
 
594
+ .visible {
595
+ visibility: visible;
596
+ }
597
+
598
  .absolute {
599
  position: absolute;
600
  }
 
624
  bottom: 0px;
625
  }
626
 
627
+ .top-0 {
628
+ top: 0px;
629
+ }
630
+
631
  .top-4 {
632
  top: 1rem;
633
  }
 
636
  right: 1.25rem;
637
  }
638
 
 
 
 
 
639
  .z-10 {
640
  z-index: 10;
641
  }
642
 
643
+ .-z-20 {
644
+ z-index: -20;
645
  }
646
 
647
+ .-z-10 {
648
+ z-index: -10;
649
  }
650
 
651
  .z-50 {
652
  z-index: 50;
653
  }
654
 
 
 
 
 
 
 
 
 
655
  .float-left {
656
  float: left;
657
  }
 
660
  margin: 0px;
661
  }
662
 
663
+ .m-auto {
664
+ margin: auto;
665
+ }
666
+
667
  .mt-4 {
668
  margin-top: 1rem;
669
  }
 
688
  margin-right: 0.5rem;
689
  }
690
 
691
+ .-mt-3 {
692
+ margin-top: -0.75rem;
693
+ }
694
+
695
+ .mt-1 {
696
+ margin-top: 0.25rem;
697
+ }
698
+
699
+ .ml-2 {
700
+ margin-left: 0.5rem;
701
+ }
702
+
703
  .block {
704
  display: block;
705
  }
 
732
  height: auto;
733
  }
734
 
735
+ .h-full {
736
+ height: 100%;
737
+ }
738
+
739
+ .h-\[600px\] {
740
+ height: 600px;
741
+ }
742
+
743
  .h-\[540px\] {
744
  height: 540px;
745
  }
746
 
747
+ .h-8 {
748
+ height: 2rem;
749
  }
750
 
751
  .h-5 {
 
764
  width: 2.25rem;
765
  }
766
 
767
+ .w-\[85\%\] {
768
+ width: 85%;
769
  }
770
 
771
  .w-screen {
772
  width: 100vw;
773
  }
774
 
775
+ .w-\[540px\] {
776
+ width: 540px;
777
+ }
778
+
779
+ .w-\[600px\] {
780
+ width: 600px;
781
+ }
782
+
783
+ .w-\[80\%\] {
784
+ width: 80%;
785
+ }
786
+
787
+ .w-\[78\%\] {
788
+ width: 78%;
789
+ }
790
+
791
+ .w-32 {
792
+ width: 8rem;
793
+ }
794
+
795
+ .w-20 {
796
+ width: 5rem;
797
+ }
798
+
799
+ .w-\[72\%\] {
800
+ width: 72%;
801
+ }
802
+
803
+ .w-\[70\%\] {
804
+ width: 70%;
805
+ }
806
+
807
+ .w-\[75\%\] {
808
+ width: 75%;
809
+ }
810
+
811
+ .w-\[60\%\] {
812
+ width: 60%;
813
+ }
814
+
815
+ .w-0 {
816
+ width: 0px;
817
+ }
818
+
819
  .flex-1 {
820
  flex: 1 1 0%;
821
  }
 
834
  cursor: pointer;
835
  }
836
 
 
 
 
 
 
 
 
 
837
  .cursor-grabbing {
838
  cursor: grabbing;
839
  }
 
843
  user-select: none;
844
  }
845
 
846
+ .flex-row {
847
+ flex-direction: row;
848
+ }
849
+
850
  .items-center {
851
  align-items: center;
852
  }
 
857
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
858
  }
859
 
860
+ .space-x-3 > :not([hidden]) ~ :not([hidden]) {
861
+ --tw-space-x-reverse: 0;
862
+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
863
+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
864
+ }
865
+
866
+ .space-x-4 > :not([hidden]) ~ :not([hidden]) {
867
+ --tw-space-x-reverse: 0;
868
+ margin-right: calc(1rem * var(--tw-space-x-reverse));
869
+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
870
+ }
871
+
872
  .overflow-auto {
873
  overflow: auto;
874
  }
 
897
  border-radius: 0.75rem;
898
  }
899
 
900
+ .rounded-lg {
901
+ border-radius: 0.5rem;
902
+ }
903
+
904
+ .rounded-l {
905
+ border-top-left-radius: 0.25rem;
906
+ border-bottom-left-radius: 0.25rem;
907
+ }
908
+
909
+ .rounded-r {
910
+ border-top-right-radius: 0.25rem;
911
+ border-bottom-right-radius: 0.25rem;
912
+ }
913
+
914
+ .rounded-l-xl {
915
+ border-top-left-radius: 0.75rem;
916
+ border-bottom-left-radius: 0.75rem;
917
+ }
918
+
919
+ .rounded-r-xl {
920
+ border-top-right-radius: 0.75rem;
921
+ border-bottom-right-radius: 0.75rem;
922
+ }
923
+
924
  .border {
925
  border-width: 1px;
926
  }
927
 
928
+ .border-2 {
929
+ border-width: 2px;
930
+ }
931
+
932
+ .border-y-2 {
933
+ border-top-width: 2px;
934
+ border-bottom-width: 2px;
935
+ }
936
+
937
  .border-r-\[1px\] {
938
  border-right-width: 1px;
939
  }
940
 
941
+ .border-t-2 {
942
+ border-top-width: 2px;
943
+ }
944
+
945
  .border-dashed {
946
  border-style: dashed;
947
  }
948
 
949
+ .border-dotted {
950
+ border-style: dotted;
951
+ }
952
+
953
  .border-black {
954
  --tw-border-opacity: 1;
955
  border-color: rgb(0 0 0 / var(--tw-border-opacity));
 
965
  border-color: rgb(220 38 38 / var(--tw-border-opacity));
966
  }
967
 
968
+ .border-green-600 {
969
+ --tw-border-opacity: 1;
970
+ border-color: rgb(22 163 74 / var(--tw-border-opacity));
971
+ }
972
+
973
+ .border-fuchsia-300 {
974
+ --tw-border-opacity: 1;
975
+ border-color: rgb(240 171 252 / var(--tw-border-opacity));
976
+ }
977
+
978
  .bg-white {
979
  --tw-bg-opacity: 1;
980
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
 
988
  background-color: rgba(255,255,255, 0.18);
989
  }
990
 
991
+ .bg-Warm-Blue {
992
+ --tw-bg-opacity: 1;
993
+ background-color: rgb(40 58 184 / var(--tw-bg-opacity));
994
+ }
995
+
996
+ .bg-Warm-Violet {
997
+ --tw-bg-opacity: 1;
998
+ background-color: rgb(141 55 158 / var(--tw-bg-opacity));
999
+ }
1000
+
1001
+ .bg-Warm-Pink {
1002
+ --tw-bg-opacity: 1;
1003
+ background-color: rgb(241 52 132 / var(--tw-bg-opacity));
1004
+ }
1005
+
1006
  .bg-black {
1007
  --tw-bg-opacity: 1;
1008
  background-color: rgb(0 0 0 / var(--tw-bg-opacity));
1009
  }
1010
 
1011
+ .bg-gray-300 {
1012
+ --tw-bg-opacity: 1;
1013
+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
1014
+ }
1015
+
1016
+ .bg-gray-900 {
1017
+ --tw-bg-opacity: 1;
1018
+ background-color: rgb(17 24 39 / var(--tw-bg-opacity));
1019
+ }
1020
+
1021
+ .bg-neutral-900 {
1022
+ --tw-bg-opacity: 1;
1023
+ background-color: rgb(23 23 23 / var(--tw-bg-opacity));
1024
+ }
1025
+
1026
+ .bg-cream {
1027
+ --tw-bg-opacity: 1;
1028
+ background-color: rgb(250 249 246 / var(--tw-bg-opacity));
1029
+ }
1030
+
1031
+ .bg-Warm-Red {
1032
+ --tw-bg-opacity: 1;
1033
+ background-color: rgb(255 96 93 / var(--tw-bg-opacity));
1034
+ }
1035
+
1036
  .bg-gradient-to-bl {
1037
  background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
1038
  }
 
1178
  --tw-gradient-to: #319B72;
1179
  }
1180
 
 
 
 
 
1181
  .p-5 {
1182
  padding: 1.25rem;
1183
  }
 
1186
  padding: 1rem;
1187
  }
1188
 
1189
+ .p-1 {
1190
+ padding: 0.25rem;
1191
+ }
1192
+
1193
  .p-0 {
1194
  padding: 0px;
1195
  }
 
1283
  line-height: 2.5rem;
1284
  }
1285
 
1286
+ .text-sm {
1287
+ font-size: 0.875rem;
1288
+ line-height: 1.25rem;
1289
+ }
1290
+
1291
  .font-medium {
1292
  font-weight: 500;
1293
  }
 
1296
  font-weight: 700;
1297
  }
1298
 
1299
+ .font-semibold {
1300
+ font-weight: 600;
1301
+ }
1302
+
1303
+ .font-thin {
1304
+ font-weight: 100;
1305
+ }
1306
+
1307
  .text-white {
1308
  --tw-text-opacity: 1;
1309
  color: rgb(255 255 255 / var(--tw-text-opacity));
1310
  }
1311
 
1312
+ .text-gray-700 {
1313
+ --tw-text-opacity: 1;
1314
+ color: rgb(55 65 81 / var(--tw-text-opacity));
1315
+ }
1316
+
1317
+ .text-gray-600 {
1318
+ --tw-text-opacity: 1;
1319
+ color: rgb(75 85 99 / var(--tw-text-opacity));
1320
+ }
1321
+
1322
+ .text-red-600 {
1323
+ --tw-text-opacity: 1;
1324
+ color: rgb(220 38 38 / var(--tw-text-opacity));
1325
+ }
1326
+
1327
+ .text-black {
1328
+ --tw-text-opacity: 1;
1329
+ color: rgb(0 0 0 / var(--tw-text-opacity));
1330
+ }
1331
+
1332
+ .text-green-300 {
1333
+ --tw-text-opacity: 1;
1334
+ color: rgb(134 239 172 / var(--tw-text-opacity));
1335
+ }
1336
+
1337
+ .text-green-400 {
1338
+ --tw-text-opacity: 1;
1339
+ color: rgb(74 222 128 / var(--tw-text-opacity));
1340
+ }
1341
+
1342
  .shadow-lg {
1343
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1344
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
 
1357
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1358
  }
1359
 
1360
+ .shadow-xl {
1361
+ --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
1362
+ --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
1363
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1364
+ }
1365
+
1366
  .shadow-black {
1367
  --tw-shadow-color: #000;
1368
  --tw-shadow: var(--tw-shadow-colored);
1369
  }
1370
 
1371
+ .outline-none {
1372
+ outline: 2px solid transparent;
1373
+ outline-offset: 2px;
1374
+ }
1375
+
1376
  .filter {
1377
  -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1378
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
 
1384
  transition-duration: 150ms;
1385
  }
1386
 
1387
+ .transition {
1388
+ transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, -webkit-text-decoration-color, -webkit-transform, -webkit-filter, -webkit-backdrop-filter;
1389
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
1390
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-transform, -webkit-filter, -webkit-backdrop-filter;
1391
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
1392
+ transition-duration: 150ms;
1393
+ }
1394
+
1395
  .duration-300 {
1396
  transition-duration: 300ms;
1397
  }
 
1440
  border-color: rgb(151 0 204 / var(--tw-border-opacity));
1441
  }
1442
 
1443
+ .hover\:border-Green-Forest:hover {
1444
+ --tw-border-opacity: 1;
1445
+ border-color: rgb(26 76 57 / var(--tw-border-opacity));
1446
+ }
1447
+
1448
+ .hover\:border-Green-Emerald:hover {
1449
+ --tw-border-opacity: 1;
1450
+ border-color: rgb(49 155 114 / var(--tw-border-opacity));
1451
+ }
1452
+
1453
+ .hover\:border-rose-600:hover {
1454
+ --tw-border-opacity: 1;
1455
+ border-color: rgb(225 29 72 / var(--tw-border-opacity));
1456
+ }
1457
+
1458
+ .hover\:border-b-Green-Forest:hover {
1459
+ --tw-border-opacity: 1;
1460
+ border-bottom-color: rgb(26 76 57 / var(--tw-border-opacity));
1461
+ }
1462
+
1463
+ .hover\:bg-gray-400:hover {
1464
  --tw-bg-opacity: 1;
1465
+ background-color: rgb(156 163 175 / var(--tw-bg-opacity));
1466
+ }
1467
+
1468
+ .hover\:text-gray-700:hover {
1469
+ --tw-text-opacity: 1;
1470
+ color: rgb(55 65 81 / var(--tw-text-opacity));
1471
+ }
1472
+
1473
+ .hover\:text-black:hover {
1474
+ --tw-text-opacity: 1;
1475
+ color: rgb(0 0 0 / var(--tw-text-opacity));
1476
  }
1477
 
1478
  .focus\:border-sky-500:focus {
 
1480
  border-color: rgb(14 165 233 / var(--tw-border-opacity));
1481
  }
1482
 
1483
+ .focus\:from-fuchsia-200:focus {
1484
+ --tw-gradient-from: #f5d0fe;
1485
+ --tw-gradient-to: rgb(245 208 254 / 0);
1486
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
1487
+ }
1488
+
1489
+ .focus\:text-black:focus {
1490
+ --tw-text-opacity: 1;
1491
+ color: rgb(0 0 0 / var(--tw-text-opacity));
1492
+ }
1493
+
1494
  .focus\:outline-none:focus {
1495
  outline: 2px solid transparent;
1496
  outline-offset: 2px;
 
1532
  color: rgb(255 255 255 / var(--tw-text-opacity));
1533
  }
1534
 
1535
+ .dark .dark\:text-red-600 {
1536
+ --tw-text-opacity: 1;
1537
+ color: rgb(220 38 38 / var(--tw-text-opacity));
1538
+ }
1539
+
1540
  @media (min-width: 640px) {
1541
  .sm\:w-60 {
1542
  width: 15rem;
images/new_feature.png ADDED

Git LFS Details

  • SHA256: 1f29ed57456de49f33bd20490d507c5d90394c9aa6e787e76f5d1dc4f63f5838
  • Pointer size: 130 Bytes
  • Size of remote file: 55.7 kB