migrate to tailwindcss v4

This commit is contained in:
MuslemRahimi 2025-03-03 11:53:06 +01:00
parent 7cbabf582a
commit eb06476f38
151 changed files with 1346 additions and 3903 deletions

1493
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -1,7 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
'@tailwindcss/postcss': {},
autoprefixer: {},
},
};

View File

@ -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;
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
:where(thead, tfoot) {
@apply whitespace-nowrap text-xs;
}
}
@layer utilities {
.no-scrollbar {
@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 */
}
/* Styles for Internet Explorer and Edge */
.no-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;
}
}

View File

@ -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>

View File

@ -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}

View File

@ -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.

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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'
: ''} "

View File

@ -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!

View File

@ -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">

View File

@ -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">

View File

@ -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'
: ''} "

View File

@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <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>

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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}

View File

@ -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 -->

View File

@ -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>

View File

@ -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"

View File

@ -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

View File

@ -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>

View File

@ -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'
: ''} "

View File

@ -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>

View File

@ -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,61 +118,34 @@
},
};
// Sort using the appropriate comparison function
displayedData = originalData.sort(compareFunctions[key]);
}
</script>
<div class="table-container">
<div class="table">
<VirtualList
width="100%"
height={$screenWidth < 640
? data?.user?.tier === "Pro"
? 550
: 250
: data?.user?.tier === "Pro"
? 850
: 250}
itemCount={displayedData.length}
itemSize={40}
>
<!-- 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
slot="header"
class="tr th m-auto sticky z-40 top-0 border border-gray-800"
class="grid grid-cols-10 sticky top-0 z-40 border border-gray-800 bg-default text-white font-bold text-xs uppercase"
>
<!-- Table headers -->
<div
on:click={() => sortData("date")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center"
>
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"
class="cursor-pointer p-2 text-center select-none"
>
Symbol
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['ticker'] ===
'asc'
? 'rotate-180'
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"
@ -213,15 +160,14 @@
<div
on:click={() => sortData("price")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none"
>
Price
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['price'] ===
'asc'
? 'rotate-180'
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"
@ -235,15 +181,14 @@
</div>
<div
on:click={() => sortData("premium")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none"
>
Premium
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['premium'] ===
'asc'
? 'rotate-180'
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"
@ -255,18 +200,16 @@
></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"
class="cursor-pointer p-2 text-center select-none"
>
Size
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['size'] ===
'asc'
? 'rotate-180'
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"
@ -280,15 +223,14 @@
</div>
<div
on:click={() => sortData("volume")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none"
>
Volume
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['volume'] ===
'asc'
? 'rotate-180'
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"
@ -303,16 +245,14 @@
<div
on:click={() => sortData("sizeVolRatio")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none"
>
% Size / Vol
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
'sizeVolRatio'
] === 'asc'
? 'rotate-180'
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"
@ -327,16 +267,14 @@
<div
on:click={() => sortData("sizeAvgVolRatio")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
>
% Size / Avg Vol
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
'sizeAvgVolRatio'
] === 'asc'
? 'rotate-180'
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"
@ -351,15 +289,14 @@
<div
on:click={() => sortData("sector")}
class="td cursor-pointer select-none bg-default text-white font-bold text-xs text-start uppercase"
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
>
Sector
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders['sector'] ===
'asc'
? 'rotate-180'
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"
@ -371,19 +308,16 @@
></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"
class="cursor-pointer p-2 text-center select-none whitespace-nowrap"
>
Asset Type
Asset type
<svg
class="flex-shrink-0 w-4 h-4 inline-block {sortOrders[
'assetType'
] === 'asc'
? 'rotate-180'
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"
@ -397,180 +331,104 @@
</div>
</div>
<!-- VirtualList renders rows in a grid -->
<VirtualList
width="100%"
height={$screenWidth < 640
? data?.user?.tier === "Pro"
? 550
: 250
: data?.user?.tier === "Pro"
? 850
: 250}
itemCount={displayedData.length}
itemSize={40}
>
<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
class="hover:text-blue-400"
>
{displayedData[index]?.sector?.length > 13
? displayedData[index]?.sector?.slice(0, 13) + "..."
: displayedData[index]?.sector}</a
>
: 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>

View File

@ -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;

View File

@ -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"}
>

View File

@ -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>

View File

@ -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>

View File

@ -14,13 +14,15 @@
<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
"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 flex-shrink-0 transition-transform duration-200" />
<ChevronDown
class="text-white h-4 w-4 sm:absolute sm:right-5 shrink-0 transition-transform duration-200"
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>

View File

@ -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:

View File

@ -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",

View File

@ -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}

View File

@ -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}

View File

@ -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
>

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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>

View File

@ -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}
/>

View File

@ -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}

View File

@ -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}

View File

@ -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
)}

View File

@ -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}

View File

@ -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}

View File

@ -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
)}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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>

View File

@ -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}
/>

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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">&lt;-</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">-&gt;</span>
</span>

View File

@ -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

View File

@ -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.

View File

@ -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 -->

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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"

View File

@ -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

View File

@ -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.

View File

@ -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'

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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=""

View File

@ -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

View File

@ -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"

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -107,7 +107,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?.img});"
tabindex="0"
on:click={() => handlePlayClick(index)}
@ -146,7 +146,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?.img}
class="h-auto w-full rounded-md"

Some files were not shown because too many files have changed in this diff Show More