migrate to tailwindcss v4
This commit is contained in:
parent
7cbabf582a
commit
eb06476f38
1507
package-lock.json
generated
1507
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -24,17 +24,15 @@
|
||||
"@sveltejs/adapter-node": "^5.2.9",
|
||||
"@sveltejs/kit": "^2.11.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"@tailwindcss/postcss": "^4.0.9",
|
||||
"@types/gtag.js": "^0.0.19",
|
||||
"@types/node": "^20.12.7",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"bits-ui": "^0.21.13",
|
||||
"blob-util": "^2.0.2",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk-sv": "^0.0.18",
|
||||
"compression": "^1.7.4",
|
||||
"d3-hierarchy": "^3.1.2",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"daisyui": "^4.12.24",
|
||||
"daisyui": "^5.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns-tz": "^3.1.3",
|
||||
"date-picker-svelte": "^2.12.0",
|
||||
@ -45,7 +43,6 @@
|
||||
"html2canvas": "^1.4.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"katex": "^0.16.11",
|
||||
"layercake": "^8.4.0-beta.1",
|
||||
"lightweight-charts": "^4.1.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-svelte": "^0.438.0",
|
||||
@ -54,7 +51,7 @@
|
||||
"nprogress": "^0.2.0",
|
||||
"object-to-formdata": "^4.5.1",
|
||||
"parse5": "^7.1.2",
|
||||
"pocketbase": "^0.22.1",
|
||||
"pocketbase": "^0.25.2",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
@ -82,7 +79,7 @@
|
||||
"svelte-tiny-virtual-list": "^2.1.2",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
"tailwind-variants": "^0.2.1",
|
||||
"tailwindcss": "^3.4.16",
|
||||
"tailwindcss": "^4.0.9",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.4.5",
|
||||
"util": "^0.12.5",
|
||||
@ -98,7 +95,6 @@
|
||||
"highcharts": "^11.4.3",
|
||||
"https": "^1.0.0",
|
||||
"jsconfig.json": "^2.3.3",
|
||||
"ol": "^10.3.1",
|
||||
"plotly.js": "^2.35.3",
|
||||
"svelte-plotly.js": "^1.2.0",
|
||||
"ua-parser-js": "^1.0.37"
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
'@tailwindcss/postcss': {},
|
||||
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
||||
142
src/app.css
142
src/app.css
@ -1,75 +1,58 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "tailwindcss";
|
||||
@plugin "daisyui";
|
||||
|
||||
.table {
|
||||
@apply text-left text-sm rtl:text-right;
|
||||
:where(th, td) {
|
||||
@apply px-4 py-3 align-middle;
|
||||
}
|
||||
tr.active,
|
||||
tr.active:nth-child(even),
|
||||
&-zebra tbody tr:nth-child(even) {
|
||||
@apply bg-[#191E24];
|
||||
}
|
||||
tr.hover,
|
||||
tr.hover:nth-child(even) {
|
||||
@apply [@media(hover:hover)]:hover:bg-[#000];
|
||||
}
|
||||
@config '../tailwind.config.cjs';
|
||||
|
||||
&-zebra {
|
||||
tr.active,
|
||||
tr.active:nth-child(even),
|
||||
&-zebra tbody tr:nth-child(even) {
|
||||
@apply bg-[#000];
|
||||
}
|
||||
}
|
||||
&-zebra tr.hover,
|
||||
&-zebra tr.hover:nth-child(even) {
|
||||
@apply [@media(hover:hover)]:hover:bg-[#000];
|
||||
}
|
||||
|
||||
:where(thead, tbody) {
|
||||
:where(tr:not(:last-child)),
|
||||
:where(tr:first-child:last-child) {
|
||||
@apply border-b-[#000] border-b;
|
||||
}
|
||||
}
|
||||
|
||||
:where(thead, tfoot) {
|
||||
@apply whitespace-nowrap text-xs;
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.no-scrollbar {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@utility no-scrollbar {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
/* Styles for WebKit browsers (Chrome, Safari, newer versions of Opera) */
|
||||
.no-scrollbar::-webkit-scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
width: auto; /* Keep the width for vertical scrollbar */
|
||||
height: 0; /* Set height to 0 to hide horizontal scrollbar */
|
||||
}
|
||||
|
||||
/* Styles for Firefox */
|
||||
.no-scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: auto transparent; /* vertical scrollbar color, then track color */
|
||||
}
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: auto transparent; /* vertical scrollbar color, then track color */
|
||||
|
||||
/* Styles for Internet Explorer and Edge */
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
}
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
}
|
||||
|
||||
.shake-ticker:hover img {
|
||||
@utility shake-ticker {
|
||||
&:hover img {
|
||||
animation-name: shake;
|
||||
animation-duration: 0.5s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
|
||||
.table {
|
||||
tr {
|
||||
@apply border-b border-gray-800;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@layer utilities {
|
||||
|
||||
@keyframes shake {
|
||||
0% {
|
||||
@ -90,60 +73,3 @@
|
||||
}
|
||||
}
|
||||
|
||||
.loader,
|
||||
.loader:before,
|
||||
.loader:after {
|
||||
border-radius: 50%;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation: load7 0.8s infinite ease-in-out;
|
||||
animation: load7 0.8s infinite ease-in-out;
|
||||
}
|
||||
.loader {
|
||||
color: #ffffff;
|
||||
font-size: 10px;
|
||||
margin: 80px auto;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
-webkit-animation-delay: -0.16s;
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
.loader:before,
|
||||
.loader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
.loader:before {
|
||||
left: -3.5em;
|
||||
-webkit-animation-delay: -0.32s;
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
.loader:after {
|
||||
left: 3.5em;
|
||||
}
|
||||
@-webkit-keyframes load7 {
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
box-shadow: 0 2.5em 0 -1.3em;
|
||||
}
|
||||
40% {
|
||||
box-shadow: 0 2.5em 0 0;
|
||||
}
|
||||
}
|
||||
@keyframes load7 {
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
box-shadow: 0 2.5em 0 -1.3em;
|
||||
}
|
||||
40% {
|
||||
box-shadow: 0 2.5em 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@
|
||||
{:else}
|
||||
<a class="block relative" href="/pricing">
|
||||
<span
|
||||
class="text-base font-semibold text-blue-link blur group-hover:blur-[3px]"
|
||||
class="text-base font-semibold text-blue-link blur-sm group-hover:blur-[3px]"
|
||||
>
|
||||
XX
|
||||
</span>
|
||||
|
||||
@ -1,476 +0,0 @@
|
||||
<script lang="ts">
|
||||
import toast from "svelte-french-toast";
|
||||
import {
|
||||
stockTicker,
|
||||
etfTicker,
|
||||
cryptoTicker,
|
||||
assetType,
|
||||
screenWidth,
|
||||
} from "$lib/store";
|
||||
import { page } from "$app/stores";
|
||||
|
||||
export let data;
|
||||
|
||||
let isClicked = false;
|
||||
|
||||
async function createPortfolio(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const postData = { userId: data?.user?.id };
|
||||
|
||||
const response = await fetch("/api/create-portfolio", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(postData),
|
||||
});
|
||||
|
||||
const output = await response.json();
|
||||
|
||||
if (output?.message === "success") {
|
||||
isClicked = true;
|
||||
toast.success("Portfolio created successfully!", {
|
||||
style: "border-radius: 200px; background: #2A2E39; color: #fff;",
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const clicked = document.getElementById("addPortfolio");
|
||||
clicked.dispatchEvent(new MouseEvent("click"));
|
||||
|
||||
const anchor = document.createElement("a");
|
||||
|
||||
if ($page.url.pathname === "/portfolio") {
|
||||
anchor.href = "/portfolio";
|
||||
} else {
|
||||
if ($assetType === "etf") {
|
||||
anchor.href = `/etf/${$etfTicker}`;
|
||||
} else if ($assetType === "crypto") {
|
||||
anchor.href = `/crypto/${$cryptoTicker}`;
|
||||
} else {
|
||||
anchor.href = `/stocks/${$stockTicker}`;
|
||||
}
|
||||
}
|
||||
|
||||
anchor.dataset.sveltekitReload = true;
|
||||
document.body.appendChild(anchor);
|
||||
anchor.dispatchEvent(new MouseEvent("click"));
|
||||
}, 500);
|
||||
} else {
|
||||
toast.error("Something went wrong. Please try again.", {
|
||||
style: "border-radius: 200px; background: #2A2E39; color: #fff;",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let participationCheckbox = false;
|
||||
let ageCheckbox = false;
|
||||
|
||||
function handleAge() {
|
||||
ageCheckbox = !ageCheckbox; // Toggle the value using the ! operator
|
||||
}
|
||||
|
||||
function handleParticipation() {
|
||||
participationCheckbox = !participationCheckbox; // Toggle the value using the ! operator
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $screenWidth >= 640}
|
||||
<input type="checkbox" id="addPortfolio" class="modal-toggle" />
|
||||
|
||||
<dialog
|
||||
id="addPortfolio"
|
||||
class="modal modal-bottom sm:modal-middle overflow-hidden"
|
||||
>
|
||||
<label
|
||||
for="addPortfolio"
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.5]"
|
||||
></label>
|
||||
|
||||
<div class="modal-box w-full bg-default overflow-hidden">
|
||||
<div class="flex flex-col w-full mt-10 sm:mt-0">
|
||||
<div class="text-white text-3xl font-bold mb-5">
|
||||
Portfolio Tournament 🔥🚀
|
||||
</div>
|
||||
|
||||
<div class="text-white text-lg font-medium mb-3">
|
||||
Terms and Conditions of Participation
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="text-white text-sm border bg-secondary border-gray-800 p-3 rounded-md overflow-y-auto h-56"
|
||||
>
|
||||
<ol class="text-white list-decimal ml-3 p-2">
|
||||
<li class="p-1">
|
||||
The organizer of the Prize competition is stocknear.
|
||||
</li>
|
||||
<li class="p-1">Participation is free of charge.</li>
|
||||
<li class="p-1">
|
||||
All individuals worldwide who have reached the age of 18 and
|
||||
comply with the laws and regulations of their respective countries
|
||||
are eligible to participate. Persons involved in the conception
|
||||
and implementation of this prize competition are excluded - this
|
||||
explicitly does not apply to voluntary moderators or other
|
||||
voluntary members who have a special status on the platform.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prerequisite for participation in the competition is the
|
||||
creation of a portfolio whereby the user can buy and sell shares.
|
||||
Each user starts with a play money of 100,000 $. To be considered
|
||||
in the final draw and eligible for any prizes, participants must
|
||||
make at least one trade (buy or sell shares) during the tournament
|
||||
period.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prize competition will take place automated once a month for
|
||||
an indefinite period of time. The potential winners are drawn
|
||||
automatically, randomly on the first day of each month, whereby
|
||||
the chance of winning depends on the overall return of the
|
||||
portfolio. If a participant has collected too little return of the
|
||||
portfolio, the chance can also be 0 percent.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prizes to be awarded may change from month to month.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
After the draw, the accounts of the winners will be checked for
|
||||
possible fraud attempts. If no abnormalities are found, the
|
||||
potential winners will be notified by email from stocknear. If any
|
||||
abnormalities are found, the draw will be repeated. The organizer
|
||||
reserves the right to refuse and reclaim prizes even after the
|
||||
fact and to permanently exclude participants from competitions in
|
||||
case of suspicion of attempted fraud or manipulation for their own
|
||||
benefit or the benefit of third parties as well as to temporarily
|
||||
or permanently block their accounts.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The potential winner must respond to the respective prize
|
||||
notification within 14 days, which will be sent via email, in
|
||||
order to claim the prize. Only a response via email will be
|
||||
considered. Otherwise, unclaimed prizes will be included in the
|
||||
next monthly draw.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer points out that the availability and functionality
|
||||
of the prize draw cannot be guaranteed. The organizer is not
|
||||
responsible for entries not being included due to technical
|
||||
failures or other reasons. The prize competition may be terminated
|
||||
or removed due to external circumstances and constraints without
|
||||
any claims arising for the participants against the organizer.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer reserves the right to change, discontinue, or
|
||||
suspend the game and the draw in whole or in part without prior
|
||||
notice in the event of unforeseen circumstances. These
|
||||
circumstances include, but are not limited to, the appearance of a
|
||||
computer virus, a program error, unauthorized intervention by
|
||||
third parties, or mechanical or technical problems beyond the
|
||||
control and influence of the organizer.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer reserves the right to terminate the prize draw at
|
||||
any time without prior notice. In this case, any outstanding
|
||||
prizes will be properly awarded.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
Should individual provisions of these terms and conditions of
|
||||
participation be or become invalid, inadmissible, or
|
||||
unenforceable, this shall not affect the validity of the remaining
|
||||
terms and conditions. In place of the invalid, inadmissible, or
|
||||
unenforceable clause, provisions shall be deemed to have been
|
||||
agreed upon that come as close as possible to the economic
|
||||
objectives.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
Furthermore, the <a
|
||||
href="/imprint"
|
||||
class="text-blue-700 hover:underline">Imprint</a
|
||||
>,
|
||||
<a href="/terms-of-use" class="text-blue-700 hover:underline">
|
||||
Terms of Use
|
||||
</a>
|
||||
and our
|
||||
<a href="/privacy-policy" class="text-blue-700 hover:underline">
|
||||
Privacy Policy
|
||||
</a>
|
||||
apply. The applicable law and jurisdiction for this prize draw shall
|
||||
be determined based on the participant's country of residence. In case
|
||||
of any legal disputes, the competent courts of the participant's country
|
||||
of residence shall have exclusive jurisdiction.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The right of recourse to the courts is excluded.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-5">
|
||||
<label class="label cursor-pointer flex flex-row">
|
||||
<input
|
||||
on:click={handleParticipation}
|
||||
checked={participationCheckbox}
|
||||
aria-describedby="helper-checkbox-text"
|
||||
type="checkbox"
|
||||
value=""
|
||||
class="w-6 h-6 bg-[#333333] border-slate-500 focus-none rounded ring-1"
|
||||
/>
|
||||
<span class="label-text text-white ml-3"
|
||||
>I accept the Terms and Conditions of Participation in the monthly
|
||||
portfolio tournament.</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer">
|
||||
<input
|
||||
on:click={handleAge}
|
||||
checked={ageCheckbox}
|
||||
aria-describedby="helper-checkbox-text"
|
||||
type="checkbox"
|
||||
value=""
|
||||
class="w-6 h-6 bg-[#333333] border-slate-500 focus-none rounded ring-1"
|
||||
/>
|
||||
<span class="label-text text-white ml-3 mr-auto"
|
||||
>I'm at least 18 years old.</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{#if ageCheckbox && participationCheckbox && !isClicked}
|
||||
<form
|
||||
on:submit={createPortfolio}
|
||||
class="w-full max-w-lg pt-5 m-auto pb-8"
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn bg-[#fff] sm:hover:bg-gray-300 btn-md w-full rounded-md m-auto text-white font-bold text-md"
|
||||
>
|
||||
Create Portfolio
|
||||
</button>
|
||||
</form>
|
||||
{:else}
|
||||
<div class="w-full max-w-lg pt-5 m-auto pb-8">
|
||||
<label
|
||||
class="opacity-[0.4] cursor-not-allowed btn bg-[#fff] btn-md w-full rounded-md m-auto text-white font-bold text-md"
|
||||
>
|
||||
{#if !isClicked}
|
||||
Create Portfolio
|
||||
{:else}
|
||||
<div class="flex flex-row m-auto">
|
||||
<span class="loading loading-infinity"></span>
|
||||
<span class="text-white ml-2">Loading</span>
|
||||
</div>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
{:else}
|
||||
<!--Start Drawer Sidewise for mobile-->
|
||||
|
||||
<!--Start ESG Modal-->
|
||||
<div
|
||||
class="drawer drawer-end overflow-hidden w-screen"
|
||||
style="z-index: 9999;"
|
||||
>
|
||||
<input id="addPortfolio" type="checkbox" class="drawer-toggle" />
|
||||
<div class="drawer-side overflow-y-auto overflow-hidden">
|
||||
<div
|
||||
class="bg-[#000] min-h-screen px-5 pt-16 w-screen pb-20 overflow-y-auto overflow-hidden"
|
||||
>
|
||||
<h1 class="text-white sm:hidden font-bold text-2xl mb-5">
|
||||
Portfolio Tournament 🔥🚀
|
||||
</h1>
|
||||
|
||||
<div class="text-white text-lg font-medium mb-3">
|
||||
Terms and Conditions of Participation
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="text-white text-sm border bg-default border-gray-800 p-3 rounded-md overflow-y-auto h-56"
|
||||
>
|
||||
<ol class="text-white list-decimal ml-3 p-2">
|
||||
<li class="p-1">
|
||||
The organizer of the Prize competition is stocknear.
|
||||
</li>
|
||||
<li class="p-1">Participation is free of charge.</li>
|
||||
<li class="p-1">
|
||||
All individuals worldwide who have reached the age of 18 and
|
||||
comply with the laws and regulations of their respective countries
|
||||
are eligible to participate. Persons involved in the conception
|
||||
and implementation of this prize competition are excluded - this
|
||||
explicitly does not apply to voluntary moderators or other
|
||||
voluntary members who have a special status on the platform.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prerequisite for participation in the competition is the
|
||||
creation of a portfolio whereby the user can buy and sell shares.
|
||||
Each user starts with a play money of 100,000 $. To be considered
|
||||
in the final draw and eligible for any prizes, participants must
|
||||
make at least one trade (buy or sell shares) during the tournament
|
||||
period.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prize competition will take place automated once a month for
|
||||
an indefinite period of time. The potential winners are drawn
|
||||
automatically, randomly on the first day of each month, whereby
|
||||
the chance of winning depends on the overall return of the
|
||||
portfolio. If a participant has collected too little return of the
|
||||
portfolio, the chance can also be 0 percent.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The prizes to be awarded may change from month to month.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
After the draw, the accounts of the winners will be checked for
|
||||
possible fraud attempts. If no abnormalities are found, the
|
||||
potential winners will be notified by email from stocknear. If any
|
||||
abnormalities are found, the draw will be repeated. The organizer
|
||||
reserves the right to refuse and reclaim prizes even after the
|
||||
fact and to permanently exclude participants from competitions in
|
||||
case of suspicion of attempted fraud or manipulation for their own
|
||||
benefit or the benefit of third parties as well as to temporarily
|
||||
or permanently block their accounts.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The potential winner must respond to the respective prize
|
||||
notification within 14 days, which will be sent via email, in
|
||||
order to claim the prize. Only a response via email will be
|
||||
considered. Otherwise, unclaimed prizes will be included in the
|
||||
next monthly draw.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer points out that the availability and functionality
|
||||
of the prize draw cannot be guaranteed. The organizer is not
|
||||
responsible for entries not being included due to technical
|
||||
failures or other reasons. The prize competition may be terminated
|
||||
or removed due to external circumstances and constraints without
|
||||
any claims arising for the participants against the organizer.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer reserves the right to change, discontinue, or
|
||||
suspend the game and the draw in whole or in part without prior
|
||||
notice in the event of unforeseen circumstances. These
|
||||
circumstances include, but are not limited to, the appearance of a
|
||||
computer virus, a program error, unauthorized intervention by
|
||||
third parties, or mechanical or technical problems beyond the
|
||||
control and influence of the organizer.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The organizer reserves the right to terminate the prize draw at
|
||||
any time without prior notice. In this case, any outstanding
|
||||
prizes will be properly awarded.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
Should individual provisions of these terms and conditions of
|
||||
participation be or become invalid, inadmissible, or
|
||||
unenforceable, this shall not affect the validity of the remaining
|
||||
terms and conditions. In place of the invalid, inadmissible, or
|
||||
unenforceable clause, provisions shall be deemed to have been
|
||||
agreed upon that come as close as possible to the economic
|
||||
objectives.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
Furthermore, the <a
|
||||
href="/imprint"
|
||||
class="text-blue-700 hover:underline">Imprint</a
|
||||
>,
|
||||
<a href="/terms-of-use" class="text-blue-700 hover:underline">
|
||||
Terms of Use
|
||||
</a>
|
||||
and our
|
||||
<a href="/privacy-policy" class="text-blue-700 hover:underline">
|
||||
Privacy Policy
|
||||
</a>
|
||||
apply. The applicable law and jurisdiction for this prize draw shall
|
||||
be determined based on the participant's country of residence. In case
|
||||
of any legal disputes, the competent courts of the participant's country
|
||||
of residence shall have exclusive jurisdiction.
|
||||
</li>
|
||||
<li class="p-1">
|
||||
The right of recourse to the courts is excluded.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-5">
|
||||
<label class="label cursor-pointer flex flex-row">
|
||||
<input
|
||||
on:click={handleParticipation}
|
||||
checked={participationCheckbox}
|
||||
aria-describedby="helper-checkbox-text"
|
||||
type="checkbox"
|
||||
value=""
|
||||
class="w-6 h-6 bg-[#333333] border-slate-500 focus-none rounded ring-1"
|
||||
/>
|
||||
<span class="label-text text-white ml-3"
|
||||
>I accept the Terms and Conditions of Participation in the monthly
|
||||
portfolio tournament.</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer">
|
||||
<input
|
||||
on:click={handleAge}
|
||||
checked={ageCheckbox}
|
||||
aria-describedby="helper-checkbox-text"
|
||||
type="checkbox"
|
||||
value=""
|
||||
class="w-6 h-6 bg-[#333333] border-slate-500 focus-none rounded ring-1"
|
||||
/>
|
||||
<span class="label-text text-white ml-3 mr-auto"
|
||||
>I'm at least 18 years old.</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{#if ageCheckbox && participationCheckbox && !isClicked}
|
||||
<form
|
||||
on:submit={createPortfolio}
|
||||
class="w-full max-w-lg m-auto pb-8 mt-10"
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn bg-[#fff] sm:hover:bg-gray-300 btn-md w-full rounded-md m-auto text-white font-bold text-md"
|
||||
>
|
||||
Create Portfolio
|
||||
</button>
|
||||
</form>
|
||||
{:else}
|
||||
<div class="w-full max-w-lg m-auto pb-8 mt-10">
|
||||
<label
|
||||
class="opacity-[0.4] cursor-not-allowed btn bg-[#fff] btn-md w-full rounded-md m-auto text-white font-bold text-md"
|
||||
>
|
||||
{#if !isClicked}
|
||||
Create Portfolio
|
||||
{:else}
|
||||
<div class="flex flex-row m-auto">
|
||||
<span class="loading loading-infinity"></span>
|
||||
<span class="text-white ml-2">Loading</span>
|
||||
</div>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<label for="addPortfolio" class="absolute left-6 top-4 sm:hidden">
|
||||
<svg
|
||||
class="w-6 h-6 inline-block mb-0.5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#fff"
|
||||
d="M9.125 21.1L.7 12.7q-.15-.15-.213-.325T.425 12q0-.2.063-.375T.7 11.3l8.425-8.425q.35-.35.875-.35t.9.375q.375.375.375.875t-.375.875L3.55 12l7.35 7.35q.35.35.35.863t-.375.887q-.375.375-.875.375t-.875-.375Z"
|
||||
/></svg
|
||||
>
|
||||
<span class="text-white text-md font-medium"> Return </span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@ -545,8 +545,8 @@
|
||||
data: growthList?.map((value) => ({
|
||||
y: value,
|
||||
// Set color based on the sign of the value
|
||||
color: value >= 0 ? "#338D73" : "#ED3333",
|
||||
borderColor: value >= 0 ? "#338D73" : "#ED3333",
|
||||
color: value >= 0 ? "#00FC50" : "#ED3333",
|
||||
borderColor: value >= 0 ? "#00FC50" : "#ED3333",
|
||||
borderRadius: "1px",
|
||||
})),
|
||||
zIndex: 5,
|
||||
@ -786,16 +786,16 @@
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="shadow-md">
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tbody>
|
||||
<tr class="bg-primary border-b border-gray-600">
|
||||
<th
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-[#27272A]"
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-gray-800"
|
||||
>
|
||||
Revenue
|
||||
</th>
|
||||
{#each tableCombinedRevenue as item}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-[#27272A] bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-gray-800 bg-default"
|
||||
>
|
||||
{item?.val === "0.00" ||
|
||||
item?.val === null ||
|
||||
@ -806,15 +806,15 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-gray-800"
|
||||
>
|
||||
Revenue Growth
|
||||
</th>
|
||||
{#each computeGrowthList(tableActualRevenue, tableCombinedRevenue) as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default border-b border-gray-800"
|
||||
>
|
||||
{#if index === 0 || item?.growth === null}
|
||||
n/a
|
||||
@ -843,13 +843,13 @@
|
||||
|
||||
<tr class="bg-primary border-b-[#09090B]">
|
||||
<th
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-[#27272A]"
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-gray-800"
|
||||
>
|
||||
EPS
|
||||
</th>
|
||||
{#each tableCombinedEPS as item}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-[#27272A] bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-gray-800 bg-default"
|
||||
>
|
||||
{item?.val === "0.00" ||
|
||||
item?.val === null ||
|
||||
@ -860,15 +860,15 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-gray-800"
|
||||
>
|
||||
EPS Growth
|
||||
</th>
|
||||
{#each computeGrowthList(tableActualEPS, tableCombinedEPS) as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default border-b border-gray-800"
|
||||
>
|
||||
{#if index === 0 || item?.growth === null}
|
||||
n/a
|
||||
@ -894,15 +894,15 @@
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary border-b border-gray-600">
|
||||
<th
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-[#27272A]"
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-gray-800"
|
||||
>
|
||||
Net Income
|
||||
</th>
|
||||
{#each tableCombinedNetIncome as item}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-[#27272A] bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-gray-800 bg-default"
|
||||
>
|
||||
{item?.val === "0.00" ||
|
||||
item?.val === null ||
|
||||
@ -913,15 +913,15 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-gray-800"
|
||||
>
|
||||
Net Income Growth
|
||||
</th>
|
||||
{#each computeGrowthList(tableActualNetIncome, tableCombinedNetIncome) as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default border-b border-gray-800"
|
||||
>
|
||||
{#if index === 0 || item?.growth === null}
|
||||
n/a
|
||||
@ -948,15 +948,15 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary border-b border-gray-600">
|
||||
<th
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-[#27272A]"
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-gray-800"
|
||||
>
|
||||
EBITDA
|
||||
</th>
|
||||
{#each tableCombinedEbitda as item}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-[#27272A] bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-gray-800 bg-default"
|
||||
>
|
||||
{item?.val === "0.00" ||
|
||||
item?.val === null ||
|
||||
@ -967,15 +967,15 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-gray-800"
|
||||
>
|
||||
EBITDA Growth
|
||||
</th>
|
||||
{#each computeGrowthList(tableActualEbitda, tableCombinedEbitda) as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default border-b border-gray-800"
|
||||
>
|
||||
{#if index === 0 || item?.growth === null}
|
||||
n/a
|
||||
@ -1002,14 +1002,14 @@
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<tr class="bg-primary border-b border-gray-600">
|
||||
<th
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-[#27272A]"
|
||||
class="text-white whitespace-nowrap text-sm sm:text-[1rem] text-start font-medium bg-primary border-b border-gray-800"
|
||||
>No. Analysts</th
|
||||
>
|
||||
{#each tableCombinedRevenue as item}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-[#27272A] bg-default"
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium border-b border-gray-800 bg-default"
|
||||
>
|
||||
{#if item?.FY > 24}
|
||||
{item?.numOfAnalysts === (null || 0)
|
||||
@ -1033,7 +1033,7 @@
|
||||
</div>
|
||||
<!--
|
||||
<div class="mt-5 text-gray-100 text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4">
|
||||
<svg class="w-5 h-5 inline-block mr-0.5 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"
|
||||
<svg class="w-5 h-5 inline-block mr-0.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"
|
||||
><path fill="#fff" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16" /></svg
|
||||
>
|
||||
For the current Fiscal Year we use available quarterly data. Complete annual data, used to compare against analyst estimates, is only finalized after the year ends.
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
class="w-full rounded-md {latestInfoDate(
|
||||
data?.getAnalystInsight?.date,
|
||||
)
|
||||
? 'bg-[#F9AB00] bg-opacity-[0.1]'
|
||||
? 'bg-[#F9AB00]/10'
|
||||
: 'bg-primary'} shadow-lg h-full pl-3 pt-2 pb-4"
|
||||
>
|
||||
<div class="flex flex-col items-start">
|
||||
@ -119,7 +119,7 @@
|
||||
>
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-2 text-blue-400 hover:sm:text-white"
|
||||
class="inline-block ml-2 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing">Pro Subscription</a
|
||||
>
|
||||
</div>
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
class="aspect-577/310 w-[36.0625rem] bg-linear-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
style="clip-path: polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
></div>
|
||||
</div>
|
||||
@ -38,7 +38,7 @@
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
class="aspect-577/310 w-[36.0625rem] bg-linear-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
style="clip-path: polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
></div>
|
||||
</div>
|
||||
@ -52,7 +52,7 @@
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="installModal"
|
||||
class="flex-none rounded-full px-5 py-1 text-lg font-semibold text-black shadow-sm bg-[#fff] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900"
|
||||
class="flex-none rounded-full px-5 py-1 text-lg font-semibold text-black shadow-xs bg-[#fff] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900"
|
||||
>
|
||||
Install
|
||||
</label>
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
<label
|
||||
for="cookieConsent"
|
||||
on:click={() => cookieConsent("false")}
|
||||
class="cursor-pointer w-auto text-sm text-gray-800 underline transition-colors duration-300 md:w-auto text-white hover:text-gray-400 focus:outline-none"
|
||||
class="cursor-pointer w-auto text-sm text-gray-800 underline transition-colors duration-300 md:w-auto text-white hover:text-gray-400 focus:outline-hidden"
|
||||
>
|
||||
Reject All
|
||||
</label>
|
||||
@ -61,7 +61,7 @@
|
||||
<label
|
||||
for="cookieConsent"
|
||||
on:click={() => cookieConsent("true")}
|
||||
class="text-xs cursor-pointer w-auto md:w-auto font-medium bg-gray-800 rounded-md hover:bg-gray-700 text-white px-4 py-2.5 duration-300 transition-colors focus:outline-none"
|
||||
class="text-xs cursor-pointer w-auto md:w-auto font-medium bg-gray-800 rounded-md hover:bg-gray-700 text-white px-4 py-2.5 duration-300 transition-colors focus:outline-hidden"
|
||||
>
|
||||
Accept All Cookies
|
||||
</label>
|
||||
|
||||
@ -343,7 +343,7 @@
|
||||
class=" mb-5 text-gray-100 text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block mr-0.5 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block mr-0.5 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
@ -385,7 +385,7 @@
|
||||
>
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-2 text-blue-400 hover:sm:text-white"
|
||||
class="inline-block ml-2 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing">Pro Subscription</a
|
||||
>
|
||||
</div>
|
||||
|
||||
@ -293,7 +293,7 @@
|
||||
{#if data?.user?.tier !== "Pro" && i > 0}
|
||||
<button
|
||||
on:click={() => goto("/pricing")}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1"
|
||||
class="group relative z-1 rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1"
|
||||
>
|
||||
<span class="relative text-sm block font-semibold">
|
||||
{item.title}
|
||||
@ -311,7 +311,7 @@
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => changeTimePeriod(i)}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
|
||||
class="group relative z-1 rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
|
||||
@ -39,10 +39,10 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="lg:max-w-xl w-full bg-gradient-to-r from-orange-400 to-purple-900 p-4 rounded-none sm:rounded-md shadow-md m-auto"
|
||||
class="lg:max-w-xl w-full bg-linear-to-r from-orange-400 to-purple-900 p-4 rounded-none sm:rounded-md shadow-md m-auto"
|
||||
>
|
||||
<div
|
||||
class="container bg-gradient-to-r from-orange-400 to-purple-900 p-4 mt-4"
|
||||
class="container bg-linear-to-r from-orange-400 to-purple-900 p-4 mt-4"
|
||||
>
|
||||
<h2 class="text-2xl font-bold text-white text-center">
|
||||
50% OFF Your Subscription!
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
<div
|
||||
class="text-white text-[1rem] {latestInfoDate(rawData?.date)
|
||||
? 'bg-[#F9AB00] bg-opacity-[0.1] p-3 rounded-md'
|
||||
? 'bg-[#F9AB00]/10 p-3 rounded-md'
|
||||
: 'bg-default pl-1'}"
|
||||
>
|
||||
<div class="mt-1">
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
<div
|
||||
class="text-white text-[1rem] {latestInfoDate(rawData?.date)
|
||||
? 'bg-[#F9AB00] bg-opacity-[0.1] p-3 rounded-md'
|
||||
? 'bg-[#F9AB00]/10 p-3 rounded-md'
|
||||
: 'bg-default pl-1'} "
|
||||
>
|
||||
<div class="mt-1">
|
||||
|
||||
@ -293,7 +293,7 @@
|
||||
{#if data?.user?.tier !== "Pro" && i > 0}
|
||||
<button
|
||||
on:click={() => goto("/pricing")}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1"
|
||||
class="group relative z-1 rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1"
|
||||
>
|
||||
<span class="relative text-sm block font-semibold">
|
||||
{item.title}
|
||||
@ -311,7 +311,7 @@
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => changeTimePeriod(i)}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
|
||||
class="group relative z-1 rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<div class="fixed z-[100] bottom-8 sm:bottom-10 right-8 sm:right-16">
|
||||
<div class="fixed z-100 bottom-8 sm:bottom-10 right-8 sm:right-16">
|
||||
<label
|
||||
for="feedbackInfo"
|
||||
class="inline-flex items-center justify-center w-12 h-12 sm:w-full sm:h-10 font-semibold bg-gray-700 sm:bg-[#fff] ml-1 mr-0 sm:mr-2 rounded-full cursor-pointer"
|
||||
@ -121,9 +121,7 @@
|
||||
<input type="checkbox" id="feedbackInfo" class="modal-toggle" />
|
||||
|
||||
<dialog id="feedbackInfo" class="modal overflow-hidden p-3 sm:p-0">
|
||||
<label
|
||||
for="feedbackInfo"
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
|
||||
<label for="feedbackInfo" class="cursor-pointer modal-backdrop bg-[#000]/30"
|
||||
></label>
|
||||
|
||||
<div class="modal-box rounded w-full bg-primary border border-gray-600">
|
||||
@ -154,7 +152,7 @@
|
||||
{#each tabs as item, i}
|
||||
<button
|
||||
on:click={() => handleMode(i)}
|
||||
class="group relative z-[1] rounded-full w-1/3 min-w-20 py-1 {activeIdx ===
|
||||
class="cursor-pointer group relative z-1 rounded-full w-1/3 min-w-20 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
@ -177,7 +175,7 @@
|
||||
|
||||
<div class="p-2 w-full h-[200px] max-h-[1000px]">
|
||||
<textarea
|
||||
class="max-h-[1000px] h-[200px] textarea textarea-bordered placeholder-gray-300 w-full bg-primary ring-1 text-white border border-gray-600"
|
||||
class="max-h-[1000px] h-[200px] textarea textarea-bordered placeholder-gray-300 w-full bg-primary ring-1 ring-gray-600 focus:outline-gray-600 text-white"
|
||||
placeholder="Your feedback..."
|
||||
value={inputValue}
|
||||
on:input={handleInput}
|
||||
|
||||
@ -173,7 +173,7 @@
|
||||
>
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-2 text-blue-400 hover:sm:text-white"
|
||||
class="inline-block ml-2 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing">Pro Subscription</a
|
||||
>
|
||||
</div>
|
||||
|
||||
@ -26,16 +26,13 @@
|
||||
<input type="checkbox" {id} class="modal-toggle" />
|
||||
|
||||
<dialog {id} class="modal p-3 sm:p-0">
|
||||
<label
|
||||
for={id}
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
|
||||
></label>
|
||||
<label for={id} class="cursor-pointer modal-backdrop bg-[#000]/30"></label>
|
||||
|
||||
<!-- Desktop modal content -->
|
||||
<div
|
||||
class="modal-box rounded-md border border-gray-600 w-full bg-secondary flex flex-col items-center"
|
||||
>
|
||||
<div class="mx-auto h-1.5 w-20 flex-shrink-0 rounded-full" />
|
||||
<div class="mx-auto h-1.5 w-20 shrink-0 rounded-full" />
|
||||
<div class="text-white mb-5 text-center">
|
||||
<h3 class="font-bold text-xl sm:text-2xl mb-5">{title}</h3>
|
||||
<span class="text-white text-[1rem] font-normal">{@html content}</span>
|
||||
|
||||
@ -253,7 +253,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverGoogle}
|
||||
on:mouseleave={handleHoverGoogle}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredGoogle
|
||||
@ -302,7 +302,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverDiscord}
|
||||
on:mouseleave={handleHoverDiscord}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredDiscord
|
||||
@ -836,7 +836,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverGithub}
|
||||
on:mouseleave={handleHoverGithub}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredGithub
|
||||
@ -943,7 +943,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverGoogle}
|
||||
on:mouseleave={handleHoverGoogle}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredGoogle
|
||||
@ -992,7 +992,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverDiscord}
|
||||
on:mouseleave={handleHoverDiscord}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredDiscord
|
||||
@ -1526,7 +1526,7 @@ const output = await response.json();
|
||||
on:click={() => (oauthLoading = !oauthLoading)}
|
||||
on:mouseenter={handleHoverGithub}
|
||||
on:mouseleave={handleHoverGithub}
|
||||
class="cursor-pointer flex-shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
class="cursor-pointer shrink-0 rounded-full w-12 h-12 relative bg-default flex items-center justify-center border border-gray-600 sm:hover:bg-secondary text-white"
|
||||
>
|
||||
<svg
|
||||
class="{isHoveredGithub
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import "ol/ol.css";
|
||||
import Map from "ol/Map";
|
||||
import View from "ol/View";
|
||||
import TileLayer from "ol/layer/Tile";
|
||||
import XYZ from "ol/source/XYZ";
|
||||
import { fromLonLat } from "ol/proj";
|
||||
import VectorLayer from "ol/layer/Vector";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
import Feature from "ol/Feature";
|
||||
import Point from "ol/geom/Point";
|
||||
import { Style, Circle, Fill } from "ol/style";
|
||||
import { defaults as defaultInteractions } from "ol/interaction";
|
||||
|
||||
// White House coordinates
|
||||
const LON = -77.0365427;
|
||||
const LAT = 38.8950368;
|
||||
const ZOOM = 4.5;
|
||||
|
||||
let mapElement;
|
||||
let map;
|
||||
let animationFrame;
|
||||
let pulseProgress = 0;
|
||||
let vectorLayer;
|
||||
|
||||
// Pulsing style function
|
||||
const createPulseStyle = (progress) => {
|
||||
return new Style({
|
||||
image: new Circle({
|
||||
radius: 6 + 9 * progress,
|
||||
fill: new Fill({
|
||||
color: `rgba(46, 134, 222, ${0.3 - 0.3 * progress})`,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
// Animation loop function
|
||||
const animate = () => {
|
||||
pulseProgress = (pulseProgress + 0.02) % 1;
|
||||
const feature = vectorLayer.getSource().getFeatures()[0];
|
||||
if (feature) {
|
||||
feature.setStyle([
|
||||
new Style({
|
||||
image: new Circle({
|
||||
radius: 6,
|
||||
fill: new Fill({ color: "#2e86de" }),
|
||||
}),
|
||||
}),
|
||||
createPulseStyle(pulseProgress),
|
||||
]);
|
||||
}
|
||||
animationFrame = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (!browser) return;
|
||||
|
||||
// Determine if the user is on a mobile device.
|
||||
// Here we use a simple viewport width check—adjust the threshold if needed.
|
||||
const isMobile = window.innerWidth <= 640;
|
||||
|
||||
const whiteHousePoint = new Feature({
|
||||
geometry: new Point(fromLonLat([LON, LAT])),
|
||||
});
|
||||
|
||||
vectorLayer = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [whiteHousePoint],
|
||||
}),
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
target: mapElement,
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
|
||||
attributions:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||
}),
|
||||
}),
|
||||
vectorLayer,
|
||||
],
|
||||
view: new View({
|
||||
center: fromLonLat([LON, LAT]),
|
||||
zoom: ZOOM,
|
||||
minZoom: 2,
|
||||
maxZoom: 18,
|
||||
}),
|
||||
controls: [],
|
||||
// For mobile devices, disable all interactions to prevent dragging or zooming.
|
||||
interactions: isMobile
|
||||
? []
|
||||
: defaultInteractions({
|
||||
mouseWheelZoom: false, // Disable scroll zoom on desktop as well
|
||||
pinchZoom: false, // Disable pinch-to-zoom on desktop
|
||||
}),
|
||||
});
|
||||
|
||||
animate();
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
if (map) {
|
||||
map.setTarget(undefined);
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={mapElement} class="map-container" />
|
||||
|
||||
<style>
|
||||
.map-container {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
background-color: #1a1a1a;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.map-container {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,148 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { cn } from "$lib/utils";
|
||||
import ReviewCard from '$lib/components/ReviewCard.svelte';
|
||||
export let pauseOnHover: boolean = false;
|
||||
export let vertical: boolean = false;
|
||||
export let repeat: number = 4;
|
||||
export let reverse: boolean = false;
|
||||
|
||||
const firstReviewBatch = [
|
||||
{
|
||||
name: "Moh",
|
||||
body: "Awesome site 🔥! The real-time data and insights are invaluable for my investments.",
|
||||
img: "https://avatar.vercel.sh/moh",
|
||||
},
|
||||
{
|
||||
name: "Markus",
|
||||
body: "Speechless. The detailed charts and summaries are just what I needed.",
|
||||
img: "https://avatar.vercel.sh/markus",
|
||||
},
|
||||
{
|
||||
name: "Mintha",
|
||||
body: "Really good ❤. The interface and stock overviews are a game-changer.",
|
||||
img: "https://avatar.vercel.sh/mintha",
|
||||
},
|
||||
{
|
||||
name: "Steven",
|
||||
body: "Perfect, keep it up 🚀! The market analysis and forecasts are top-notch.",
|
||||
img: "https://avatar.vercel.sh/steven",
|
||||
},
|
||||
{
|
||||
name: "Lars",
|
||||
body: "Amazing! The site simplifies complex data into clear insights.",
|
||||
img: "https://avatar.vercel.sh/lars",
|
||||
}
|
||||
];
|
||||
|
||||
const secondReviewBatch = [
|
||||
{
|
||||
name: "Alanis",
|
||||
body: "Love it 🫰🏻! The charts with concise explanations make stock movements clear.",
|
||||
img: "https://avatar.vercel.sh/alanis",
|
||||
},
|
||||
{
|
||||
name: "Parviz",
|
||||
body: "Great, already shared 😎! This site is my go-to for stock information.",
|
||||
img: "https://avatar.vercel.sh/parviz",
|
||||
},
|
||||
{
|
||||
name: "Daniel",
|
||||
body: "Finally, a site that helps me find great stocks 💸. The research is spot-on.",
|
||||
img: "https://avatar.vercel.sh/daniel",
|
||||
},
|
||||
{
|
||||
name: "Hassan",
|
||||
body: "The best platform so far for researching stocks 💎.",
|
||||
img: "https://avatar.vercel.sh/hassan",
|
||||
},
|
||||
{
|
||||
name: "Pete",
|
||||
body: "The platform promised High Quality Wallstreet Data and they delivered it. Love it!",
|
||||
img: "https://avatar.vercel.sh/pete",
|
||||
},
|
||||
]
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<div
|
||||
class={cn(
|
||||
"slider group flex overflow-hidden p-2 [--duration:12s] [--gap:1rem] [gap:var(--gap)]"
|
||||
)}
|
||||
>
|
||||
{#each firstReviewBatch as item, i (i)}
|
||||
<div
|
||||
class={cn("flex shrink-0 justify-around animate-marquee flex-row [gap:var(--gap)]", {
|
||||
"group-hover:[animation-play-state:paused]": true,
|
||||
"[animation-direction:reverse]": true,
|
||||
})}
|
||||
>
|
||||
<ReviewCard img={item?.img} name={item?.name} body={item?.body}/>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
class={cn(
|
||||
"slider group flex overflow-hidden p-2 [--duration:12s] [--gap:1rem] [gap:var(--gap)]"
|
||||
)}
|
||||
>
|
||||
{#each secondReviewBatch as item, i (i)}
|
||||
<div
|
||||
class={cn("flex shrink-0 justify-around animate-marquee flex-row [gap:var(--gap)]", {
|
||||
"group-hover:[animation-play-state:paused]": true,
|
||||
"[animation-direction:reverse]": false,
|
||||
})}
|
||||
>
|
||||
<ReviewCard img={item?.img} name={item?.name} body={item?.body}/>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<style lang='scss'>
|
||||
|
||||
@mixin white-gradient {
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
$animationSpeed: 60s;
|
||||
|
||||
|
||||
// Styling
|
||||
.slider {
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
@include white-gradient;
|
||||
content: "";
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 2%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: rotateZ(180deg);
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -183,7 +183,7 @@
|
||||
<div class="w-full aspect-video">
|
||||
<div class="mb-3 sm:order-3 lg:pr-2">
|
||||
<div
|
||||
class="group relative block cursor-pointer bg-black bg-cover bg-[center_50%] object-contain after:block after:pb-[56.25%] after:content-[''] rounded-sm focus:outline-none focus:ring-2 focus:ring-blue-brand_light focus:ring-offset-2"
|
||||
class="group relative block cursor-pointer bg-black bg-cover bg-[center_50%] object-contain after:block after:pb-[56.25%] after:content-[''] rounded-sm focus:outline-hidden focus:ring-2 focus:ring-blue-brand_light focus:ring-offset-2"
|
||||
style="background-image: url({item?.image});"
|
||||
tabindex="0"
|
||||
on:click={() => handlePlayClick(index)}
|
||||
@ -222,7 +222,7 @@
|
||||
target="_blank"
|
||||
class="w-full sm:max-w-56 h-fit max-h-96 sm:mr-3 border border-gray-800 rounded-md"
|
||||
>
|
||||
<div class="flex-shrink-0 m-auto">
|
||||
<div class="shrink-0 m-auto">
|
||||
<img
|
||||
src={item?.image}
|
||||
class="h-auto w-full rounded-md"
|
||||
|
||||
@ -849,7 +849,7 @@
|
||||
</span>
|
||||
</p>
|
||||
<button
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-none"
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-hidden"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8"
|
||||
|
||||
@ -883,7 +883,7 @@
|
||||
</span>
|
||||
</p>
|
||||
<button
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-none"
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-hidden"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8"
|
||||
|
||||
@ -253,7 +253,7 @@
|
||||
class="text-gray-100 text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block sm:mr-2 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
|
||||
@ -1,157 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
|
||||
export let quantity = 30;
|
||||
export let staticity = 50;
|
||||
export let ease = 50;
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let canvasContainer: HTMLDivElement;
|
||||
|
||||
class ParticleAnimation {
|
||||
canvas: HTMLCanvasElement;
|
||||
context: CanvasRenderingContext2D;
|
||||
dpr: number;
|
||||
settings: { quantity: number; staticity: number; ease: number };
|
||||
circles: any[];
|
||||
canvasSize: { w: number; h: number };
|
||||
initCanvas: () => void;
|
||||
resizeCanvas: () => void;
|
||||
drawCircle: (circle: any, update?: boolean) => void;
|
||||
drawParticles: () => void;
|
||||
animate: () => void;
|
||||
|
||||
constructor(el: HTMLCanvasElement, options = {}) {
|
||||
this.canvas = el;
|
||||
if (!this.canvas) return;
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
|
||||
this.settings = {
|
||||
quantity: options.quantity || 30,
|
||||
staticity: options.staticity || 50,
|
||||
ease: options.ease || 50,
|
||||
};
|
||||
this.circles = [];
|
||||
this.canvasSize = {
|
||||
w: 0,
|
||||
h: 0,
|
||||
};
|
||||
this.initCanvas = this.initCanvas.bind(this);
|
||||
this.resizeCanvas = this.resizeCanvas.bind(this);
|
||||
this.drawCircle = this.drawCircle.bind(this);
|
||||
this.drawParticles = this.drawParticles.bind(this);
|
||||
this.animate = this.animate.bind(this);
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initCanvas();
|
||||
this.animate();
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('resize', this.initCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
initCanvas() {
|
||||
this.resizeCanvas();
|
||||
this.drawParticles();
|
||||
}
|
||||
|
||||
resizeCanvas() {
|
||||
this.circles.length = 0;
|
||||
this.canvasSize.w = this.canvas.parentElement.offsetWidth;
|
||||
this.canvasSize.h = this.canvas.parentElement.offsetHeight;
|
||||
this.canvas.width = this.canvasSize.w * this.dpr;
|
||||
this.canvas.height = this.canvasSize.h * this.dpr;
|
||||
this.canvas.style.width = this.canvasSize.w + 'px';
|
||||
this.canvas.style.height = this.canvasSize.h + 'px';
|
||||
this.context.scale(this.dpr, this.dpr);
|
||||
}
|
||||
|
||||
circleParams() {
|
||||
const x = Math.floor(Math.random() * this.canvasSize.w);
|
||||
const y = Math.floor(Math.random() * this.canvasSize.h);
|
||||
const translateX = 0;
|
||||
const translateY = 0;
|
||||
const size = Math.floor(Math.random() * 2) + 1;
|
||||
const alpha = 0;
|
||||
const targetAlpha = parseFloat((Math.random() * 0.6 + 0.1).toFixed(1));
|
||||
const dx = (Math.random() - 0.5) * 0.2;
|
||||
const dy = (Math.random() - 0.5) * 0.2;
|
||||
return { x, y, translateX, translateY, size, alpha, targetAlpha, dx, dy };
|
||||
}
|
||||
|
||||
drawCircle(circle, update = false) {
|
||||
const { x, y, translateX, translateY, size, alpha } = circle;
|
||||
this.context.translate(translateX, translateY);
|
||||
this.context.beginPath();
|
||||
this.context.arc(x, y, size, 0, 2 * Math.PI);
|
||||
this.context.fillStyle = `rgba(255, 255, 255, ${alpha})`;
|
||||
this.context.fill();
|
||||
this.context.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
|
||||
if (!update) {
|
||||
this.circles.push(circle);
|
||||
}
|
||||
}
|
||||
|
||||
clearContext() {
|
||||
this.context.clearRect(0, 0, this.canvasSize.w, this.canvasSize.h);
|
||||
}
|
||||
|
||||
drawParticles() {
|
||||
this.clearContext();
|
||||
const particleCount = this.settings.quantity;
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
const circle = this.circleParams();
|
||||
this.drawCircle(circle);
|
||||
}
|
||||
}
|
||||
|
||||
animate() {
|
||||
this.clearContext();
|
||||
this.circles.forEach((circle) => {
|
||||
const { x, y, dx, dy, alpha, targetAlpha } = circle;
|
||||
circle.x += dx;
|
||||
circle.y += dy;
|
||||
|
||||
// Wrap particles around the canvas edges
|
||||
if (circle.x > this.canvasSize.w) circle.x = 0;
|
||||
if (circle.x < 0) circle.x = this.canvasSize.w;
|
||||
if (circle.y > this.canvasSize.h) circle.y = 0;
|
||||
if (circle.y < 0) circle.y = this.canvasSize.h;
|
||||
|
||||
circle.alpha += alpha < targetAlpha ? 0.01 : -0.01;
|
||||
circle.alpha = Math.min(Math.max(circle.alpha, 0), targetAlpha);
|
||||
this.drawCircle(circle, true);
|
||||
});
|
||||
if (typeof window !== 'undefined') {
|
||||
window.requestAnimationFrame(this.animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let animation: ParticleAnimation;
|
||||
|
||||
onMount(() => {
|
||||
if (canvas) {
|
||||
animation = new ParticleAnimation(canvas, { quantity, staticity, ease });
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.removeEventListener('resize', animation.initCanvas);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={canvasContainer}>
|
||||
<canvas bind:this={canvas} data-particle-animation></canvas>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,339 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
retailVolumeComponent,
|
||||
displayCompanyName,
|
||||
stockTicker,
|
||||
assetType,
|
||||
etfTicker,
|
||||
screenWidth,
|
||||
getCache,
|
||||
setCache,
|
||||
} from "$lib/store";
|
||||
import InfoModal from "$lib/components/InfoModal.svelte";
|
||||
import { Chart } from "svelte-echarts";
|
||||
import { abbreviateNumber, formatDateRange, monthNames } from "$lib/utils";
|
||||
import { init, use } from "echarts/core";
|
||||
import { LineChart, BarChart } from "echarts/charts";
|
||||
import { GridComponent, TooltipComponent } from "echarts/components";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
|
||||
use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
|
||||
|
||||
export let data: any;
|
||||
|
||||
let isLoaded = false;
|
||||
let historyData: Array<{ date: string; traded: number; sentiment: number }> =
|
||||
[];
|
||||
let rawData: { history: typeof historyData; lastDate?: string } | null = null;
|
||||
let optionsData: any;
|
||||
let avgVolume: number | string = 0;
|
||||
let avgSentiment: string = "";
|
||||
let monthlyVolume: string | number = 0;
|
||||
let lowestSentiment: string | number = 0;
|
||||
let highestSentiment: string | number = 0;
|
||||
|
||||
function findMonthlyValue(data: any[], lastDateStr: string) {
|
||||
if (!data || !data[0]?.sentiment) {
|
||||
console.error("Sentiment is undefined or missing in the data:", data);
|
||||
$retailVolumeComponent = false;
|
||||
return;
|
||||
}
|
||||
const lastDate = new Date(lastDateStr);
|
||||
const firstDate = new Date(lastDate.getFullYear(), lastDate.getMonth(), 1);
|
||||
const filteredData = data.filter((item) => {
|
||||
const currentDate = new Date(item.date);
|
||||
return currentDate >= firstDate && currentDate <= lastDate;
|
||||
});
|
||||
|
||||
monthlyVolume = filteredData.reduce(
|
||||
(acc, item) => acc + (item.traded || 0),
|
||||
0,
|
||||
);
|
||||
monthlyVolume =
|
||||
monthlyVolume > 100e3 ? abbreviateNumber(monthlyVolume, true) : "< $100K";
|
||||
|
||||
const sentiments = filteredData.map((item) => parseFloat(item.sentiment));
|
||||
lowestSentiment = Math.min(...sentiments).toFixed(0);
|
||||
highestSentiment = Math.max(...sentiments).toFixed(0);
|
||||
}
|
||||
|
||||
function getPlotOptions() {
|
||||
const dates = historyData.map((item) => item.date);
|
||||
const tradingList = historyData.map((item) => item.traded);
|
||||
const sentimentList = historyData.map((item) => item.sentiment);
|
||||
|
||||
findMonthlyValue(historyData, rawData?.lastDate || "");
|
||||
|
||||
const totalTraded = tradingList.reduce((acc, traded) => acc + traded, 0);
|
||||
avgVolume = totalTraded / tradingList.length;
|
||||
avgSentiment =
|
||||
sentimentList.reduce((acc, sentiment) => acc + sentiment, 0) /
|
||||
tradingList.length >
|
||||
1
|
||||
? "Bullish"
|
||||
: "Bearish";
|
||||
|
||||
return {
|
||||
silent: true,
|
||||
animation: false,
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
hideDelay: 100,
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "3%",
|
||||
bottom: "0%",
|
||||
top: "5%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
data: dates,
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
formatter: (value: string) => {
|
||||
const [year, month, day] = value.split("-");
|
||||
return `${day} ${monthNames[parseInt(month) - 1]}`;
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
splitLine: { show: false },
|
||||
axisLabel: { show: false },
|
||||
},
|
||||
{
|
||||
type: "value",
|
||||
splitLine: { show: false },
|
||||
position: "right",
|
||||
axisLabel: { show: false },
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "Volume [$]",
|
||||
data: tradingList,
|
||||
type: "line",
|
||||
itemStyle: { color: "#fff" },
|
||||
showSymbol: false,
|
||||
},
|
||||
{
|
||||
name: "Retail Sentiment",
|
||||
data: sentimentList,
|
||||
type: "bar",
|
||||
yAxisIndex: 1,
|
||||
itemStyle: {
|
||||
color: (params: any) => (params.data >= 0 ? "#22C55E" : "#F71F4F"),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const getRetailVolume = async (ticker: string) => {
|
||||
const cachedData = getCache(ticker, "getRetailVolume");
|
||||
if (cachedData) {
|
||||
rawData = cachedData;
|
||||
historyData = rawData.history;
|
||||
} else {
|
||||
const response = await fetch("/api/ticker-data", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ ticker, path: "retail-volume" }),
|
||||
});
|
||||
rawData = await response.json();
|
||||
historyData = rawData.history;
|
||||
setCache(ticker, rawData, "getRetailVolume");
|
||||
}
|
||||
$retailVolumeComponent = !!rawData;
|
||||
};
|
||||
|
||||
$: {
|
||||
if (
|
||||
($assetType === "stock" ? $stockTicker : $etfTicker) &&
|
||||
typeof window !== "undefined"
|
||||
) {
|
||||
isLoaded = false;
|
||||
const ticker = $assetType === "stock" ? $stockTicker : $etfTicker;
|
||||
Promise.all([getRetailVolume(ticker)])
|
||||
.then(() => {
|
||||
optionsData = rawData ? getPlotOptions() : null;
|
||||
isLoaded = true;
|
||||
})
|
||||
.catch((error) => console.error("An error occurred:", error));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="overflow-hidden text-white h-full pb-8">
|
||||
<main class="overflow-hidden">
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="retailTraderTrackerInfo"
|
||||
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
|
||||
>
|
||||
Retail Trader Activity
|
||||
</label>
|
||||
<InfoModal
|
||||
title={"Retail Trader Activity"}
|
||||
content={"Gain insights into Retail Trader activity with the following visualization: The green bar illustrates the daily volume trend, signifying a bullish sentiment if it ranges from 0 to 100, or bearish if it spans from -100 to just below 0. The white line depicts the daily trading volume of retail investors."}
|
||||
id={"retailTraderTrackerInfo"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isLoaded}
|
||||
{#if Object?.keys(rawData)?.length !== 0}
|
||||
<div class="w-full flex flex-col items-start">
|
||||
<div class="text-white text-[1rem] mt-2 mb-2 w-full">
|
||||
In the past six months, the {$displayCompanyName} had an average retail
|
||||
investor volume of
|
||||
<span class="font-semibold"
|
||||
>{avgVolume > 100e3
|
||||
? abbreviateNumber(avgVolume, true)
|
||||
: "< $100K"}</span
|
||||
>, with a prevailing
|
||||
{#if avgSentiment === "Bullish"}
|
||||
<span class="text-[#00FC50]">
|
||||
<svg
|
||||
class="w-6 h-6 sm:w-7 sm:h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><g
|
||||
fill="none"
|
||||
stroke="#00FC50"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2.5"
|
||||
><path d="m3 17l6-6l4 4l8-8" /><path d="M17 7h4v4" /></g
|
||||
></svg
|
||||
>
|
||||
{avgSentiment}
|
||||
</span>
|
||||
{:else if avgSentiment === "Bearish"}
|
||||
<span class="text-[#E57C34]">
|
||||
<svg
|
||||
class="w-6 h-6 sm:w-7 sm:h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#ff2f1f"
|
||||
d="M244 136v64a12 12 0 0 1-12 12h-64a12 12 0 0 1 0-24h35l-67-67l-31.51 31.52a12 12 0 0 1-17 0l-72-72a12 12 0 0 1 17-17L96 127l31.51-31.52a12 12 0 0 1 17 0L220 171v-35a12 12 0 0 1 24 0Z"
|
||||
/></svg
|
||||
>
|
||||
{avgSentiment}
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-[#FF2F1F]">
|
||||
<svg
|
||||
class="w-6 h-6 sm:w-7 sm:h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path fill="#e57c34" d="m22 12l-4-4v3H3v2h15v3l4-4Z" /></svg
|
||||
>
|
||||
Neutral
|
||||
</span>
|
||||
{/if} trend.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pb-8 sm:pb-2 rounded-md bg-default">
|
||||
<div class="app w-full h-[300px] mt-5">
|
||||
<Chart {init} options={optionsData} class="chart" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-white mt-6">
|
||||
The line chart shows dollar volume, while the bar chart indicates
|
||||
sentiment from -100 to 100, with negative values for more selling and
|
||||
positive values for more buying.
|
||||
</div>
|
||||
|
||||
<h2
|
||||
class="mt-10 mr-1 flex flex-row items-center text-white text-xl sm:text-2xl font-bold mb-3"
|
||||
>
|
||||
Latest Information
|
||||
</h2>
|
||||
<span class="text-white">
|
||||
On {new Date(rawData?.lastDate)?.toLocaleString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
daySuffix: "2-digit",
|
||||
})}, retail traders accounted for
|
||||
<span class="font-semibold"
|
||||
>{rawData?.retailStrength > 0.01
|
||||
? rawData?.retailStrength
|
||||
: "< 0.01"}%</span
|
||||
> of the trading volume.
|
||||
</span>
|
||||
<div class="flex justify-start items-center w-full m-auto mt-6">
|
||||
<table class="w-full" data-test="statistics-table">
|
||||
<tbody>
|
||||
<tr class="border-y border-gray-800 odd:bg-odd">
|
||||
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
|
||||
<span>Date</span>
|
||||
</td>
|
||||
<td
|
||||
class="px-[5px] whitespace-nowrap py-1.5 text-right font-medium xs:px-2.5 xs:py-2"
|
||||
>
|
||||
{formatDateRange(rawData?.lastDate)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-y border-gray-800 odd:bg-odd">
|
||||
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
|
||||
<span>Volume in $</span>
|
||||
</td>
|
||||
<td
|
||||
class="px-[5px] py-1.5 text-right font-medium xs:px-2.5 xs:py-2"
|
||||
>
|
||||
{monthlyVolume}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="border-y border-gray-800 odd:bg-odd">
|
||||
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
|
||||
<span>Retail Sentiment Range</span>
|
||||
</td>
|
||||
<td
|
||||
class="px-[5px] py-1.5 text-right font-medium xs:px-2.5 xs:py-2"
|
||||
>
|
||||
Between {lowestSentiment} to {highestSentiment}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.app {
|
||||
height: 300px;
|
||||
max-width: 100%; /* Ensure chart width doesn't exceed the container */
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.app {
|
||||
height: 210px;
|
||||
}
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<button
|
||||
class="mr-1.5 cursor-pointer text-gray-300 sm:hover:text-red-500 focus:outline-none"
|
||||
class="mr-1.5 cursor-pointer text-gray-300 sm:hover:text-red-500 focus:outline-hidden"
|
||||
title="Remove filter"
|
||||
>
|
||||
<svg
|
||||
@ -99,7 +99,7 @@
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="dropdown-content absolute z-40 mt-2 rounded-md bg-[#181C1F] py-1 shadow-lg border border-gray-600 focus:outline-none"
|
||||
class="dropdown-content absolute z-40 mt-2 rounded-md bg-[#181C1F] py-1 shadow-lg border border-gray-600 focus:outline-hidden"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
>
|
||||
@ -144,7 +144,7 @@
|
||||
<button
|
||||
on:click={() => changeValue(newValue)}
|
||||
class="block w-full border-b border-gray-600 px-4 py-2 text-left text-sm text-white last:border-0 sm:hover:bg-gray-100 sm:hover:text-gray-900
|
||||
focus:bg-blue-100 focus:text-gray-900 focus:outline-none"
|
||||
focus:bg-blue-100 focus:text-gray-900 focus:outline-hidden"
|
||||
>
|
||||
{condition}
|
||||
{newValue}{unit}
|
||||
|
||||
@ -1,253 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { secFilingsClicked, stockTicker, clientSideCache } from "$lib/store";
|
||||
import * as Tabs from "$lib/components/shadcn/tabs/index.js";
|
||||
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
let secFilingsList;
|
||||
|
||||
let displayList = [];
|
||||
let accordionOpen = {};
|
||||
let newData;
|
||||
let isLoaded = false;
|
||||
|
||||
function changeSECType(secType) {
|
||||
switch (secType) {
|
||||
case "8-K":
|
||||
prepareData(secFilingsList?.eightK);
|
||||
break;
|
||||
case "10-K":
|
||||
prepareData(secFilingsList?.tenK);
|
||||
break;
|
||||
case "10-Q":
|
||||
prepareData(secFilingsList?.tenQ);
|
||||
break;
|
||||
// Default case in case changeType doesn't match any of the specified cases
|
||||
default:
|
||||
// Handle the default case or leave it empty if not needed
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareData(dataset) {
|
||||
if (dataset?.length !== 0) {
|
||||
newData = {};
|
||||
accordionOpen = {};
|
||||
|
||||
dataset?.forEach((item) => {
|
||||
// Extract year from the date
|
||||
const year = new Date(item?.date)?.getFullYear()?.toString();
|
||||
|
||||
// Check if the year already exists in newData
|
||||
if (!newData[year]) {
|
||||
// If not, initialize a new entry for the year
|
||||
newData[year] = {
|
||||
year: year,
|
||||
totalReports: 0,
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
// Increment the totalReports count
|
||||
newData[year].totalReports++;
|
||||
|
||||
// Add the current item to the 'data' array
|
||||
newData[year].data?.push(item);
|
||||
});
|
||||
|
||||
// Convert newData object to an array of values
|
||||
displayList = Object?.values(newData);
|
||||
displayList = displayList?.sort((a, b) => b?.year - a?.year);
|
||||
// Output the displayList
|
||||
displayList = [...displayList];
|
||||
//console.log(displayList)
|
||||
} else {
|
||||
displayList = [];
|
||||
}
|
||||
}
|
||||
|
||||
async function handleAccordion(year) {
|
||||
accordionOpen[year] = !accordionOpen[year];
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
if ($clientSideCache[$stockTicker]?.getSECFilings) {
|
||||
secFilingsList = $clientSideCache[$stockTicker]?.getSECFilings;
|
||||
} else {
|
||||
const postData = { ticker: $stockTicker, path: "get-sec-filings" };
|
||||
const response = await fetch("/api/ticker-data", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(postData),
|
||||
});
|
||||
|
||||
secFilingsList = await response.json();
|
||||
$clientSideCache[$stockTicker].getSECFilings = secFilingsList;
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (
|
||||
$stockTicker &&
|
||||
typeof window !== "undefined" &&
|
||||
$secFilingsClicked === true
|
||||
) {
|
||||
isLoaded = false;
|
||||
$secFilingsClicked = false;
|
||||
accordionOpen = {};
|
||||
|
||||
const asyncFunctions = [fetchData()];
|
||||
Promise.all(asyncFunctions)
|
||||
.then((results) => {
|
||||
prepareData(secFilingsList?.eightK);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("An error occurred:", error);
|
||||
});
|
||||
|
||||
isLoaded = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="space-y-3 sm:pt-5">
|
||||
<div class="bg-[#000] h-auto w-screen">
|
||||
<!--Start Header-->
|
||||
<div class="bg-[#000] w-full p-1 flex flex-col items-center pb-5 h-auto">
|
||||
<h2 class="text-center m-auto text-lg font-semibold text-white mt-5">
|
||||
SEC Filings
|
||||
</h2>
|
||||
|
||||
<div class="w-11/12 mt-5">
|
||||
<div class="relative right-0 bg-primary rounded-md">
|
||||
<Tabs.Root value="eightK" class="w-full">
|
||||
<Tabs.List class="grid w-full grid-cols-3 bg-primary">
|
||||
<Tabs.Trigger on:click={() => changeSECType("8-K")} value="eightK"
|
||||
>8-K</Tabs.Trigger
|
||||
>
|
||||
<Tabs.Trigger on:click={() => changeSECType("10-K")} value="tenK"
|
||||
>10-K</Tabs.Trigger
|
||||
>
|
||||
<Tabs.Trigger on:click={() => changeSECType("10-Q")} value="tenQ"
|
||||
>10-Q</Tabs.Trigger
|
||||
>
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--End Header-->
|
||||
{#if isLoaded}
|
||||
{#if displayList?.length !== 0}
|
||||
<div class="mt-5 w-full">
|
||||
{#each displayList as item}
|
||||
<div
|
||||
class="flex flex-col justify-center m-auto items-start rounded-md bg-primary shadow-lg h-auto w-11/12 mb-3"
|
||||
transition:fade={{ delay: 0, duration: 80 }}
|
||||
in={accordionOpen[item?.year]}
|
||||
>
|
||||
<div class="flex flex-row items-center w-full p-3">
|
||||
<div
|
||||
class="flex-shrink-0 mr-2 rounded-full w-12 h-12 relative bg-[#000]"
|
||||
>
|
||||
<svg
|
||||
class="rounded-full w-7 h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="white"
|
||||
d="m18 22l3-3l-.7-.7l-1.8 1.8V16h-1v4.1l-1.8-1.8l-.7.7zm-6-11.15l5.925-3.425L12 4L6.075 7.425zm-9 6.275V6.875L12 1.7l9 5.175V12h-2V9.1l-7.025 4.05L5 9.1v6.85l6.025 3.475v2.3zM18 24q-2.075 0-3.537-1.463T13 19q0-2.075 1.463-3.537T18 14q2.075 0 3.538 1.463T23 19q0 2.075-1.463 3.538T18 24m-6.975-12.275"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => handleAccordion(item?.year)}
|
||||
class="flex flex-row items-center w-full"
|
||||
>
|
||||
<div class="flex flex-col items-start w-full">
|
||||
<span
|
||||
class="text-white text-sm sm:text-md font-medium text-start mt-2"
|
||||
>
|
||||
{item?.year}
|
||||
</span>
|
||||
<span
|
||||
class="text-white text-opacity-[0.6] text-xs text-start mb-2"
|
||||
>
|
||||
Total Reports: {item?.totalReports}
|
||||
</span>
|
||||
</div>
|
||||
<svg
|
||||
class="h-6 w-6 inline-block transform transition-transform mr-5 {accordionOpen[
|
||||
item?.year
|
||||
]
|
||||
? ''
|
||||
: 'rotate-180'}"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1024 1024"
|
||||
><path
|
||||
fill="#fff"
|
||||
d="m488.832 344.32l-339.84 356.672a32 32 0 0 0 0 44.16l.384.384a29.44 29.44 0 0 0 42.688 0l320-335.872l319.872 335.872a29.44 29.44 0 0 0 42.688 0l.384-.384a32 32 0 0 0 0-44.16L535.168 344.32a32 32 0 0 0-46.336 0z"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{#if accordionOpen[item?.year]}
|
||||
{#each item?.data as entry}
|
||||
<div
|
||||
class="shadow-lg bg-[#000] bg-opacity-[0.5] w-11/12 rounded-md p-4 mb-3 m-auto flex flex-row justify-center items-center"
|
||||
>
|
||||
<div class="flex flex-col -mt-2 w-full">
|
||||
<div class="flex flex-row items-center w-full">
|
||||
<span
|
||||
class="text-white text-sm sm:text-md font-medium text-start mb-2 mr-auto mt-2"
|
||||
>
|
||||
{new Date(entry?.date)?.toLocaleString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
daySuffix: "2-digit",
|
||||
})}
|
||||
</span>
|
||||
<span
|
||||
class="text-white text-sm sm:text-md font-medium ml-auto"
|
||||
>
|
||||
<a
|
||||
href={entry?.link}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Check Report
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class=" mt-20 flex justify-center items-center text-2xl font-bold text-slate-700 mb-20 m-auto"
|
||||
>
|
||||
No data available
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<!--End Similar Stocks Card -->
|
||||
@ -1,82 +0,0 @@
|
||||
<script lang='ts'>
|
||||
import { getContext } from 'svelte';
|
||||
import * as Sankey from 'd3-sankey';
|
||||
|
||||
const { data, width, height } = getContext('LayerCake');
|
||||
|
||||
/** @type {Function} [colorLinks=d => '#fff'] - A function to return a color for the links. */
|
||||
export let colorLinks = d => '#fff';
|
||||
|
||||
/** @type {Function} [colorNodes=d => '#333'] - A function to return a color for each node. */
|
||||
export let colorNodes = d => '#fff';
|
||||
|
||||
/** @type {Function} [colorText=d => '#263238'] - A function to return a color for each text label. */
|
||||
export let colorText = d => '#fff';
|
||||
|
||||
/** @type {Number} [nodeWidth=5] - The width of each node, in pixels, passed to [`sankey.nodeWidth`](https://github.com/d3/d3-sankey#sankey_nodeWidth). */
|
||||
export let nodeWidth = 10;
|
||||
|
||||
/** @type {Number} [nodePadding=10] - The padding between nodes, passed to [`sankey.nodePadding`](https://github.com/d3/d3-sankey#sankey_nodePadding). */
|
||||
export let nodePadding = 35;
|
||||
|
||||
/** @type {Function} [linkSort=null] - How to sort the links, passed to [`sankey.linkSort`](https://github.com/d3/d3-sankey#sankey_linkSort). */
|
||||
export let linkSort = null;
|
||||
|
||||
/** @type {Function} [nodeId=d => d.id] - The ID field accessor, passed to [`sankey.nodeId`](https://github.com/d3/d3-sankey#sankey_nodeId). */
|
||||
export let nodeId = d => d.id;
|
||||
|
||||
/** @type {Function} [nodeAlign=d3.sankeyLeft] - An alignment function to position the Sankey blocks. See the [d3-sankey documentation](https://github.com/d3/d3-sankey#alignments) for more. */
|
||||
export let nodeAlign = Sankey.sankeyLeft;
|
||||
|
||||
$: sankey = Sankey.sankey()
|
||||
.nodeAlign(nodeAlign)
|
||||
.nodeWidth(nodeWidth)
|
||||
.nodePadding(nodePadding)
|
||||
.nodeId(nodeId)
|
||||
.size([$width, $height])
|
||||
.linkSort(linkSort);
|
||||
|
||||
$: sankeyData = sankey($data);
|
||||
|
||||
$: link = Sankey.sankeyLinkHorizontal();
|
||||
|
||||
$: fontSize = $width <= 320 ? 8 : 16;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
text {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<g class="sankey-layer">
|
||||
<g class='link-group'>
|
||||
{#each sankeyData.links as d}
|
||||
<path
|
||||
d={link(d)}
|
||||
fill='none'
|
||||
stroke={colorLinks(d)}
|
||||
stroke-opacity='0.5'
|
||||
stroke-width={d.width} />
|
||||
{/each}
|
||||
</g>
|
||||
<g class='rect-group'>
|
||||
{#each sankeyData.nodes as d, i}
|
||||
<rect
|
||||
x={d.x0}
|
||||
y={d.y0}
|
||||
height={d.y1 - d.y0}
|
||||
width={d.x1 - d.x0}
|
||||
fill={i ===(sankeyData.nodes.length-1) ? colorNodes(d) : '#EA7CCC'} />
|
||||
<text
|
||||
x={d.x0 < $width / 4 ? d.x1 + 6 : d.x0 - 6}
|
||||
y={(d.y1 + d.y0) / 2}
|
||||
dy="{(fontSize / 2) - 2}"
|
||||
style="fill: {colorText(d)};
|
||||
font-size: {fontSize}px;
|
||||
text-anchor: {d.x0 < $width / 4 ? 'start' : 'end'};">
|
||||
{d.id}
|
||||
</text>
|
||||
{/each}
|
||||
</g>
|
||||
</g>
|
||||
@ -323,7 +323,7 @@
|
||||
<Combobox.Input
|
||||
id="combobox-input"
|
||||
on:click={() => (inputValue = "")}
|
||||
class="grow rounded-sm border border-gray-600 py-2 pl-9 text-[1rem] placeholder-gray-400 focus:border-default focus:shadow-lg focus:outline-none focus:ring-0 tiny:pl-8 xs:pl-10 text-white md:py-2 w-full bg-secondary focus:bg-secondary"
|
||||
class="grow rounded-sm border border-gray-600 py-2 pl-9 text-[1rem] placeholder-gray-400 focus:border-default focus:shadow-lg focus:outline-hidden focus:ring-0 tiny:pl-8 xs:pl-10 text-white md:py-2 w-full bg-secondary focus:bg-secondary"
|
||||
placeholder="Company or stock symbol..."
|
||||
aria-label="Company or stock symbol..."
|
||||
/>
|
||||
@ -355,7 +355,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<Combobox.Content
|
||||
class="w-auto z-40 -mt-0.5 rounded-md border border-gray-700 bg-secondary px-1 py-3 shadow-popover outline-none"
|
||||
class="w-auto z-40 -mt-0.5 rounded-md border border-gray-700 bg-secondary px-1 py-3 shadow-popover outline-hidden"
|
||||
sideOffset={8}
|
||||
>
|
||||
{#if inputValue?.length > 0 && searchBarData?.length > 0}
|
||||
@ -366,7 +366,7 @@
|
||||
</div>
|
||||
{#each searchBarData as item}
|
||||
<Combobox.Item
|
||||
class="cursor-pointer text-white border-b border-gray-600 last:border-none flex h-fit w-auto select-none items-center rounded-button py-3 pl-2 pr-1.5 text-sm capitalize outline-none transition-all duration-75 data-[highlighted]:bg-primary"
|
||||
class="cursor-pointer text-white border-b border-gray-600 last:border-none flex h-fit w-auto select-none items-center rounded-button py-3 pl-2 pr-1.5 text-sm capitalize outline-hidden transition-all duration-75 data-highlighted:bg-primary"
|
||||
value={item?.symbol}
|
||||
label={item?.name}
|
||||
on:click={() => handleSearch(item?.symbol, item?.type)}
|
||||
@ -386,7 +386,7 @@
|
||||
</div>
|
||||
{#each searchHistory?.length > 0 ? searchHistory : popularList as item}
|
||||
<Combobox.Item
|
||||
class="cursor-pointer text-white border-b border-gray-600 last:border-none flex h-fit w-auto select-none items-center rounded-button py-3 pl-2 pr-1.5 text-sm capitalize outline-none transition-all duration-75 data-[highlighted]:bg-primary"
|
||||
class="cursor-pointer text-white border-b border-gray-600 last:border-none flex h-fit w-auto select-none items-center rounded-button py-3 pl-2 pr-1.5 text-sm capitalize outline-hidden transition-all duration-75 data-highlighted:bg-primary"
|
||||
value={item?.symbol}
|
||||
label={item?.name}
|
||||
on:click={() => handleSearch(item?.symbol, item?.type)}
|
||||
@ -411,7 +411,7 @@
|
||||
|
||||
<label
|
||||
for="searchBarModal"
|
||||
class="sm:hidden cursor-pointer p-2 sm:hover:bg-primary text-gray-300 sm:hover:text-white flex-shrink-0 flex items-center justify-center border border-gray-600 rounded-md"
|
||||
class="sm:hidden cursor-pointer p-2 sm:hover:bg-primary text-gray-300 sm:hover:text-white shrink-0 flex items-center justify-center border border-gray-600 rounded-md"
|
||||
>
|
||||
<Search class="h-[20px] w-[20px]" />
|
||||
</label>
|
||||
@ -427,7 +427,7 @@
|
||||
<label for="searchBarModal" class="cursor-pointer modal-backdrop"></label>
|
||||
|
||||
<div
|
||||
class="z-[999] modal-box overflow-hidden rounded-md bg-secondary border border-gray-600 sm:my-8 sm:m-auto sm:h-auto w-full sm:w-3/4 lg:w-1/2 2xl:w-1/3"
|
||||
class="z-999 modal-box overflow-hidden rounded-md bg-secondary border border-gray-600 sm:my-8 sm:m-auto sm:h-auto w-full sm:w-3/4 lg:w-1/2 2xl:w-1/3"
|
||||
>
|
||||
<label
|
||||
for="searchBarModal"
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
class="mt-5 text-gray-100 text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block mr-0.5 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block mr-0.5 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
|
||||
@ -149,7 +149,7 @@
|
||||
<span class="block font-semibold">Website</span>
|
||||
<a
|
||||
href={website}
|
||||
class="hover:sm:text-white truncate text-blue-400"
|
||||
class="sm:hover:text-white truncate text-blue-400"
|
||||
target="_blank">{website}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
@ -225,7 +225,7 @@
|
||||
{#each tabs as item, i}
|
||||
<button
|
||||
on:click={() => changeTab(i)}
|
||||
class="group relative z-[1] rounded-full px-3 py-1 {activeIdx ===
|
||||
class="group relative z-1 rounded-full px-3 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
|
||||
@ -1,266 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
taRatingComponent,
|
||||
stockTicker,
|
||||
etfTicker,
|
||||
cryptoTicker,
|
||||
assetType,
|
||||
getCache,
|
||||
setCache,
|
||||
} from "$lib/store";
|
||||
import SignalBar from "$lib/components/SignalBar.svelte";
|
||||
import InfoModal from "$lib/components/InfoModal.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
let rawData = [];
|
||||
let isLoaded = false;
|
||||
let signalList = [];
|
||||
let showFullStats = false;
|
||||
let overallSignal = "n/a";
|
||||
let buyCount = 0;
|
||||
let sellCount = 0;
|
||||
let neutralCount = 0;
|
||||
|
||||
const modalContent = `
|
||||
Momentum indicators gauge the speed at which a financial instrument's price is changing, indicating the strength of its recent price movements.<br><br>
|
||||
On the other hand, trend indicators help identify the direction in which the price of an asset is moving over time, highlighting whether it's in an upward, downward, or sideways trend.<br><br>
|
||||
Together, these indicators assist in evaluating the overall market sentiment and potential future price movements.
|
||||
`;
|
||||
|
||||
async function getTaRating(ticker) {
|
||||
const cachedData = getCache(ticker, "getTaRating");
|
||||
if (cachedData) {
|
||||
rawData = cachedData;
|
||||
} else {
|
||||
try {
|
||||
const response = await fetch("/api/ticker-data", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ ticker: ticker, path: "stock-rating" }),
|
||||
});
|
||||
rawData = await response?.json();
|
||||
|
||||
setCache(ticker, rawData, "getTaRating");
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch swap data:", error);
|
||||
rawData = {};
|
||||
}
|
||||
}
|
||||
if (Object?.keys(rawData)?.length !== 0) {
|
||||
$taRatingComponent = true;
|
||||
} else {
|
||||
$taRatingComponent = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function updateData() {
|
||||
if (
|
||||
($assetType === "stock"
|
||||
? $stockTicker
|
||||
: $assetType === "etf"
|
||||
? $etfTicker
|
||||
: $cryptoTicker) &&
|
||||
typeof window !== "undefined"
|
||||
) {
|
||||
isLoaded = false;
|
||||
const ticker =
|
||||
$assetType === "stock"
|
||||
? $stockTicker
|
||||
: $assetType === "etf"
|
||||
? $etfTicker
|
||||
: $cryptoTicker;
|
||||
|
||||
try {
|
||||
await getTaRating(ticker);
|
||||
showFullStats = false;
|
||||
overallSignal = rawData?.overallSignal;
|
||||
signalList = rawData?.signalList || [];
|
||||
buyCount = 0;
|
||||
sellCount = 0;
|
||||
neutralCount = 0;
|
||||
|
||||
signalList?.forEach((item) => {
|
||||
switch (item?.signal) {
|
||||
case "Strong Buy":
|
||||
case "Buy":
|
||||
buyCount++;
|
||||
break;
|
||||
case "Sell":
|
||||
case "Strong Sell":
|
||||
sellCount++;
|
||||
break;
|
||||
default:
|
||||
neutralCount++;
|
||||
}
|
||||
});
|
||||
|
||||
isLoaded = true;
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($assetType || $stockTicker || $etfTicker || $cryptoTicker) {
|
||||
updateData();
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="overflow-hidden w-full">
|
||||
<main>
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="technicalIndicatorInfo"
|
||||
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
|
||||
>
|
||||
TA Indicators
|
||||
</label>
|
||||
<InfoModal
|
||||
title={"TA Indicators"}
|
||||
content={modalContent}
|
||||
id={"technicalIndicatorInfo"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isLoaded}
|
||||
{#if signalList?.length !== 0}
|
||||
{#if overallSignal !== "n/a"}
|
||||
<div class="text-white text-[1rem] sm:text-lg mt-3 mb-8 text-start">
|
||||
Out of 11 indicators, <span class="font-semibold text-[#00FC50]"
|
||||
>{buyCount}</span
|
||||
>
|
||||
indicates a Buy,
|
||||
<span class="font-semibold text-[#F8901E]">{neutralCount}</span> are
|
||||
Neutral and
|
||||
<span class="font-semibold text-[#FF2F1F]">{sellCount}</span>
|
||||
indicate a Sell. On average, the signal is to
|
||||
{#if overallSignal === "Buy" || overallSignal === "Strong Buy"}
|
||||
<span class="text-[#00FC50] sm:font-medium">
|
||||
<svg
|
||||
class="w-7 h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><g
|
||||
fill="none"
|
||||
stroke="#00FC50"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2.5"
|
||||
><path d="m3 17l6-6l4 4l8-8" /><path d="M17 7h4v4" /></g
|
||||
></svg
|
||||
>
|
||||
Buy.
|
||||
</span>
|
||||
{:else if overallSignal === "Neutral"}
|
||||
<span class="text-[#E57C34] sm:font-medium">
|
||||
<svg
|
||||
class="w-7 h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path fill="#e57c34" d="m22 12l-4-4v3H3v2h15v3l4-4Z" /></svg
|
||||
>
|
||||
Hold.
|
||||
</span>
|
||||
{:else if overallSignal === "Sell" || overallSignal === "Strong Sell"}
|
||||
<span class="text-[#FF2F1F] sm:font-medium">
|
||||
<svg
|
||||
class="w-7 h-7 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#ff2f1f"
|
||||
d="M244 136v64a12 12 0 0 1-12 12h-64a12 12 0 0 1 0-24h35l-67-67l-31.51 31.52a12 12 0 0 1-17 0l-72-72a12 12 0 0 1 17-17L96 127l31.51-31.52a12 12 0 0 1 17 0L220 171v-35a12 12 0 0 1 24 0Z"
|
||||
/></svg
|
||||
>
|
||||
Sell.
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-[#FF2F1F] sm:font-medium"> n/a. </span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!--Start Momentum Indicators-->
|
||||
<div class="w-full overflow-x-auto">
|
||||
<table class="table table-sm table-compact w-full mb-5 mt-5">
|
||||
<!-- head -->
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
class="text-white text-sm font-medium bg-default font-semibold"
|
||||
>Name</th
|
||||
>
|
||||
<th
|
||||
class="text-white text-sm font-medium bg-default font-semibold text-end"
|
||||
>Value</th
|
||||
>
|
||||
<th
|
||||
class="text-white text-sm font-medium bg-default font-semibold text-end"
|
||||
>Signal</th
|
||||
>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each showFullStats ? signalList : signalList?.slice(0, 3) as item, index}
|
||||
<tr
|
||||
class="border-y border-gray-800 odd:bg-odd sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] bg-default border-b-[#09090B] {index ===
|
||||
2 &&
|
||||
!showFullStats &&
|
||||
signalList?.length > 2
|
||||
? 'opacity-[0.3]'
|
||||
: ''}"
|
||||
>
|
||||
<td class="text-white text-sm sm:text-[1rem]">
|
||||
{item?.name}
|
||||
</td>
|
||||
|
||||
<td class="text-white text-end">
|
||||
<span class="text-white text-sm sm:text-[1rem] font-medium">
|
||||
{item?.value}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="text-white">
|
||||
<SignalBar signal={item?.signal} />
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<label
|
||||
on:click={() => (showFullStats = !showFullStats)}
|
||||
class="{signalList?.length < 4
|
||||
? 'hidden'
|
||||
: ''} cursor-pointer m-auto flex justify-center items-center mt-5"
|
||||
>
|
||||
<svg
|
||||
class="w-10 h-10 transform {showFullStats ? 'rotate-180' : ''} "
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#2A323C"
|
||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 13.5L7.5 11l1.42-1.41L12 12.67l3.08-3.08L16.5 11L12 15.5z"
|
||||
/></svg
|
||||
>
|
||||
</label>
|
||||
<!--End Momentum Indicators-->
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</section>
|
||||
@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { screenWidth } from "$lib/store";
|
||||
import { abbreviateNumberWithColor, sectorNavigation } from "$lib/utils";
|
||||
|
||||
import VirtualList from "svelte-tiny-virtual-list";
|
||||
import HoverStockChart from "$lib/components/HoverStockChart.svelte";
|
||||
|
||||
@ -12,19 +11,15 @@
|
||||
|
||||
function formatToNewYorkTime(isoString) {
|
||||
const date = new Date(isoString);
|
||||
|
||||
// Get the date components in New York time zone
|
||||
const options = {
|
||||
year: "2-digit", // Shortened year
|
||||
year: "2-digit",
|
||||
month: "numeric",
|
||||
day: "2-digit", // Ensures day has two digits
|
||||
day: "2-digit",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
timeZone: "America/New_York",
|
||||
hour12: true, // Enable AM/PM format
|
||||
hour12: true,
|
||||
};
|
||||
|
||||
// Format date for New York timezone
|
||||
const formatter = new Intl.DateTimeFormat("en-US", options);
|
||||
const parts = formatter.formatToParts(date);
|
||||
|
||||
@ -35,7 +30,7 @@
|
||||
const minute = parts
|
||||
.find((p) => p.type === "minute")
|
||||
.value.padStart(2, "0");
|
||||
const ampm = parts.find((p) => p.type === "dayPeriod").value; // AM/PM
|
||||
const ampm = parts.find((p) => p.type === "dayPeriod").value;
|
||||
|
||||
return `${month}/${day}/${year} ${hour}:${minute} ${ampm}`;
|
||||
}
|
||||
@ -53,16 +48,11 @@
|
||||
sector: "none",
|
||||
};
|
||||
|
||||
// Generalized sorting function
|
||||
function sortData(key) {
|
||||
// Reset all other keys to 'none' except the current key
|
||||
for (const k in sortOrders) {
|
||||
if (k !== key) {
|
||||
sortOrders[k] = "none";
|
||||
}
|
||||
if (k !== key) sortOrders[k] = "none";
|
||||
}
|
||||
|
||||
// Cycle through 'none', 'asc', 'desc' for the clicked key
|
||||
const orderCycle = ["none", "asc", "desc"];
|
||||
const currentOrderIndex = orderCycle.indexOf(sortOrders[key]);
|
||||
sortOrders[key] = orderCycle[(currentOrderIndex + 1) % orderCycle.length];
|
||||
@ -70,8 +60,6 @@
|
||||
const sortOrder = sortOrders[key];
|
||||
const originalData =
|
||||
filteredData?.length !== 0 ? [...filteredData] : [...rawData];
|
||||
|
||||
// Reset to original data when 'none'
|
||||
if (sortOrder === "none") {
|
||||
displayedData = originalData;
|
||||
return;
|
||||
@ -86,56 +74,42 @@
|
||||
: tickerB.localeCompare(tickerA);
|
||||
},
|
||||
sector: (a, b) => {
|
||||
const sectorA = a.sector || ""; // Default to empty string if undefined
|
||||
const sectorB = b.sector || ""; // Default to empty string if undefined
|
||||
|
||||
// Check if either sector is an empty string and ensure it's placed at the bottom
|
||||
if (sectorA === "" && sectorB !== "") return 1; // Move empty string to the bottom
|
||||
if (sectorB === "" && sectorA !== "") return -1; // Move empty string to the bottom
|
||||
|
||||
// If both are non-empty, sort normally
|
||||
const stringA = sectorA.toUpperCase();
|
||||
const stringB = sectorB.toUpperCase();
|
||||
|
||||
const sectorA = a.sector || "";
|
||||
const sectorB = b.sector || "";
|
||||
if (sectorA === "" && sectorB !== "") return 1;
|
||||
if (sectorB === "" && sectorA !== "") return -1;
|
||||
return sortOrder === "asc"
|
||||
? stringA.localeCompare(stringB)
|
||||
: stringB.localeCompare(stringA);
|
||||
},
|
||||
date: (a, b) => {
|
||||
const timeA = new Date(a.date);
|
||||
const timeB = new Date(b.date);
|
||||
return sortOrder === "asc" ? timeA - timeB : timeB - timeA;
|
||||
},
|
||||
price: (a, b) => {
|
||||
const priceA = parseFloat(a.price);
|
||||
const priceB = parseFloat(b.price);
|
||||
return sortOrder === "asc" ? priceA - priceB : priceB - priceA;
|
||||
},
|
||||
premium: (a, b) => {
|
||||
const premiumA = parseFloat(a.premium);
|
||||
const premiumB = parseFloat(b.premium);
|
||||
return sortOrder === "asc" ? premiumA - premiumB : premiumB - premiumA;
|
||||
},
|
||||
size: (a, b) => {
|
||||
const volA = parseFloat(a?.size);
|
||||
const volB = parseFloat(b?.size);
|
||||
return sortOrder === "asc" ? volA - volB : volB - volA;
|
||||
},
|
||||
volume: (a, b) => {
|
||||
const volA = parseFloat(a.volume);
|
||||
const volB = parseFloat(b.volume);
|
||||
return sortOrder === "asc" ? volA - volB : volB - volA;
|
||||
},
|
||||
sizeVolRatio: (a, b) => {
|
||||
const volA = parseFloat(a.sizeVolRatio);
|
||||
const volB = parseFloat(b.sizeVolRatio);
|
||||
return sortOrder === "asc" ? volA - volB : volB - volA;
|
||||
},
|
||||
sizeAvgVolRatio: (a, b) => {
|
||||
const volA = parseFloat(a.sizeAvgVolRatio);
|
||||
const volB = parseFloat(b.sizeAvgVolRatio);
|
||||
return sortOrder === "asc" ? volA - volB : volB - volA;
|
||||
? sectorA.toUpperCase().localeCompare(sectorB.toUpperCase())
|
||||
: sectorB.toUpperCase().localeCompare(sectorA.toUpperCase());
|
||||
},
|
||||
date: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? new Date(a.date) - new Date(b.date)
|
||||
: new Date(b.date) - new Date(a.date),
|
||||
price: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a.price) - parseFloat(b.price)
|
||||
: parseFloat(b.price) - parseFloat(a.price),
|
||||
premium: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a.premium) - parseFloat(b.premium)
|
||||
: parseFloat(b.premium) - parseFloat(a.premium),
|
||||
size: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a?.size) - parseFloat(b?.size)
|
||||
: parseFloat(b?.size) - parseFloat(a?.size),
|
||||
volume: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a.volume) - parseFloat(b.volume)
|
||||
: parseFloat(b.volume) - parseFloat(a.volume),
|
||||
sizeVolRatio: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a.sizeVolRatio) - parseFloat(b.sizeVolRatio)
|
||||
: parseFloat(b.sizeVolRatio) - parseFloat(a.sizeVolRatio),
|
||||
sizeAvgVolRatio: (a, b) =>
|
||||
sortOrder === "asc"
|
||||
? parseFloat(a.sizeAvgVolRatio) - parseFloat(b.sizeAvgVolRatio)
|
||||
: parseFloat(b.sizeAvgVolRatio) - parseFloat(a.sizeAvgVolRatio),
|
||||
assetType: (a, b) => {
|
||||
const typeOrder = { STOCK: 1, ETF: 2 };
|
||||
const typeA = typeOrder[a.assetType?.toUpperCase()] || 3;
|
||||
@ -144,13 +118,220 @@
|
||||
},
|
||||
};
|
||||
|
||||
// Sort using the appropriate comparison function
|
||||
displayedData = originalData.sort(compareFunctions[key]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="table-container">
|
||||
<div class="table">
|
||||
<!-- Container with horizontal scrolling -->
|
||||
<div class="w-full overflow-x-auto">
|
||||
<!-- Set a min-width on smaller screens so the grid can show all columns -->
|
||||
<div class="min-w-[1000px]">
|
||||
<!-- Header row using grid -->
|
||||
<div
|
||||
class="grid grid-cols-10 sticky top-0 z-40 border border-gray-800 bg-default text-white font-bold text-xs uppercase"
|
||||
>
|
||||
<div
|
||||
on:click={() => sortData("date")}
|
||||
class="cursor-pointer p-2 text-center"
|
||||
>
|
||||
Date
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("ticker")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
Symbol
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['ticker'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['ticker'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("price")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
Price
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['price'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['price'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("premium")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
Premium
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['premium'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['premium'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("size")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
Size
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['size'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['size'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("volume")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
Volume
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['volume'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['volume'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sizeVolRatio")}
|
||||
class="cursor-pointer p-2 text-center select-none"
|
||||
>
|
||||
% Size / Vol
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['sizeVolRatio'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['sizeVolRatio'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sizeAvgVolRatio")}
|
||||
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
|
||||
>
|
||||
% Size / Avg Vol
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['sizeAvgVolRatio'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['sizeAvgVolRatio'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sector")}
|
||||
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
|
||||
>
|
||||
Sector
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['sector'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['sector'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("assetType")}
|
||||
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
|
||||
>
|
||||
Asset type
|
||||
<svg
|
||||
class="shrink-0 w-4 h-4 -mt-1 {sortOrders['assetType'] === 'asc'
|
||||
? 'rotate-180 inline-block'
|
||||
: sortOrders['assetType'] === 'desc'
|
||||
? 'inline-block'
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VirtualList renders rows in a grid -->
|
||||
<VirtualList
|
||||
width="100%"
|
||||
height={$screenWidth < 640
|
||||
@ -163,414 +344,91 @@
|
||||
itemCount={displayedData.length}
|
||||
itemSize={40}
|
||||
>
|
||||
<div
|
||||
slot="header"
|
||||
class="tr th m-auto sticky z-40 top-0 border border-gray-800"
|
||||
>
|
||||
<!-- Table headers -->
|
||||
<div
|
||||
on:click={() => sortData("date")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Date
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['date'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: ''} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("ticker")}
|
||||
class="td cursor-pointer select-none bg-default font-bold text-white text-xs text-start uppercase"
|
||||
>
|
||||
Symbol
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['ticker'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['ticker'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("price")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Price
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['price'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['price'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("premium")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Premium
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['premium'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['premium'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("size")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Size
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['size'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['size'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
on:click={() => sortData("volume")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Volume
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['volume'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['volume'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sizeVolRatio")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
% Size / Vol
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
|
||||
'sizeVolRatio'
|
||||
] === 'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['sizeVolRatio'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sizeAvgVolRatio")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
% Size / Avg Vol
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
|
||||
'sizeAvgVolRatio'
|
||||
] === 'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['sizeAvgVolRatio'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("sector")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Sector
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['sector'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['sector'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
on:click={() => sortData("assetType")}
|
||||
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
|
||||
>
|
||||
Asset Type
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
|
||||
'assetType'
|
||||
] === 'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['assetType'] === 'desc'
|
||||
? ''
|
||||
: 'hidden'} "
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:50px"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
slot="item"
|
||||
let:index
|
||||
let:style
|
||||
{style}
|
||||
class="tr {index % 2 === 0 ? 'bg-[#19191F]' : 'bg-[#121217]'} {index +
|
||||
1 ===
|
||||
rawData?.length && data?.user?.tier !== 'Pro'
|
||||
? 'opacity-[0.3]'
|
||||
: ''}"
|
||||
class="grid grid-cols-10 gap-0"
|
||||
class:bg-[#19191F]={index % 2 === 0}
|
||||
class:bg-[#121217]={index % 2 !== 0}
|
||||
class:opacity-30={index + 1 === rawData?.length &&
|
||||
data?.user?.tier !== "Pro"}
|
||||
>
|
||||
<!-- Row data -->
|
||||
|
||||
<!-- Date Column -->
|
||||
<div
|
||||
style="justify-content: center; "
|
||||
class=" td w-full text-white text-xs sm:text-sm whitespace-nowrap m-auto"
|
||||
class="p-2 text-center text-white text-xs sm:text-sm whitespace-nowrap"
|
||||
>
|
||||
{$screenWidth < 640
|
||||
? formatToNewYorkTime(displayedData[index]?.date)?.slice(0, -3)
|
||||
: formatToNewYorkTime(displayedData[index]?.date)}
|
||||
</div>
|
||||
<div
|
||||
on:click|stopPropagation
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:hover:text-white sm:text-[1rem] text-blue-400 font-normal"
|
||||
>
|
||||
<!-- Symbol Column -->
|
||||
<div class="p-2 text-center text-sm sm:text-[1rem]">
|
||||
<HoverStockChart
|
||||
symbol={displayedData[index]?.ticker}
|
||||
assetType={displayedData[index]?.assetType}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-start text-white"
|
||||
>
|
||||
<!-- Price Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{displayedData[index]?.price}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-start text-white"
|
||||
>
|
||||
<!-- Premium Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{@html abbreviateNumberWithColor(
|
||||
displayedData[index]?.premium,
|
||||
true,
|
||||
true,
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-end"
|
||||
>
|
||||
<!-- Size Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{new Intl.NumberFormat("en", {
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
}).format(displayedData[index]?.size)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-end"
|
||||
>
|
||||
<!-- Volume Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{@html abbreviateNumberWithColor(
|
||||
displayedData[index]?.volume,
|
||||
false,
|
||||
true,
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-end"
|
||||
>
|
||||
<!-- % Size / Vol Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{displayedData[index]?.sizeVolRatio > 0.01
|
||||
? displayedData[index]?.sizeVolRatio?.toFixed(2) + "%"
|
||||
: "< 0.01%"}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-end"
|
||||
>
|
||||
<!-- % Size / Avg Vol Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{displayedData[index]?.sizeAvgVolRatio > 0.01
|
||||
? displayedData[index]?.sizeAvgVolRatio?.toFixed(2) + "%"
|
||||
: "< 0.01%"}
|
||||
</div>
|
||||
|
||||
<!-- Sector Column -->
|
||||
<div
|
||||
style="justify-content: start;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-start"
|
||||
class="p-2 text-left text-white text-sm sm:text-[1rem] whitespace-nowrap"
|
||||
>
|
||||
<a
|
||||
href={sectorNavigation?.find(
|
||||
(item) => item?.title === displayedData[index]?.sector,
|
||||
)?.link}
|
||||
class="sm:hover:text-blue-400 text-white"
|
||||
>{displayedData[index]?.sector?.length > 13
|
||||
? displayedData[index]?.sector?.slice(0, 13) + "..."
|
||||
: displayedData[index]?.sector}</a
|
||||
class="hover:text-blue-400"
|
||||
>
|
||||
{displayedData[index]?.sector?.length > 13
|
||||
? displayedData[index]?.sector?.slice(0, 13) + "..."
|
||||
: displayedData[index]?.sector}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="justify-content: center;"
|
||||
class="td text-sm sm:text-[1rem] text-white text-end"
|
||||
>
|
||||
<!-- Asset Type Column -->
|
||||
<div class="p-2 text-center text-white text-sm sm:text-[1rem]">
|
||||
{displayedData[index]?.assetType}
|
||||
</div>
|
||||
</div>
|
||||
</VirtualList>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.table-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.table :global(.virtual-list-inner) {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.table {
|
||||
width: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
.table .virtual-list-inner {
|
||||
flex-flow: column nowrap;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.5;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.th {
|
||||
display: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.th > .td {
|
||||
white-space: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tr {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
|
||||
.tr.even {
|
||||
background-color: #2a2e39;
|
||||
}
|
||||
|
||||
.tr.odd {
|
||||
background-color: #09090b;
|
||||
}
|
||||
|
||||
.td {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
padding: 0.5em;
|
||||
word-break: break-word;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -256,7 +256,7 @@
|
||||
>
|
||||
Time
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['time'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['time'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: ''} "
|
||||
@ -276,7 +276,7 @@
|
||||
>
|
||||
Symbol
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['ticker'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['ticker'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['ticker'] === 'desc'
|
||||
@ -303,7 +303,7 @@
|
||||
>
|
||||
Expiry
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['expiry'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['expiry'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['expiry'] === 'desc'
|
||||
@ -325,7 +325,7 @@
|
||||
>
|
||||
DTE
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['dte'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['dte'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['dte'] === 'desc'
|
||||
@ -347,7 +347,7 @@
|
||||
>
|
||||
Strike
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['strike'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['strike'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['strike'] === 'desc'
|
||||
@ -369,7 +369,7 @@
|
||||
>
|
||||
C/P
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['callPut'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['callPut'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['callPut'] === 'desc'
|
||||
@ -391,7 +391,7 @@
|
||||
>
|
||||
Sent.
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders[
|
||||
'sentiment'
|
||||
] === 'asc'
|
||||
? 'rotate-180'
|
||||
@ -414,7 +414,7 @@
|
||||
>
|
||||
Spot
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['spot'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['spot'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['spot'] === 'desc'
|
||||
@ -436,7 +436,7 @@
|
||||
>
|
||||
Price
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['price'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['price'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['price'] === 'desc'
|
||||
@ -458,7 +458,7 @@
|
||||
>
|
||||
Prem
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['premium'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['premium'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['premium'] === 'desc'
|
||||
@ -480,7 +480,7 @@
|
||||
>
|
||||
Type
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['type'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['type'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['type'] === 'desc'
|
||||
@ -502,7 +502,7 @@
|
||||
>
|
||||
Exec
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['exec'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['exec'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['exec'] === 'desc'
|
||||
@ -524,7 +524,7 @@
|
||||
>
|
||||
Size
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['size'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['size'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['size'] === 'desc'
|
||||
@ -546,7 +546,7 @@
|
||||
>
|
||||
Vol
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['vol'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['vol'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['vol'] === 'desc'
|
||||
@ -568,7 +568,7 @@
|
||||
>
|
||||
OI
|
||||
<svg
|
||||
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['oi'] ===
|
||||
class="shrink-0 w-4 h-4 inline-block {sortOrders['oi'] ===
|
||||
'asc'
|
||||
? 'rotate-180'
|
||||
: sortOrders['oi'] === 'desc'
|
||||
@ -630,7 +630,7 @@
|
||||
<svg
|
||||
class="{displayedData[index]?.id === animationId
|
||||
? animationClass
|
||||
: ''} w-4 sm:w-5 sm:h-5 inline-block cursor-pointer flex-shrink-0"
|
||||
: ''} w-4 sm:w-5 sm:h-5 inline-block cursor-pointer shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
><path
|
||||
@ -827,7 +827,7 @@
|
||||
.td {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
flex-grow: 1;
|
||||
grow: 1;
|
||||
flex-basis: 0;
|
||||
padding: 0.5em;
|
||||
word-break: break-word;
|
||||
|
||||
@ -858,7 +858,7 @@
|
||||
<tbody>
|
||||
{#each stockList as item, index}
|
||||
<tr
|
||||
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-odd border-b border-gray-800 {index +
|
||||
class="sm:hover:bg-[#245073]/10 odd:bg-odd border-b border-gray-800 {index +
|
||||
1 ===
|
||||
rawData?.length &&
|
||||
data?.user?.tier !== 'Pro' &&
|
||||
@ -868,7 +868,7 @@
|
||||
>
|
||||
{#each columns as column}
|
||||
<td
|
||||
class="text-sm sm:text-[1rem] whitespace-nowrap"
|
||||
class="text-sm sm:text-[1rem] whitespace-nowrap border-b border-gray-800"
|
||||
class:text-left={column.align === "left"}
|
||||
class:text-right={column.align === "right"}
|
||||
>
|
||||
|
||||
@ -4,8 +4,12 @@
|
||||
export let sortData;
|
||||
|
||||
const SortIcon = ({ sortOrder }) => `
|
||||
<svg class="flex-shrink-0 w-4 h-4 inline-block ${
|
||||
sortOrder === "asc" ? "rotate-180" : sortOrder === "desc" ? "" : "hidden"
|
||||
<svg class="shrink-0 w-4 h-4 ${
|
||||
sortOrder === "asc"
|
||||
? "rotate-180 inline-block"
|
||||
: sortOrder === "desc"
|
||||
? "inline-block"
|
||||
: "hidden"
|
||||
}" viewBox="0 0 20 20" fill="currentColor" style="max-width:50px">
|
||||
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
@ -21,8 +25,8 @@
|
||||
? 'text-end'
|
||||
: 'text-start'}"
|
||||
>
|
||||
{column.label}
|
||||
{@html SortIcon({ sortOrder: sortOrders[column.key].order })}
|
||||
{column?.label}
|
||||
{@html SortIcon({ sortOrder: sortOrders[column.key]?.order })}
|
||||
</th>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
@ -158,7 +158,7 @@
|
||||
target="_blank"
|
||||
class="cursor-pointer mb-10 w-full"
|
||||
>
|
||||
<div class="flex-shrink-0 float-left">
|
||||
<div class="shrink-0 float-left">
|
||||
<img
|
||||
src={item?.image}
|
||||
class="float-left w-36 sm:w-40 rounded-xl ml-2 mr-4 mb-2"
|
||||
@ -173,7 +173,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow">
|
||||
<div class="grow">
|
||||
<div class="text-sm text-white flex flex-row">
|
||||
<div
|
||||
class="rounded-full w-6 h-6 relative bg-gray-800 mr-1.5 mb-0.5"
|
||||
@ -188,7 +188,7 @@
|
||||
ago
|
||||
</div>
|
||||
<h2
|
||||
class="text-start text-sm sm:text-md font-medium mb-2 flex-shrink text-white"
|
||||
class="text-start text-sm sm:text-md font-medium mb-2 shrink text-white"
|
||||
>
|
||||
{item.title}
|
||||
</h2>
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { Accordion as AccordionPrimitive } from "bits-ui";
|
||||
import ChevronDown from "lucide-svelte/icons/chevron-down";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Accordion as AccordionPrimitive } from "bits-ui";
|
||||
import ChevronDown from "lucide-svelte/icons/chevron-down";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = AccordionPrimitive.TriggerProps;
|
||||
type $$Events = AccordionPrimitive.TriggerEvents;
|
||||
type $$Props = AccordionPrimitive.TriggerProps;
|
||||
type $$Events = AccordionPrimitive.TriggerEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let level: AccordionPrimitive.HeaderProps["level"] = 3;
|
||||
export { className as class };
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let level: AccordionPrimitive.HeaderProps["level"] = 3;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AccordionPrimitive.Header {level} class="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
class={cn(
|
||||
"flex flex-1 items-center justify-between font-medium transition-all [&[data-state=open]>svg1]:rotate-180",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
>
|
||||
<slot />
|
||||
<ChevronDown class="text-white h-4 w-4 sm:absolute sm:right-5 flex-shrink-0 transition-transform duration-200" />
|
||||
</AccordionPrimitive.Trigger>
|
||||
<AccordionPrimitive.Trigger
|
||||
class={cn(
|
||||
"cursor-pointer flex flex-1 items-center justify-between font-medium transition-all [&[data-state=open]>svg1]:rotate-180",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
>
|
||||
<slot />
|
||||
<ChevronDown
|
||||
class="text-white h-4 w-4 sm:absolute sm:right-5 shrink-0 transition-transform duration-200"
|
||||
/>
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
@ -2,7 +2,7 @@ import { type VariantProps, tv } from "tailwind-variants";
|
||||
export { default as Badge } from "./badge.svelte";
|
||||
|
||||
export const badgeVariants = tv({
|
||||
base: "inline-flex select-none items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
base: "inline-flex select-none items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
<script lang="ts">
|
||||
import { Button as ButtonPrimitive } from "bits-ui";
|
||||
import { type Events, type Props, buttonVariants } from "./index.ts";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Button as ButtonPrimitive } from "bits-ui";
|
||||
import { type Events, type Props, buttonVariants } from "./index.ts";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = Props;
|
||||
type $$Events = Events;
|
||||
type $$Props = Props;
|
||||
type $$Events = Events;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let variant: $$Props["variant"] = "default";
|
||||
export let size: $$Props["size"] = "default";
|
||||
export let builders: $$Props["builders"] = [];
|
||||
export { className as class };
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let variant: $$Props["variant"] = "default";
|
||||
export let size: $$Props["size"] = "default";
|
||||
export let builders: $$Props["builders"] = [];
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ButtonPrimitive.Root
|
||||
{builders}
|
||||
class={cn(buttonVariants({ variant, size, className }))}
|
||||
type="button"
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
{builders}
|
||||
class={cn(buttonVariants({ variant, size, className }))}
|
||||
type="button"
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
>
|
||||
<slot />
|
||||
<slot />
|
||||
</ButtonPrimitive.Root>
|
||||
@ -3,7 +3,7 @@ import type { Button as ButtonPrimitive } from "bits-ui";
|
||||
import Root from "./button.svelte";
|
||||
|
||||
const buttonVariants = tv({
|
||||
base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
base: "cursor-pointer inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground",
|
||||
|
||||
@ -21,13 +21,13 @@
|
||||
"h-9 w-9 p-0 font-normal ",
|
||||
"[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground",
|
||||
// Selected
|
||||
"data-[selected]:bg-[#262626] data-[selected]:text-white data-[selected]:hover:bg-[#262626] data-[selected]:hover:text-white data-[selected]:focus:bg-[#262626] data-[selected]:focus:text-white data-[selected]:opacity-100",
|
||||
"data-selected:bg-[#262626] data-selected:text-white data-selected:hover:bg-[#262626] data-selected:hover:text-white data-selected:focus:bg-[#262626] data-selected:focus:text-white data-selected:opacity-100",
|
||||
// Disabled
|
||||
"data-[disabled]:text-muted-foreground data-[disabled]:opacity-50",
|
||||
"data-disabled:text-muted-foreground data-disabled:opacity-50",
|
||||
// Unavailable
|
||||
"data-[unavailable]:text-destructive-foreground data-[unavailable]:line-through",
|
||||
"data-unavailable:text-destructive-foreground data-unavailable:line-through",
|
||||
// Outside months
|
||||
"data-[outside-month]:text-muted-foreground [&[data-outside-month][data-selected]]:bg-accent/50 [&[data-outside-month][data-selected]]:text-muted-foreground data-[outside-month]:pointer-events-none data-[outside-month]:opacity-50 [&[data-outside-month][data-selected]]:opacity-30",
|
||||
"data-outside-month:text-muted-foreground [&[data-outside-month][data-selected]]:bg-accent/50 [&[data-outside-month][data-selected]]:text-muted-foreground data-outside-month:pointer-events-none data-outside-month:opacity-50 [&[data-outside-month][data-selected]]:opacity-30",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
<div
|
||||
class={cn(
|
||||
"rounded-md border border-gray-800 bg-default text-white shadow-sm",
|
||||
"rounded-md border border-gray-800 bg-default text-white shadow-xs",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<Dialog.Root bind:open {...$$restProps}>
|
||||
<Dialog.Content class="overflow-hidden p-0 shadow-lg">
|
||||
<Command
|
||||
class="[&_[data-cmdk-group-heading]]:text-muted-foreground [&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:font-medium [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 [&_[data-cmdk-group]]:px-2 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 [&_[data-cmdk-input]]:h-12 [&_[data-cmdk-item]]:px-2 [&_[data-cmdk-item]]:py-3 [&_[data-cmdk-item]_svg]:h-5 [&_[data-cmdk-item]_svg]:w-5"
|
||||
class="**:data-cmdk-group-heading:text-muted-foreground **:data-cmdk-group-heading:px-2 **:data-cmdk-group-heading:font-medium [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 **:data-cmdk-group:px-2 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 **:data-cmdk-input:h-12 **:data-cmdk-item:px-2 **:data-cmdk-item:py-3 [&_[data-cmdk-item]_svg]:h-5 [&_[data-cmdk-item]_svg]:w-5"
|
||||
{...$$restProps}
|
||||
bind:value
|
||||
>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<CommandPrimitive.Group
|
||||
class={cn(
|
||||
"text-foreground [&_[data-cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:py-1.5 [&_[data-cmdk-group-heading]]:text-xs [&_[data-cmdk-group-heading]]:font-medium",
|
||||
"text-foreground **:data-cmdk-group-heading:text-muted-foreground overflow-hidden p-1 **:data-cmdk-group-heading:px-2 **:data-cmdk-group-heading:py-1.5 **:data-cmdk-group-heading:text-xs **:data-cmdk-group-heading:font-medium",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
<CommandPrimitive.Input
|
||||
class={cn(
|
||||
"placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<CommandPrimitive.Item
|
||||
{asChild}
|
||||
class={cn(
|
||||
"text-white sm:hover:bg-primary sm:hover:text-white aria-selected:bg-primary aria-selected:text-white relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"text-white sm:hover:bg-primary sm:hover:text-white aria-selected:bg-primary aria-selected:text-white relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
>
|
||||
<slot />
|
||||
<DialogPrimitive.Close
|
||||
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none"
|
||||
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none"
|
||||
>
|
||||
<X class="h-4 w-4" />
|
||||
<span class="sr-only">Close</span>
|
||||
|
||||
@ -16,6 +16,6 @@
|
||||
<DialogPrimitive.Overlay
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn("bg-background/80 fixed inset-0 z-50 backdrop-blur-sm", className)}
|
||||
class={cn("bg-background/80 fixed inset-0 z-50 backdrop-blur-xs", className)}
|
||||
{...$$restProps}
|
||||
/>
|
||||
@ -14,7 +14,7 @@
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
bind:checked
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
{transitionConfig}
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
"z-50 min-w-[8rem] no-scrollbar rounded-md border border-gray-500 bg-default p-1 text-white shadow-md focus:outline-none",
|
||||
"z-50 min-w-[8rem] no-scrollbar rounded-md border border-gray-500 bg-default p-1 text-white shadow-md focus:outline-hidden",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
<DropdownMenuPrimitive.Item
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none ",
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-disabled:pointer-events-none ",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{value}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn(
|
||||
"z-50 min-w-[8rem] rounded-md border bg-default p-1 text-white shadow-lg focus:outline-none",
|
||||
"z-50 min-w-[8rem] rounded-md border bg-default p-1 text-white shadow-lg focus:outline-hidden",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
class={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground",
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-highlighted:bg-accent data-[state=open]:bg-accent data-highlighted:text-accent-foreground data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
{sideOffset}
|
||||
{align}
|
||||
class={cn(
|
||||
"bg-popover text-popover-foreground z-50 w-64 rounded-md border p-4 shadow-md outline-none",
|
||||
"bg-popover text-popover-foreground z-50 w-64 rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn(
|
||||
"bg-popover text-popover-foreground z-50 w-72 rounded-md border p-4 shadow-md outline-none",
|
||||
"bg-popover text-popover-foreground z-50 w-72 rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
{outTransitionConfig}
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
"bg-default text-white relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-gray-800 shadow-md outline-none",
|
||||
"bg-default text-white relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-gray-800 shadow-md outline-hidden",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
{disabled}
|
||||
{label}
|
||||
class={cn(
|
||||
"data-[highlighted]:bg-primary data-[highlighted]:text-white relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"data-highlighted:bg-primary data-highlighted:text-white relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
<SelectPrimitive.Trigger
|
||||
class={cn(
|
||||
"border-input bg-default ring-offset-background focus-visible:ring-ring aria-[invalid]:border-destructive data-[placeholder]:[&>span]:text-white flex h-10 w-full items-center justify-between rounded-md border border-gray-800 px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||
"border-input bg-default ring-offset-background focus-visible:ring-ring aria-[invalid]:border-destructive [&>span]:data-placeholder:text-white flex h-10 w-full items-center justify-between rounded-md border border-gray-800 px-3 py-2 text-sm focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||
className,
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<slot />
|
||||
<SheetPrimitive.Close
|
||||
id="close-sheet"
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none "
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none "
|
||||
>
|
||||
<X class="h-4 w-4" />
|
||||
<span class="sr-only">Close</span>
|
||||
|
||||
@ -16,6 +16,6 @@
|
||||
<SheetPrimitive.Overlay
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn("fixed inset-0 z-50 bg-default/80 backdrop-blur-sm ", className)}
|
||||
class={cn("fixed inset-0 z-50 bg-default/80 backdrop-blur-xs ", className)}
|
||||
{...$$restProps}
|
||||
/>
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<SwitchPrimitive.Root
|
||||
bind:checked
|
||||
class={cn(
|
||||
"focus-visible:ring-ring border border-gray-500 focus-visible:ring-offset-background data-[state=checked]:bg-purple-500 data-[state=unchecked]:bg-[#1D232A] peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"focus-visible:ring-ring border border-gray-500 focus-visible:ring-offset-background data-[state=checked]:bg-purple-500 data-[state=unchecked]:bg-[#1D232A] peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
<TabsPrimitive.Content
|
||||
class={cn(
|
||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
"mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
className
|
||||
)}
|
||||
{value}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
<TabsPrimitive.Trigger
|
||||
class={cn(
|
||||
" inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-2 text-[1rem] font-semibold ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[#fff] data-[state=active]:text-black data-[state=active]:shadow-sm",
|
||||
" inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-2 text-[1rem] font-semibold ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[#fff] data-[state=active]:text-black data-[state=active]:shadow-xs",
|
||||
className,
|
||||
)}
|
||||
{value}
|
||||
|
||||
@ -789,7 +789,7 @@
|
||||
</Sheet.Content>
|
||||
</Sheet.Root>
|
||||
|
||||
<a href="/" class="-ml-2 flex flex-shrink-0">
|
||||
<a href="/" class="-ml-2 flex shrink-0">
|
||||
<img
|
||||
class="avatar w-9 3xl:w-10 rounded-full"
|
||||
src={stocknear_logo}
|
||||
@ -871,7 +871,7 @@
|
||||
{:else}
|
||||
<a
|
||||
href="/login"
|
||||
class="inline-flex items-center justify-center rounded bg-[#fff] px-4 py-2 text-sm font-semibold text-black shadow-sm transition-all duration-150 sm:hover:bg-gray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-purple-600"
|
||||
class="inline-flex items-center justify-center rounded bg-[#fff] px-4 py-2 text-sm font-semibold text-black shadow-xs transition-all duration-150 sm:hover:bg-gray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-purple-600"
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
class="aspect-577/310 w-[36.0625rem] bg-linear-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
style="clip-path: polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
></div>
|
||||
</div>
|
||||
@ -89,7 +89,7 @@
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="aspect-[577/310] w-[36.0625rem] bg-gradient-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
class="aspect-577/310 w-[36.0625rem] bg-linear-to-r from-[#ff80b5] to-[#9089fc] opacity-30"
|
||||
style="clip-path: polygon(74.8% 41.9%, 97.2% 73.2%, 100% 34.9%, 92.5% 0.4%, 87.5% 0%, 75% 28.6%, 58.5% 54.6%, 50.1% 56.8%, 46.9% 44%, 48.3% 17.4%, 24.7% 53.9%, 0% 27.9%, 11.9% 74.2%, 24.9% 54.1%, 68.6% 100%, 74.8% 41.9%)"
|
||||
></div>
|
||||
</div>
|
||||
@ -109,7 +109,7 @@
|
||||
|
||||
<a
|
||||
href="/pricing"
|
||||
class="flex-none rounded-full m-auto sm:m-0 px-3.5 py-1 text-[1rem] font-semibold text-black shadow-sm sm:hover:bg-gray-100 bg-[#fff] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900"
|
||||
class="flex-none rounded-full m-auto sm:m-0 px-3.5 py-1 text-[1rem] font-semibold text-black shadow-xs sm:hover:bg-gray-100 bg-[#fff] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900"
|
||||
>
|
||||
Get Lifetime
|
||||
</a>
|
||||
|
||||
@ -99,7 +99,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Sponsor Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn more about why we're doing this here
|
||||
@ -118,7 +118,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Contact Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Let me know if you need something
|
||||
|
||||
@ -464,7 +464,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Stocks Picks
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings.
|
||||
@ -483,7 +483,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Shorted Stocks
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Never miss out another short squeeze
|
||||
|
||||
@ -198,7 +198,7 @@
|
||||
<div
|
||||
class="flex space-x-3 border-b-[2px] border-below-title pb-3 lg:border-none lg:pb-0"
|
||||
>
|
||||
<div class="flex-shrink-0">
|
||||
<div class="shrink-0">
|
||||
<svg
|
||||
class="h-16 w-16 sm:h-20 sm:w-20 text-gray-200"
|
||||
fill="currentColor"
|
||||
@ -410,13 +410,13 @@
|
||||
{#if index >= 5 && data?.user?.tier !== "Pro"}
|
||||
<a class="block relative" href="/pricing">
|
||||
<span
|
||||
class="text-base font-semibold text-blue-link blur group-hover:blur-[6px]"
|
||||
class="text-base font-semibold text-blue-link blur-sm group-hover:blur-[6px]"
|
||||
>
|
||||
XXXX
|
||||
</span>
|
||||
|
||||
<div
|
||||
class="ml-px max-w-[130px] truncate text-sm text-white blur group-hover:blur-[6px] lg:max-w-[150px]"
|
||||
class="ml-px max-w-[130px] truncate text-sm text-white blur-sm group-hover:blur-[6px] lg:max-w-[150px]"
|
||||
>
|
||||
XXXXXXXXXXXXXXXX
|
||||
</div>
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
<div
|
||||
class="flex flex-col overflow-hidden rounded border border-gray-700"
|
||||
>
|
||||
<div class="flex-shrink-0">
|
||||
<div class="shrink-0">
|
||||
<a href={"/blog/article/" + convertToSlug(item?.title)}
|
||||
><img
|
||||
class="h-48 w-full object-cover"
|
||||
|
||||
@ -40,10 +40,10 @@
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 translate-z-0 bg-gradient-to-r from-[#E8BB28] to-purple-600 rounded-full blur-[120px] opacity-20"
|
||||
class="absolute inset-0 translate-z-0 bg-linear-to-r from-[#E8BB28] to-purple-600 rounded-full blur-[120px] opacity-20"
|
||||
></div>
|
||||
<div
|
||||
class="absolute w-32 h-32 translate-z-0 bg-gradient-to-r from-[#E8BB28] to-purple-700 rounded-full blur-[80px] opacity-40"
|
||||
class="absolute w-32 h-32 translate-z-0 bg-linear-to-r from-[#E8BB28] to-purple-700 rounded-full blur-[80px] opacity-40"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
<!-- Page header -->
|
||||
<div class="text-center pb-12 md:pb-20">
|
||||
<h1
|
||||
class="text-4xl sm:text-6xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-[#E8BB28] to-purple-500 via-slate-200 to-slate-200/60 pb-4"
|
||||
class="text-4xl sm:text-6xl font-bold bg-clip-text text-transparent bg-linear-to-r from-[#E8BB28] to-purple-500 via-slate-200 to-slate-200/60 pb-4"
|
||||
>
|
||||
What's New
|
||||
</h1>
|
||||
@ -72,7 +72,7 @@
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<div class="relative">
|
||||
<div
|
||||
class="absolute h-full top-4 left-[2px] w-0.5 bg-slate-800 [mask-image:_linear-gradient(0deg,transparent,theme(colors.white)_150px,theme(colors.white))] -z-10 overflow-hidden after:absolute after:h-4 after:top-0 after:-translate-y-full after:left-0 after:w-0.5 after:bg-[linear-gradient(180deg,_transparent,_theme(colors.purple.500/.65)_25%,_theme(colors.purple.200)_50%,_theme(colors.purple.500/.65)_75%,_transparent)] after:animate-shine"
|
||||
class="absolute h-full top-4 left-[2px] w-0.5 bg-slate-800 [mask-image:linear-gradient(0deg,transparent,var(--color-white)_150px,var(--color-white))] -z-10 overflow-hidden after:absolute after:h-4 after:top-0 after:-translate-y-full after:left-0 after:w-0.5 after:bg-[linear-gradient(180deg,transparent,--theme(--color-purple-500/.65)_25%,--theme(--color-purple-200)_50%,--theme(--color-purple-500/.65)_75%,transparent)] after:animate-shine"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
<!-- Post -->
|
||||
@ -89,7 +89,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -124,7 +124,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -160,7 +160,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -211,7 +211,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -252,7 +252,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -285,7 +285,7 @@
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,theme(colors.slate.700/.3),theme(colors.slate.700),theme(colors.slate.700/.3))1] group-last-of-type:border-none"
|
||||
class="grow ml-8 md:ml-0 pb-12 group-last-of-type:pb-0 border-b [border-image:linear-gradient(to_right,--theme(--color-slate-700/.3),--theme(--color-slate-700),--theme(--color-slate-700/.3))1] group-last-of-type:border-none"
|
||||
>
|
||||
<header>
|
||||
<h2
|
||||
@ -310,14 +310,14 @@
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<ul class="flex items-center justify-between mt-12 pl-8 md:pl-48">
|
||||
<li>
|
||||
<span class="btn-sm text-slate-700 transition duration-150 ease-in-out group [background:linear-gradient(theme(colors.slate.900),_theme(colors.slate.900))_padding-box,_conic-gradient(theme(colors.slate.400),_theme(colors.slate.700)_25%,_theme(colors.slate.700)_75%,_theme(colors.slate.400)_100%)_border-box] relative before:absolute before:inset-0 before:bg-slate-800/30 before:rounded-full before:pointer-events-none cursor-not-allowed">
|
||||
<span class="btn-sm text-slate-700 transition duration-150 ease-in-out group [background:linear-gradient(var(--color-slate-900),var(--color-slate-900))_padding-box,conic-gradient(var(--color-slate-400),var(--color-slate-700)_25%,var(--color-slate-700)_75%,var(--color-slate-400)_100%)_border-box] relative before:absolute before:inset-0 before:bg-slate-800/30 before:rounded-full before:pointer-events-none cursor-not-allowed">
|
||||
<span class="relative inline-flex items-center">
|
||||
<span class="tracking-normal text-slate-700 mr-1"><-</span> Previous Page
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn-sm text-slate-300 hover:text-white transition duration-150 ease-in-out group [background:linear-gradient(theme(colors.slate.900),_theme(colors.slate.900))_padding-box,_conic-gradient(theme(colors.slate.400),_theme(colors.slate.700)_25%,_theme(colors.slate.700)_75%,_theme(colors.slate.400)_100%)_border-box] relative before:absolute before:inset-0 before:bg-slate-800/30 before:rounded-full before:pointer-events-none" href="#0">
|
||||
<a class="btn-sm text-slate-300 hover:text-white transition duration-150 ease-in-out group [background:linear-gradient(var(--color-slate-900),var(--color-slate-900))_padding-box,conic-gradient(var(--color-slate-400),var(--color-slate-700)_25%,var(--color-slate-700)_75%,var(--color-slate-400)_100%)_border-box] relative before:absolute before:inset-0 before:bg-slate-800/30 before:rounded-full before:pointer-events-none" href="#0">
|
||||
<span class="relative inline-flex items-center">
|
||||
Next Page <span class="tracking-normal text-purple-500 group-hover:translate-x-0.5 transition-transform duration-150 ease-in-out ml-1">-></span>
|
||||
</span>
|
||||
|
||||
@ -119,7 +119,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Sponsor Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn more about why we're doing this here
|
||||
@ -138,7 +138,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
About Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn the mission of the company and the team
|
||||
|
||||
@ -272,7 +272,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Analyst
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings
|
||||
@ -291,7 +291,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Congress Trading
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Congress trading insights.
|
||||
|
||||
@ -767,13 +767,13 @@
|
||||
</span>
|
||||
|
||||
<label
|
||||
class="inline-flex items-center cursor-pointer focus-none focus:outline-none"
|
||||
class="inline-flex items-center cursor-pointer focus-none focus:outline-hidden"
|
||||
>
|
||||
<input
|
||||
on:click={() =>
|
||||
toast("Feature is coming soon 🔥", {
|
||||
style:
|
||||
"border-radius: 200px; background: #272B37; color: #fff; border: 1px solid #4B5563; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);",
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
})}
|
||||
type="checkbox"
|
||||
checked={mode}
|
||||
@ -782,7 +782,7 @@
|
||||
/>
|
||||
|
||||
<div
|
||||
class="relative w-11 h-6 bg-gray-600 focus:outline-none peer-focus:outline-none peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#00A96E]"
|
||||
class="relative w-11 h-6 bg-gray-600 focus:outline-hidden peer-focus:outline-hidden peer-focus:outline-hidden rounded-full peer peer-checked:after:translate-x-full peer-checked:rtl:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#00A96E]"
|
||||
></div>
|
||||
</label>
|
||||
|
||||
@ -857,7 +857,7 @@
|
||||
on:click={() =>
|
||||
toast("Feature is coming soon 🔥", {
|
||||
style:
|
||||
"border-radius: 200px; background: #272B37; color: #fff; border: 1px solid #4B5563; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);",
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
})}
|
||||
class={cn(
|
||||
"w-full sm:w-[160px] truncate sm:mr-3 py-3 bg-[#000] sm:hover:bg-[#000] sm:hover:text-white text-white justify-center sm:justify-start text-center sm:text-left font-normal border-none rounded-md",
|
||||
@ -904,7 +904,7 @@
|
||||
>
|
||||
<label
|
||||
for="ruleModal"
|
||||
class="inline-flex cursor-pointer items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-sm bg-[#000] sm:hover:bg-default/60 ease-out focus:outline-none focus:ring-2 focus:ring-blue-500 sm:text-smaller"
|
||||
class="inline-flex cursor-pointer items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-xs bg-[#000] sm:hover:bg-default/60 ease-out focus:outline-hidden focus:ring-2 focus:ring-blue-500 sm:text-smaller"
|
||||
>
|
||||
<svg
|
||||
class="h-5 w-5"
|
||||
@ -925,7 +925,7 @@
|
||||
{#if ruleOfList?.length !== 0}
|
||||
<label
|
||||
on:click={handleResetAll}
|
||||
class="sm:ml-3 cursor-pointer inline-flex items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-sm bg-[#000] sm:hover:text-red-500 ease-out focus:outline-none focus:ring-2 focus:ring-blue-500 sm:text-smaller"
|
||||
class="sm:ml-3 cursor-pointer inline-flex items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-xs bg-[#000] sm:hover:text-red-500 ease-out focus:outline-hidden focus:ring-2 focus:ring-blue-500 sm:text-smaller"
|
||||
>
|
||||
<svg
|
||||
class="h-4 w-4"
|
||||
@ -987,7 +987,7 @@
|
||||
<div class="flex items-center">
|
||||
<button
|
||||
on:click={() => handleDeleteRule(row?.rule)}
|
||||
class="mr-1.5 cursor-pointer text-gray-300 sm:hover:text-red-500 focus:outline-none"
|
||||
class="mr-1.5 cursor-pointer text-gray-300 sm:hover:text-red-500 focus:outline-hidden"
|
||||
title="Remove filter"
|
||||
>
|
||||
<svg
|
||||
@ -1073,7 +1073,7 @@
|
||||
?.replace("exactly", "Exactly")}
|
||||
</span>
|
||||
<svg
|
||||
class="mt-1 -mr-1 ml-1 h-5 w-5 xs:ml-2 !ml-0 sm:ml-0 inline-block"
|
||||
class="mt-1 -mr-1 ml-1 h-5 w-5 xs:ml-2 ml-0! sm:ml-0 inline-block"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:40px"
|
||||
@ -1116,7 +1116,7 @@
|
||||
: ""}
|
||||
on:input={(e) =>
|
||||
handleValueInput(e, row?.rule, 0)}
|
||||
class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-xs focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
/>
|
||||
<span
|
||||
class="text-white text-[1rem] font-normal mt-1"
|
||||
@ -1133,7 +1133,7 @@
|
||||
: ""}
|
||||
on:input={(e) =>
|
||||
handleValueInput(e, row?.rule, 1)}
|
||||
class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-xs focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
@ -1145,7 +1145,7 @@
|
||||
: valueMappings[row?.rule]}
|
||||
on:input={(e) =>
|
||||
handleValueInput(e, row?.rule)}
|
||||
class="ios-zoom-fix block max-w-[4.8rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
class="ios-zoom-fix block max-w-[4.8rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-xs focus:border-blue-500 focus:ring-blue-500 bg-secondary"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@ -1200,7 +1200,7 @@
|
||||
</DropdownMenu.Label>
|
||||
{:else}
|
||||
<div
|
||||
class="relative sticky z-40 focus:outline-none -top-1"
|
||||
class="relative sticky z-40 focus:outline-hidden -top-1"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
style=""
|
||||
@ -1221,7 +1221,7 @@
|
||||
row?.step[index + 1],
|
||||
]);
|
||||
}}
|
||||
class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-none"
|
||||
class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-hidden"
|
||||
>
|
||||
{ruleCondition[row?.rule]?.replace(
|
||||
"between",
|
||||
@ -1241,7 +1241,7 @@
|
||||
on:click={() => {
|
||||
handleChangeValue(newValue);
|
||||
}}
|
||||
class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-none"
|
||||
class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-hidden"
|
||||
>
|
||||
{ruleCondition[row?.rule]
|
||||
?.replace("under", "Under")
|
||||
@ -1306,7 +1306,7 @@
|
||||
class="text-white text-center p-3 sm:p-5 mb-10 mt-5 rounded-md sm:flex sm:flex-row sm:items-center border border-gray-600 text-sm sm:text-[1rem]"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 flex-shrink-0 inline-block sm:mr-2"
|
||||
class="w-6 h-6 shrink-0 inline-block sm:mr-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
@ -1342,7 +1342,7 @@
|
||||
id="ruleModal"
|
||||
for="ruleModal"
|
||||
on:click={() => (searchTerm = "")}
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
|
||||
class="cursor-pointer modal-backdrop bg-[#000]/50"
|
||||
></label>
|
||||
|
||||
<div
|
||||
@ -1352,7 +1352,7 @@
|
||||
<!-- Sticky Header -->
|
||||
|
||||
<div
|
||||
class="fixed w-full h-fit sticky -top-6 z-40 bg-primary shadow-sm opacity-100 pb-6 pt-5 border-gray-600 border-b"
|
||||
class="fixed w-full h-fit sticky -top-6 z-40 bg-primary shadow-xs opacity-100 pb-6 pt-5 border-gray-600 border-b"
|
||||
>
|
||||
<div class="flex flex-row items-center justify-between mb-2">
|
||||
<h2 class="text-white text-[1rem] sm:text-xl font-semibold">
|
||||
@ -1495,9 +1495,7 @@
|
||||
<input type="checkbox" id="mobileTooltip" class="modal-toggle" />
|
||||
|
||||
<dialog id="mobileTooltip" class="modal p-3">
|
||||
<label
|
||||
for="mobileTooltip"
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
|
||||
<label for="mobileTooltip" class="cursor-pointer modal-backdrop bg-[#000]/30"
|
||||
></label>
|
||||
|
||||
<!-- Desktop modal content -->
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Pro Subscription
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Upgrade now for unlimited access to all data and tools.
|
||||
@ -195,7 +195,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
About Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn more about why we're doing this here
|
||||
@ -214,7 +214,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Contact Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Let me know if you need something
|
||||
|
||||
@ -132,7 +132,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
About Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn more about why we're doing this here
|
||||
@ -151,7 +151,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Contact Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Let me know if you need something
|
||||
|
||||
@ -454,7 +454,7 @@
|
||||
class="w-56 h-fit max-h-72 overflow-y-auto scroller"
|
||||
>
|
||||
<div
|
||||
class="relative sticky z-40 focus:outline-none -top-1"
|
||||
class="relative sticky z-40 focus:outline-hidden -top-1"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
>
|
||||
@ -517,7 +517,7 @@
|
||||
class="w-56 h-fit max-h-72 overflow-y-auto scroller"
|
||||
>
|
||||
<div
|
||||
class="relative sticky z-40 focus:outline-none -top-1"
|
||||
class="relative sticky z-40 focus:outline-hidden -top-1"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
></div>
|
||||
@ -597,11 +597,11 @@
|
||||
</h2>
|
||||
{#if filterList.length !== 0}
|
||||
<div
|
||||
class="ml-auto text-[1rem] sm:text-lg flex flex-row items-center relative block rounded-md px-2 py-1 focus:outline-none"
|
||||
class="ml-auto text-[1rem] sm:text-lg flex flex-row items-center relative block rounded-md px-2 py-1 focus:outline-hidden"
|
||||
>
|
||||
<span class="text-white">Filters</span>
|
||||
<span
|
||||
class="ml-2 rounded-full avatar w-5 h-5 text-xs font-semibold text-white text-center flex-shrink-0 flex items-center justify-center bg-red-500"
|
||||
class="ml-2 rounded-full avatar w-5 h-5 text-xs font-semibold text-white text-center shrink-0 flex items-center justify-center bg-red-500"
|
||||
>
|
||||
{filterList.length}
|
||||
</span>
|
||||
@ -795,7 +795,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Earnings Calendar
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3"
|
||||
>Get the latest Earnings of companies</span
|
||||
@ -814,7 +814,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Dividend Calendar
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3"
|
||||
>Get the latest dividend announcement</span
|
||||
|
||||
@ -623,7 +623,7 @@
|
||||
/>
|
||||
|
||||
<section
|
||||
class="w-full max-w-screen-2xl overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3"
|
||||
class="w-full max-w-(--breakpoint-2xl) overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3"
|
||||
>
|
||||
<div class="text-sm sm:text-[1rem] breadcrumbs">
|
||||
<ul>
|
||||
@ -774,7 +774,7 @@
|
||||
{#each tabs as item, i}
|
||||
<button
|
||||
on:click={() => changeTablePeriod(i)}
|
||||
class="group relative z-[1] rounded-full px-6 py-1 {activeIdx ===
|
||||
class="group relative z-1 rounded-full px-6 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
@ -967,7 +967,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Economic Events
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Stay updated on upcoming Economic Events worldwide.
|
||||
@ -986,7 +986,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Earnings Calendar
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest Earnings of companies.
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Pro Subscription
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Upgrade now for unlimited access to all data and tools
|
||||
@ -79,7 +79,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Analyst
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings
|
||||
@ -98,7 +98,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Stocks Picks
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings.
|
||||
|
||||
@ -377,7 +377,7 @@
|
||||
: 'ease-out'} m-auto w-full"
|
||||
>
|
||||
<div
|
||||
class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2"
|
||||
class="flex-1 shrink-0 flex flex-row items-center justify-between -mt-2"
|
||||
>
|
||||
<a
|
||||
href={/^\/(stocks|etf|index)/.test($previousPage || "")
|
||||
@ -465,7 +465,7 @@
|
||||
{#if userWatchList?.length !== 0}
|
||||
<label
|
||||
for="addWatchListModal"
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -492,7 +492,7 @@
|
||||
{:else if userWatchList?.length === 0}
|
||||
<label
|
||||
on:click={() => toggleUserWatchlist("firstList")}
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -521,7 +521,7 @@
|
||||
{:else}
|
||||
<label
|
||||
for="userLogin"
|
||||
class="cursor-pointer flex-shrink-0 text-white mr-4"
|
||||
class="cursor-pointer shrink-0 text-white mr-4"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 inline-block"
|
||||
@ -586,11 +586,11 @@
|
||||
<div class="flex flex-col ml-auto mr-2">
|
||||
{#if userWatchList?.length !== 0}
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full sm:hover:bg-white sm:hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full sm:hover:bg-white sm:hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
for="addWatchListModal"
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -617,12 +617,12 @@
|
||||
</div>
|
||||
{:else if userWatchList?.length === 0}
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
on:click={() =>
|
||||
toggleUserWatchlist("firstList")}
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -651,11 +651,11 @@
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="flex-shrink-0 ml-auto mr-2 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 ml-auto mr-2 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
for="userLogin"
|
||||
class="cursor-pointer flex-shrink-0 text-white"
|
||||
class="cursor-pointer shrink-0 text-white"
|
||||
>
|
||||
<svg
|
||||
class="w-7 h-7 inline-block"
|
||||
@ -674,12 +674,12 @@
|
||||
<!--Start Price Alert -->
|
||||
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
on:click={() => ($openPriceAlert = true)}
|
||||
for={data?.user ? "priceAlertModal" : "userLogin"}
|
||||
class="cursor-pointer flex-shrink-0 text-white"
|
||||
class="cursor-pointer shrink-0 text-white"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Dark Pool Flow
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Follow the dark pool feed in realtime
|
||||
|
||||
@ -529,7 +529,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Stock Screener
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Filter, sort and analyze all stocks to find your next
|
||||
@ -549,7 +549,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Watchlist
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Keep track of your favorite stocks in real-time.
|
||||
|
||||
@ -354,7 +354,7 @@
|
||||
>
|
||||
<div class="flex flex-row items-center">
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full border border-slate-700 w-9 h-9 relative {item?.party ===
|
||||
class="shrink-0 rounded-full border border-slate-700 w-9 h-9 relative {item?.party ===
|
||||
'Republican'
|
||||
? 'bg-[#98272B]'
|
||||
: item?.party === 'Democratic'
|
||||
|
||||
@ -149,7 +149,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Options Flow
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get realtime options flow and customize your screener
|
||||
@ -168,7 +168,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Stock Screener
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Build your Stock Screener to find profitable etf.
|
||||
|
||||
@ -329,7 +329,7 @@
|
||||
class="text-white text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block sm:mr-2 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
</script>
|
||||
|
||||
<section
|
||||
class="w-full max-w-screen-2xl overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3"
|
||||
class="w-full max-w-(--breakpoint-2xl) overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3"
|
||||
>
|
||||
<div class="text-sm sm:text-[1rem] breadcrumbs">
|
||||
<ul>
|
||||
@ -65,7 +65,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Analyst
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings
|
||||
@ -84,7 +84,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Congress Trading
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Congress trading insights.
|
||||
|
||||
@ -204,7 +204,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Analyst
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings
|
||||
@ -223,7 +223,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Congress Trading
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Congress trading insights.
|
||||
|
||||
@ -187,7 +187,7 @@
|
||||
class="w-auto h-fit max-h-72 overflow-y-auto scroller"
|
||||
>
|
||||
<div
|
||||
class="relative sticky z-40 focus:outline-none -top-1"
|
||||
class="relative sticky z-40 focus:outline-hidden -top-1"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
style=""
|
||||
@ -236,7 +236,7 @@
|
||||
class="w-auto h-fit max-h-72 overflow-y-auto scroller"
|
||||
>
|
||||
<div
|
||||
class="relative sticky z-40 focus:outline-none -top-1"
|
||||
class="relative sticky z-40 focus:outline-hidden -top-1"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
style=""
|
||||
|
||||
@ -177,7 +177,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Sponsor Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Learn more about why we're doing this here
|
||||
@ -196,7 +196,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Contact Us
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Let me know if you need something
|
||||
|
||||
@ -378,7 +378,7 @@
|
||||
: 'ease-out'} m-auto w-full"
|
||||
>
|
||||
<div
|
||||
class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2"
|
||||
class="flex-1 shrink-0 flex flex-row items-center justify-between -mt-2"
|
||||
>
|
||||
<a
|
||||
href={/^\/(stocks|etf|index)/.test($previousPage || "")
|
||||
@ -468,7 +468,7 @@
|
||||
{#if userWatchList?.length !== 0}
|
||||
<label
|
||||
for="addWatchListModal"
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -495,7 +495,7 @@
|
||||
{:else if userWatchList?.length === 0}
|
||||
<label
|
||||
on:click={() => toggleUserWatchlist("firstList")}
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -524,7 +524,7 @@
|
||||
{:else}
|
||||
<label
|
||||
for="userLogin"
|
||||
class="cursor-pointer flex-shrink-0 text-white mr-4"
|
||||
class="cursor-pointer shrink-0 text-white mr-4"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 inline-block"
|
||||
@ -589,11 +589,11 @@
|
||||
<div class="flex flex-col ml-auto mr-2">
|
||||
{#if userWatchList?.length !== 0}
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full sm:hover:bg-white sm:hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full sm:hover:bg-white sm:hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
for="addWatchListModal"
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -620,12 +620,12 @@
|
||||
</div>
|
||||
{:else if userWatchList?.length === 0}
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
on:click={() =>
|
||||
toggleUserWatchlist("firstList")}
|
||||
class="cursor-pointer flex-shrink-0"
|
||||
class="cursor-pointer shrink-0"
|
||||
>
|
||||
{#if isTickerIncluded}
|
||||
<svg
|
||||
@ -654,11 +654,11 @@
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="flex-shrink-0 ml-auto mr-2 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 ml-auto mr-2 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
for="userLogin"
|
||||
class="cursor-pointer flex-shrink-0 text-white"
|
||||
class="cursor-pointer shrink-0 text-white"
|
||||
>
|
||||
<svg
|
||||
class="w-7 h-7 inline-block"
|
||||
@ -677,12 +677,12 @@
|
||||
<!--Start Price Alert -->
|
||||
|
||||
<div
|
||||
class="flex-shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
class="shrink-0 rounded-full hover:bg-white hover:bg-opacity-[0.02] transition ease-out w-12 h-12 relative bg-default flex items-center justify-center"
|
||||
>
|
||||
<label
|
||||
on:click={() => ($openPriceAlert = true)}
|
||||
for={data?.user ? "priceAlertModal" : "userLogin"}
|
||||
class="cursor-pointer flex-shrink-0 text-white"
|
||||
class="cursor-pointer shrink-0 text-white"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@ -527,7 +527,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Stock Screener
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Filter, sort and analyze all stocks to find your next
|
||||
@ -547,7 +547,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Watchlist
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Keep track of your favorite stocks in real-time.
|
||||
|
||||
@ -137,7 +137,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Options Flow
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get realtime options flow and customize your screener
|
||||
@ -156,7 +156,7 @@
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Stock Screener
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
<ArrowLogo class="w-8 h-8 mr-3 shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Build your Stock Screener to find profitable etf.
|
||||
|
||||
@ -338,7 +338,7 @@
|
||||
class="text-white text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block sm:mr-2 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
|
||||
@ -831,7 +831,7 @@
|
||||
</span>
|
||||
</p>
|
||||
<button
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-none"
|
||||
class="cursor-pointer text-[1.8rem] text-white focus:outline-hidden"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8"
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
class="border border-gray-800 w-full sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-default sm:rounded-md h-auto p-5 mb-4"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0"
|
||||
class="w-5 h-5 inline-block sm:mr-2 shrink-0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user