Merge branch 'next'

This commit is contained in:
hzrd149 2023-10-16 18:08:53 -05:00
commit b489004071
2585 changed files with 30683 additions and 2879 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add redeem button for cashu tokens

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add option to set zap splits when creating note

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add stemstr embeds

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add theme option and better dark theme

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Show repost counts on notes

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add support for paying zap splits

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Show recent badge awards on badges page

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Make notes clickable

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add sign up view

View File

@ -0,0 +1,5 @@
---
"nostrudel": patch
---
Fix bug with stream chat not showing on chromium based browsers

View File

@ -0,0 +1,5 @@
---
"nostrudel": patch
---
Reduce churn when loading relays on app load

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Show profile badges on users profile

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Support video and audio file uploads to nostr.build

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Show articles in lists

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Update all icons

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add badge activity tab

View File

@ -44,6 +44,12 @@ jobs:
type=ref,event=branch
type=ref,event=pr
type=sha
- name: Set build env
run: |
echo "VITE_COMMIT_HASH=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV
echo "VITE_APP_VERSION=$(jq -r .version ./package.json)" >> $GITHUB_ENV
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:

View File

@ -37,6 +37,10 @@ jobs:
cache: "npm"
- name: Install dependencies
run: yarn install
- name: Set build env
run: |
echo "VITE_COMMIT_HASH=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV
echo "VITE_APP_VERSION=$(jq -r .version ./package.json)" >> $GITHUB_ENV
- name: Build
run: yarn build
- name: Setup Pages

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
dist
node_modules
cypress/videos
stats.html

View File

@ -1,3 +1,4 @@
node_modules
dist
public/lib
stats.html

View File

@ -1,12 +0,0 @@
import { defineConfig } from "cypress";
export default defineConfig({
viewportWidth: 1200,
viewportHeight: 800,
e2e: {
baseUrl: "http://localhost:5173",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});

View File

@ -1,127 +0,0 @@
describe("Embeds", () => {
describe("hashtags", () => {
it('should handle uppercase hashtags and ","', () => {
cy.visit(
"#/n/nevent1qqsrj5ns6wva3fcghlyx0hp7hhajqtqk3kuckp7xhhscrm4jl7futegpz9mhxue69uhkummnw3e82efwvdhk6qgswaehxw309ahx7um5wgh8w6twv5pkpt8l",
);
cy.findByRole("link", { name: "#Japan" }).should("be.visible");
cy.findByRole("link", { name: "#kyudo" }).should("be.visible");
cy.findByRole("link", { name: "#Shiseikan" }).should("be.visible");
cy.findByRole("link", { name: "#Nostrasia" }).should("be.visible");
});
});
describe("links", () => {
it("embed trustless.computer links", () => {
cy.visit(
"#/n/nevent1qqsfn2mv3pe2v7jak4r5wnyengt36t0rx26w04hgysrmtpml8jnlk5cprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk2qgawaehxw309ahx7um5wgkhqatz9emk2mrvdaexgetj9ehx2aq2wry06",
);
cy.get('[href="https://trustless.computer/"]').should("be.visible");
cy.get(
'[href="https://mempool.space/tx/461c6f56015c94d74837b68c9d08f4b80e7db7ca1e5ac4c53d9aa8c76b667672"]',
).should("be.visible");
});
it("embeds links", () => {
cy.visit(
"#/n/nevent1qqsvg6kt4hl79qpp5p673g7ref6r0c5jvp4yys7mmvs4m50t30sy9dgpz9mhxue69uhkummnw3e82efwvdhk6qgjwaehxw309aex2mrp0yhxvdm69e5k7r3xlpe",
);
cy.get('[href="https://getalby.com/"]').should("exist");
cy.get('[href="https://lightningaddress.com/"]').should("exist");
cy.get('[href="https://snort.social/"]').should("exist");
cy.get('[href="http://damus.io/"]').should("exist");
cy.get('[href="https://vida.live/"]').should("exist");
});
it("embeds simplex.chat links", () => {
cy.visit(
"#/n/nevent1qqsymds0vlpp4f5s0dckjf4qz283pdsen0rmx8lu7ct6hpnxag2hpacpremhxue69uhkummnw3ez6un9d3shjtnwda4k7arpwfhjucm0d5q3qamnwvaz7tmwdaehgu3wwa5kueghxyq76",
);
cy.get(
'[href="https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2F0YuTwO05YJWS8rkjn9eLJDjQhFKvIYd8d4xG8X1blIU%3D%40smp8.simplex.im%2FVlHiRmia02CDgga7w-uNb2FQZTZsj3UR%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAd2GEWU9Zjrljhw8O4FldcxrqehkDWezXl-cWD-VkeEw%253D%26srv%3Dbeccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion"]',
).should("be.visible");
});
});
describe("Nostr links", () => {
it("should embed noub1...", () => {
cy.visit(
"#/n/nevent1qqsd5yw7sntqfc4e7u4aempvgctry2plz653t9gpf97ctk5vc0ftskgpz3mhxue69uhhyetvv9ujuerpd46hxtnfduq3zamnwvaz7tmwdaehgun4v5hxxmmdfxdj3a",
);
cy.contains("Alby team");
cy.get(".chakra-card")
.first()
.within(() => {
cy.get('[href="#/u/npub13sajvl5ak6cpz4ycesl0e5v869r5sey5pt50l9mcy6uas0fqtpmscth4np"]').should("be.visible");
cy.get('[href="#/u/npub167n5w6cj2wseqtmk26zllc7n28uv9c4vw28k2kht206vnghe5a7stgzu3r"]').should("be.visible");
// make sure the leading @ is removed
cy.get(".chakra-card__body").should("not.contain.text", "@@");
});
});
});
describe("youtube", () => {
it("should embed playlists", () => {
cy.visit(
"#/n/nevent1qqs8w6e63smpr5ccmz4l0w5pvnkp6r7z2fxaadjwu2g74y95pl9xv0cpzpmhxue69uhkummnw3ezuamfdejszrthwden5te0dehhxtnvdakqqkgf54",
);
cy.findByTitle(/youtube video player/i).should("be.visible");
cy.findByTitle(/youtube video player/i).should("have.attr", "src");
});
});
describe("Music", () => {
it("should handle wavlake links", () => {
cy.visit(
"#/n/nevent1qqsve4ud5v8gjds2f2h7exlmjvhqayu4s520pge7frpwe22wezny0pcpp4mhxue69uhkummn9ekx7mqprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk2mxs3z0",
);
cy.findByTitle("Wavlake Embed").should("be.visible");
});
it("should handle spotify links", () => {
cy.visit(
"#/n/nevent1qqsx0lz7m72qzq499exwhnfszvgwea8tv38x9wkv32yhkmwwmhgs7jgprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk25m3sln",
);
cy.findByTitle("Spotify List Embed").should("exist");
cy.visit(
"#/n/nevent1qqsqxkmz49hydf8ppa9k6x6zrcq7m4evhhlye0j3lcnz8hrl2q6np4spz3mhxue69uhhyetvv9ujuerpd46hxtnfdult02qz",
);
cy.findByTitle("Spotify Embed").should("exist");
});
it("should handle apple music links", () => {
cy.visit(
"#/n/nevent1qqs9kqt9d7r4zjpawcyl82x5qsn4hals4wn294dv95knrahs4mggwasprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk2whhzvz",
);
cy.findByTitle("Apple Music Embed").should("exist");
cy.visit(
"#/n/nevent1qqszyrz4uug75j4086kj4f8peg3g0v8g9f04zjxplnpq0uxljtthggqprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk2aeexmq",
);
cy.findByTitle("Apple Music List Embed").should("exist");
});
it("should handle Tidal playlist links", () => {
cy.visit("#/n/nevent1qqsg4d6rvg3te0y7sa0xp8r2rgcrnqyp2jmddzm4ufnmqs36aa2247qpp4mhxue69uhkummn9ekx7mqacwd3t");
cy.findByTitle("Tidal List Embed").should("be.visible");
});
});
describe("Emoji", () => {
it("should embed emojis", () => {
cy.visit(
"#/n/nevent1qqsdj7k47uh4z0ypl2m29lvd4ar9zpf6dcy7ls0q6g6qctnxfj5n3pcpzpmhxue69uhkummnw3ezuamfdejszrthwden5te0dehhxtnvdakqdyqlpq",
);
cy.findByRole("img", { name: /pepeD/i }).should("be.visible");
});
});
});

View File

@ -1,68 +0,0 @@
describe("Login view", () => {
beforeEach(() => {
cy.visit("#/login");
cy.window().then(($win) => {
cy.stub($win, "prompt").returns("pass");
});
});
it("login with nip05", () => {
cy.intercept("get", "https://hzrd149.com/.well-known/nostr.json?name=_", {
names: {
_: "266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5",
},
relays: {
"266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5": ["wss://nostrue.com"],
},
});
cy.findByRole("link", { name: /nip-05/i }).click();
cy.findByRole("textbox", { name: /nip-05/i }).type("_@hzrd149.com");
cy.contains(/found 1 relays/i);
cy.findByRole("button", { name: /login/i }).click();
cy.findByRole("button", { name: "Home" }).should("be.visible");
});
it("login with npub", () => {
cy.findByRole("link", { name: /npub/i }).click();
cy.findByRole("textbox", { name: /npub/i }).type("npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr");
cy.findByRole("combobox", { name: /bootstrap relay/i })
.clear()
.type("wss://nostrue.com");
cy.findByRole("button", { name: /login/i }).click();
cy.findByRole("button", { name: "Home" }).should("be.visible");
});
it("login with new nsec", () => {
cy.findByRole("link", { name: /nsec/i }).click();
cy.findByRole("button", { name: /generate/i }).click();
cy.findByRole("combobox", { name: /bootstrap relay/i })
.clear()
.type("wss://nostrue.com");
cy.findByRole("button", { name: /login/i }).click();
cy.findByRole("button", { name: "Home" }).should("be.visible");
});
it("should redirect after login", () => {
cy.visit(
"#/n/nevent1qqs88gdxv36qsjfwr66k7wxuq9r2tg8rsdcnfkcqdg4sc6vlnsma98qpzpmhxue69uhkummnw3ezuamfdejsz9rhwden5te0wfjkccte9ejxzmt4wvhxjmccew89d",
);
cy.findByRole("link", { name: /login/i }).click();
cy.findByRole("link", { name: /nsec/i }).click();
cy.findByRole("button", { name: /generate/i }).click();
cy.findByRole("combobox", { name: /bootstrap relay/i })
.clear()
.type("wss://nostrue.com");
cy.findByRole("button", { name: /login/i }).click();
// should be redirect to note
cy.contains(/GM, and happy bday to your son/i);
});
});

View File

@ -1,16 +0,0 @@
describe("Profile view", () => {
it("should load a rss feed profile", () => {
cy.visit(
"#/u/nprofile1qqsp6hxqjatvxtesgszs8aee0fcjccxa3ef3mzjva4uv2yr5lucp6jcpzemhxue69uhhyumnd3shjtnwdaehgu3wd4hk2s8c5un",
);
cy.contains("fjsmu");
cy.contains("https://rsshub.app/pixiv/user/7569500@rsslay.nostr.moe");
});
it("should load PABLOF7z", () => {
cy.visit("#/u/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft");
cy.contains("npub1l2vyh...3afqutajft");
});
});

View File

@ -1,22 +0,0 @@
describe("No account", () => {
describe("note view", () => {
it("should fetch and render note", () => {
cy.visit(
"#/n/nevent1qqs84hwdlls703w4yf66qsszxjqfc0xselfxrzr6n4qp40vzdnczragpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5jcwczn",
);
cy.get(".chakra-card")
.first()
.within(() => {
// check for note content
cy.contains('I didn\'t know someone had taken the "rsslay" idea and made it good');
// check for author name
cy.get(".chakra-card__header .chakra-heading .chakra-link").should("not.contain", "npub");
});
// check for multiple replies
cy.get(".chakra-card").should("have.length.above", 2);
});
});
});

View File

@ -1,69 +0,0 @@
describe("Search", () => {
describe("Events", () => {
const links: [string, RegExp][] = [
[
"nostr:nevent1qqsvg6kt4hl79qpp5p673g7ref6r0c5jvp4yys7mmvs4m50t30sy9dgpp4mhxue69uhkummn9ekx7mqpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet59dl66z",
/Nostr zaps - a guide/i,
],
["nostr:note10twumllpulza2gn45ppqydyqns7dpn7jvxy8482qr27cym8sy86sgxe3c8", /someone had taken/i],
];
for (const [link, regexp] of links) {
it(`should handle ${link}`, () => {
cy.visit("#/search");
cy.findByRole("searchbox").type(link, { delay: 0 }).type("{enter}");
cy.contains(regexp).should("be.visible");
});
}
for (const [link, regexp] of links) {
const withoutPrefix = link.replace("nostr:", "");
it(`should handle ${withoutPrefix}`, () => {
cy.visit("#/search");
cy.findByRole("searchbox").type(link, { delay: 0 }).type("{enter}");
cy.contains(regexp).should("be.visible");
});
}
});
describe("Profiles", () => {
const profiles: [string, RegExp][] = [
[
"nostr:nprofile1qqsp2alytxwazryxxjv0u0pqhkp247hc9xjetn5rch8c4s6xx5cmpxcpzpmhxue69uhkummnw3ezuamfdejsz9nhwden5te0v96xcctn9ehx7um5wghxcctwvs6ymk33",
/npub1z4m7g\.\.\.kzdsxana6p/i,
],
["nostr:npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", /npub180cvv\.\.\.gkwsyjh6w6/i],
];
for (const [search, regexp] of profiles) {
it(`should handle ${search}`, () => {
cy.visit("#/search");
cy.findByRole("searchbox").type(search, { delay: 0 }).type("{enter}");
cy.contains(regexp).should("be.visible");
});
}
for (const [search, regexp] of profiles) {
const withoutPrefix = search.replace("nostr:", "");
it(`should handle ${withoutPrefix}`, () => {
cy.visit("#/search");
cy.findByRole("searchbox").type(search, { delay: 0 }).type("{enter}");
cy.contains(regexp).should("be.visible");
});
}
});
describe("Hashtag", () => {
it("should redirect to hashtag view", () => {
cy.visit("#/search");
cy.findByRole("searchbox").type("#bitcoin").type("{enter}");
cy.url().should("contain", "/t/bitcoin");
cy.contains("#bitcoin");
});
});
});

View File

@ -1,17 +0,0 @@
describe("Thread", () => {
it("should handle quote notes with e tags correctly", () => {
cy.visit(
"#/n/nevent1qqsx2lnyuke6vmsrz9fdrd6uwjy0g0e9l6menfgdj5truugkh9qmkkgpzpmhxue69uhkummnw3ezuamfdejszrthwden5te0dehhxtnvdakqgc9md6",
);
// find first note
cy.get(".chakra-card")
.first()
.within(() => {
// get quoted note
cy.get(".chakra-card").within(() => {
cy.contains(/looking for people to send money/);
});
});
});
});

View File

@ -1,53 +0,0 @@
/// <reference types="cypress" />
import "@testing-library/cypress/add-commands";
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
declare global {
namespace Cypress {
interface Chainable {
loginWithNewUser(): Chainable<void>;
}
}
}
Cypress.Commands.add("loginWithNewUser", () => {
cy.visit("/login");
cy.window().then(($win) => {
cy.stub($win, "prompt").returns("pass");
});
cy.findByRole("link", { name: /nsec/i }).click();
cy.findByRole("button", { name: /generate/i }).click();
cy.findByRole("combobox", { name: /bootstrap relay/i })
.clear()
.type("wss://nostrue.com", { delay: 0 });
cy.findByRole("button", { name: /login/i }).click();
cy.findByRole("button", { name: "Home" }).should("be.visible");
});

View File

@ -1,31 +0,0 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import "./commands";
// Alternatively you can use CommonJS syntax:
// require('./commands')
beforeEach(() => {
cy.clearAllLocalStorage();
// remove the database for every test
new Promise((res, rej) => {
const request = window.indexedDB.deleteDatabase("storage");
request.onsuccess = res;
request.onerror = rej;
});
});

View File

@ -1,8 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../tsconfig.json",
"include": ["../next-env.d.ts", "../cypress.config.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"types": ["cypress", "@testing-library/cypress", "next"]
}
}

View File

@ -2,6 +2,8 @@
FROM node:18
WORKDIR /app
COPY . /app/
ENV VITE_COMMIT_HASH=""
ENV VITE_APP_VERSION="custom"
RUN yarn install && yarn build
FROM nginx:stable-alpine-slim

View File

@ -20,13 +20,7 @@
content="https://repository-images.githubusercontent.com/581644549/d5eec580-ba3d-41e8-87db-58c313bf3f45"
/>
<script
async
defer
src="https://ackee.nostrudel.ninja/tracker.js"
data-ackee-server="https://ackee.nostrudel.ninja"
data-ackee-domain-id="58b1c39f-43f9-422b-bc7d-06aff35e764e"
></script>
%VITE_ANALYTICS_SCRIPT%
</head>
<body>
<div id="root"></div>

View File

@ -5,16 +5,21 @@
"license": "MIT",
"scripts": {
"start": "vite serve",
"dev": "vite serve",
"dev": "VITE_APP_VERSION=development vite serve",
"build": "tsc --project tsconfig.json && vite build",
"format": "prettier --ignore-path .prettierignore -w .",
"e2e": "cypress open",
"test": "cypress run --e2e --browser=chrome",
"analyze": "npx vite-bundle-visualizer -o ./stats.html"
"analyze": "npx vite-bundle-visualizer -o ./stats.html",
"build-icons": "node ./scripts/build-icons.mjs"
},
"dependencies": {
"@cashu/cashu-ts": "^0.8.2-rc.7",
"@chakra-ui/anatomy": "^2.2.1",
"@chakra-ui/breakpoint-utils": "^2.0.8",
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/media-query": "^3.3.0",
"@chakra-ui/react": "^2.8.1",
"@chakra-ui/shared-utils": "^2.0.4",
"@chakra-ui/styled-system": "^2.9.1",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@getalby/bitcoin-connect-react": "^1.1.0",
@ -22,6 +27,7 @@
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
"bech32": "^2.0.0",
"cheerio": "^1.0.0-rc.12",
"chroma-js": "^2.4.2",
"dayjs": "^1.11.9",
"debug": "^4.3.4",
"emojilib": "2",
@ -29,6 +35,7 @@
"hls.js": "^1.4.10",
"idb": "^7.1.1",
"identicon.js": "^2.3.3",
"json-stringify-deterministic": "^1.0.11",
"leaflet": "^1.9.4",
"leaflet.locatecontrol": "^0.79.0",
"light-bolt11-decoder": "^3.0.0",
@ -58,7 +65,7 @@
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@testing-library/cypress": "^9.0.0",
"@types/chroma-js": "^2.4.1",
"@types/debug": "^4.1.8",
"@types/identicon.js": "^2.3.1",
"@types/leaflet": "^1.9.3",
@ -69,7 +76,7 @@
"@types/react-dom": "^18.2.7",
"@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
"@vitejs/plugin-react": "^4.0.4",
"cypress": "^12.17.4",
"camelcase": "^8.0.0",
"prettier": "^3.0.2",
"typescript": "^5.1.6",
"vite": "^4.4.9",

63
scripts/build-icons.mjs Normal file
View File

@ -0,0 +1,63 @@
import cheerio from "cheerio";
import fs from "fs/promises";
import path from "path";
import camelcase from "camelcase";
import * as prettier from "prettier";
const prettierConfig = JSON.parse(await fs.readFile(".prettierrc", { encoding: "utf-8" }));
const iconsSrc = "./src/components/icons/svg/untitledui-icons";
const iconsDist = "./src/components/icons";
const iconsList = await fs.readdir(iconsSrc);
for (const filename of iconsList) {
const content = await fs.readFile(path.join(iconsSrc, filename), { encoding: "utf-8" });
const componentName = camelcase(path.basename(filename, ".svg"), { pascalCase: true });
const $ = cheerio.load(content);
const viewBox = $("svg").attr("viewBox");
const pathElements = $("path");
const paths = [];
for (const path of pathElements) {
// convert all attributes to camelcase
for (const [key, value] of Object.entries(path.attribs)) {
const ccKey = camelcase(key);
if (ccKey !== key) {
delete path.attribs[key];
path.attribs[ccKey] = value;
}
}
if (path.attribs["stroke"]) {
path.attribs["stroke"] = "currentColor";
}
if (path.attribs["fill"]) {
path.attribs["fill"] = "currentColor";
} else path.attribs["fill"] = "none";
paths.push($.html(path));
}
const outputCode = await prettier.format(
`
import { createIcon } from "@chakra-ui/icons";
const ${componentName} = createIcon({
displayName: "${componentName}",
viewBox: "${viewBox}",
path: [
${paths.join(",\n")}
],
defaultProps: { boxSize: 4 },
});
export default ${componentName};
`,
{ ...prettierConfig, parser: "typescript" },
);
const outputPath = path.join(iconsDist, filename.replace(".svg", ".tsx"));
fs.writeFile(outputPath, outputCode, { encoding: "utf-8" });
console.log(`Wrote ${outputPath}`);
}

View File

@ -1,72 +1,85 @@
import React, { Suspense } from "react";
import { lazy, Suspense } from "react";
import { createHashRouter, Outlet, RouterProvider, ScrollRestoration } from "react-router-dom";
import { Spinner } from "@chakra-ui/react";
import { css, Global } from "@emotion/react";
import { ErrorBoundary } from "./components/error-boundary";
import Layout from "./components/layout";
import { PageProviders } from "./providers";
import DrawerSubViewProvider from "./providers/drawer-sub-view-provider";
import useSetColorMode from "./hooks/use-set-color-mode";
import HomeView from "./views/home/index";
import SettingsView from "./views/settings";
import LoginView from "./views/login";
import NostrLinkView from "./views/link";
import ProfileView from "./views/profile";
import HashTagView from "./views/hashtag";
import NoteView from "./views/note";
import NotificationsView from "./views/notifications";
import DirectMessagesView from "./views/messages";
import DirectMessageChatView from "./views/messages/chat";
import SigninView from "./views/signin";
import SignupView from "./views/signup";
import LoginStartView from "./views/signin/start";
import LoginNpubView from "./views/signin/npub";
import LoginNip05View from "./views/signin/nip05";
import LoginNsecView from "./views/signin/nsec";
import UserView from "./views/user";
import UserNotesTab from "./views/user/notes";
import UserFollowersTab from "./views/user/followers";
import UserRelaysTab from "./views/user/relays";
import UserFollowingTab from "./views/user/following";
import NoteView from "./views/note";
import LoginStartView from "./views/login/start";
import LoginNpubView from "./views/login/npub";
import NotificationsView from "./views/notifications";
import LoginNip05View from "./views/login/nip05";
import LoginNsecView from "./views/login/nsec";
import UserZapsTab from "./views/user/zaps";
import DirectMessagesView from "./views/messages";
import DirectMessageChatView from "./views/messages/chat";
import NostrLinkView from "./views/link";
import UserReportsTab from "./views/user/reports";
import ToolsHomeView from "./views/tools";
import UserAboutTab from "./views/user/about";
import UserReactionsTab from "./views/user/reactions";
import useSetColorMode from "./hooks/use-set-color-mode";
import UserStreamsTab from "./views/user/streams";
import { PageProviders } from "./providers";
import RelaysView from "./views/relays";
import RelayView from "./views/relays/relay";
import RelayReviewsView from "./views/relays/reviews";
import UserListsTab from "./views/user/lists";
import UserGoalsTab from "./views/user/goals";
import MutedByView from "./views/user/muted-by";
import UserArticlesTab from "./views/user/articles";
import ListsView from "./views/lists";
import ListDetailsView from "./views/lists/list-details";
import UserListsTab from "./views/user/lists";
import BrowseListView from "./views/lists/browse";
import EmojiPacksBrowseView from "./views/emoji-packs/browse";
import EmojiPackView from "./views/emoji-packs/emoji-pack";
import UserEmojiPacksTab from "./views/user/emoji-packs";
import EmojiPacksView from "./views/emoji-packs";
import GoalsView from "./views/goals";
import GoalsBrowseView from "./views/goals/browse";
import GoalDetailsView from "./views/goals/goal-details";
import UserGoalsTab from "./views/user/goals";
import MutedByView from "./views/user/muted-by";
import BadgesView from "./views/badges";
import BadgesBrowseView from "./views/badges/browse";
import BadgeDetailsView from "./views/badges/badge-details";
import UserArticlesTab from "./views/user/articles";
import DrawerSubViewProvider from "./providers/drawer-sub-view-provider";
import CommunitiesHomeView from "./views/communities";
import CommunityFindByNameView from "./views/community/find-by-name";
import CommunityView from "./views/community/index";
import PopularRelaysView from "./views/relays/popular";
import CommunityPendingView from "./views/community/views/pending";
import CommunityNewView from "./views/community/views/new";
const NetworkView = React.lazy(() => import("./views/tools/network"));
const NetworkGraphView = React.lazy(() => import("./views/tools/network-mute-graph"));
const StreamsView = React.lazy(() => import("./views/streams"));
const StreamView = React.lazy(() => import("./views/streams/stream"));
const SearchView = React.lazy(() => import("./views/search"));
const MapView = React.lazy(() => import("./views/map"));
const StreamModerationView = React.lazy(() => import("./views/tools/stream-moderation"));
import RelaysView from "./views/relays";
import RelayView from "./views/relays/relay";
import RelayReviewsView from "./views/relays/reviews";
import PopularRelaysView from "./views/relays/popular";
const UserTracksTab = lazy(() => import("./views/user/tracks"));
const ToolsHomeView = lazy(() => import("./views/tools"));
const NetworkView = lazy(() => import("./views/tools/network"));
const StreamModerationView = lazy(() => import("./views/tools/stream-moderation"));
const NetworkGraphView = lazy(() => import("./views/tools/network-mute-graph"));
const UserStreamsTab = lazy(() => import("./views/user/streams"));
const StreamsView = lazy(() => import("./views/streams"));
const StreamView = lazy(() => import("./views/streams/stream"));
const SearchView = lazy(() => import("./views/search"));
const MapView = lazy(() => import("./views/map"));
const overrideReactTextareaAutocompleteStyles = css`
.rta__autocomplete {
@ -110,8 +123,8 @@ const RootPage = () => {
const router = createHashRouter([
{
path: "login",
element: <LoginView />,
path: "signin",
element: <SigninView />,
children: [
{ path: "", element: <LoginStartView /> },
{ path: "npub", element: <LoginNpubView /> },
@ -119,6 +132,27 @@ const router = createHashRouter([
{ path: "nsec", element: <LoginNsecView /> },
],
},
{
path: "signup",
children: [
{
path: "",
element: (
<PageProviders>
<SignupView />
</PageProviders>
),
},
{
path: ":step",
element: (
<PageProviders>
<SignupView />
</PageProviders>
),
},
],
},
{
path: "streams/:naddr",
element: (
@ -152,6 +186,7 @@ const router = createHashRouter([
{ path: "notes", element: <UserNotesTab /> },
{ path: "articles", element: <UserArticlesTab /> },
{ path: "streams", element: <UserStreamsTab /> },
{ path: "tracks", element: <UserTracksTab /> },
{ path: "zaps", element: <UserZapsTab /> },
{ path: "likes", element: <UserReactionsTab /> },
{ path: "lists", element: <UserListsTab /> },
@ -207,7 +242,14 @@ const router = createHashRouter([
path: "c/:community",
children: [
{ path: "", element: <CommunityFindByNameView /> },
{ path: ":pubkey", element: <CommunityView /> },
{
path: ":pubkey",
element: <CommunityView />,
children: [
{ path: "", element: <CommunityNewView /> },
{ path: "pending", element: <CommunityPendingView /> },
],
},
],
},
{

View File

@ -1,8 +1,9 @@
import { getEventUID } from "../helpers/nostr/events";
import { NostrEvent } from "../types/nostr-event";
import { getEventUID, isReplaceable } from "../helpers/nostr/events";
import replaceableEventLoaderService from "../services/replaceable-event-requester";
import { NostrEvent, isDTag } from "../types/nostr-event";
import Subject from "./subject";
export type EventFilter = (event: NostrEvent) => boolean;
export type EventFilter = (event: NostrEvent, store: EventStore) => boolean;
export default class EventStore {
name?: string;
@ -20,7 +21,8 @@ export default class EventStore {
onDelete = new Subject<string>(undefined, false);
onClear = new Subject(undefined, false);
addEvent(event: NostrEvent) {
private replaceableEventSubs = new Map<string, Subject<NostrEvent>>();
private handleEvent(event: NostrEvent) {
const id = getEventUID(event);
const existing = this.events.get(id);
if (!existing || event.created_at > existing.created_at) {
@ -28,6 +30,21 @@ export default class EventStore {
this.onEvent.next(event);
}
}
addEvent(event: NostrEvent) {
const id = getEventUID(event);
this.handleEvent(event);
if (isReplaceable(event.kind)) {
// pass the event on
replaceableEventLoaderService.handleEvent(event);
// subscribe to any future changes
const sub = replaceableEventLoaderService.getEvent(event.kind, event.pubkey, event.tags.find(isDTag)?.[1]);
sub.subscribe(this.handleEvent, this);
this.replaceableEventSubs.set(id, sub);
}
}
getEvent(id: string) {
return this.events.get(id);
}
@ -36,11 +53,23 @@ export default class EventStore {
this.events.delete(id);
this.onDelete.next(id);
}
if (this.replaceableEventSubs.has(id)) {
this.replaceableEventSubs.get(id)?.unsubscribe(this.handleEvent, this);
this.replaceableEventSubs.delete(id);
}
}
clear() {
this.events.clear();
this.onClear.next(undefined);
for (const [_, sub] of this.replaceableEventSubs) {
sub.unsubscribe(this.handleEvent, this);
}
}
cleanup() {
this.clear();
}
connect(other: EventStore) {
@ -59,7 +88,7 @@ export default class EventStore {
while (true) {
const event = events.shift();
if (!event) return;
if (filter && !filter(event)) continue;
if (filter && !filter(event, this)) continue;
if (i === nth) return event;
i++;
}
@ -71,7 +100,7 @@ export default class EventStore {
while (true) {
const event = events.pop();
if (!event) return;
if (filter && !filter(event)) continue;
if (filter && !filter(event, this)) continue;
if (i === nth) return event;
i++;
}

View File

@ -2,10 +2,10 @@ import { nanoid } from "nanoid";
import { Subject } from "./subject";
import { NostrEvent } from "../types/nostr-event";
import { NostrOutgoingMessage, NostrRequestFilter } from "../types/nostr-query";
import { IncomingEvent, Relay } from "./relay";
import Relay, { IncomingEvent } from "./relay";
import relayPoolService from "../services/relay-pool";
export class NostrMultiSubscription {
export default class NostrMultiSubscription {
static INIT = "initial";
static OPEN = "open";
static CLOSED = "closed";

View File

@ -5,7 +5,7 @@ import relayPoolService from "../services/relay-pool";
import replaceableEventLoaderService from "../services/replaceable-event-requester";
import { NostrEvent } from "../types/nostr-event";
import createDefer from "./deferred";
import { IncomingCommandResult, Relay } from "./relay";
import Relay, { IncomingCommandResult } from "./relay";
import Subject, { PersistentSubject } from "./subject";
export default class NostrPublishAction {

View File

@ -1,13 +1,13 @@
import { nanoid } from "nanoid";
import { NostrEvent } from "../types/nostr-event";
import { CountResponse, NostrEvent } from "../types/nostr-event";
import { NostrRequestFilter } from "../types/nostr-query";
import relayPoolService from "../services/relay-pool";
import { IncomingEOSE, IncomingEvent, Relay } from "./relay";
import Relay, { IncomingCount, IncomingEOSE, IncomingEvent } from "./relay";
import Subject from "./subject";
import createDefer from "./deferred";
const REQUEST_DEFAULT_TIMEOUT = 1000 * 5;
export class NostrRequest {
export default class NostrRequest {
static IDLE = "idle";
static RUNNING = "running";
static COMPLETE = "complete";
@ -16,7 +16,8 @@ export class NostrRequest {
timeout: number;
relays: Set<Relay>;
state = NostrRequest.IDLE;
onEvent = new Subject<NostrEvent>();
onEvent = new Subject<NostrEvent>(undefined, false);
onCount = new Subject<CountResponse>(undefined, false);
onComplete = createDefer<void>();
seenEvents = new Set<string>();
@ -27,6 +28,7 @@ export class NostrRequest {
for (const relay of this.relays) {
relay.onEOSE.subscribe(this.handleEOSE, this);
relay.onEvent.subscribe(this.handleEvent, this);
relay.onCount.subscribe(this.handleCount, this);
}
this.timeout = timeout ?? REQUEST_DEFAULT_TIMEOUT;
@ -57,8 +59,13 @@ export class NostrRequest {
this.seenEvents.add(incomingEvent.body.id);
}
}
handleCount(incomingCount: IncomingCount) {
if (incomingCount.subId === this.id) {
this.onCount.next({ count: incomingCount.count, approximate: incomingCount.approximate });
}
}
start(filter: NostrRequestFilter) {
start(filter: NostrRequestFilter, type: "REQ" | "COUNT" = "REQ") {
if (this.state !== NostrRequest.IDLE) {
throw new Error("cant restart a nostr request");
}
@ -66,8 +73,8 @@ export class NostrRequest {
this.state = NostrRequest.RUNNING;
for (const relay of this.relays) {
if (Array.isArray(filter)) {
relay.send(["REQ", this.id, ...filter]);
} else relay.send(["REQ", this.id, filter]);
relay.send([type, this.id, ...filter]);
} else relay.send([type, this.id, filter]);
}
setTimeout(() => this.complete(), this.timeout);

View File

@ -1,11 +1,11 @@
import { NostrEvent } from "../types/nostr-event";
import { NostrOutgoingMessage, NostrRequestFilter } from "../types/nostr-query";
import { IncomingEOSE, Relay } from "./relay";
import Relay, { IncomingEOSE } from "./relay";
import relayPoolService from "../services/relay-pool";
import { Subject } from "./subject";
import { nanoid } from "nanoid";
export class NostrSubscription {
export default class NostrSubscription {
static INIT = "initial";
static OPEN = "open";
static CLOSED = "closed";

View File

@ -16,6 +16,7 @@ export type IncomingNotice = {
};
export type IncomingCount = {
type: "COUNT";
subId: string;
relay: Relay;
} & CountResponse;
export type IncomingEOSE = {
@ -42,7 +43,7 @@ export type RelayConfig = { url: string; mode: RelayMode };
const CONNECTION_TIMEOUT = 1000 * 30;
export class Relay {
export default class Relay {
url: string;
onOpen = new Subject<Relay>(undefined, false);
onClose = new Subject<Relay>(undefined, false);
@ -116,7 +117,7 @@ export class Relay {
this.ws?.send(JSON.stringify(json));
// record start time
if (json[0] === "REQ") {
if (json[0] === "REQ" || json[0] === "COUNT") {
this.startSubResTimer(json[1]);
}
} else this.queue.push(json);
@ -186,7 +187,7 @@ export class Relay {
this.onNotice.next({ relay: this, type, message: data[1] });
break;
case "COUNT":
this.onCount.next({ relay: this, type, ...data[2] });
this.onCount.next({ relay: this, type, subId: data[1], ...data[2] });
break;
case "EOSE":
this.onEOSE.next({ relay: this, type, subId: data[1] });

View File

@ -1,4 +1,4 @@
export class SuperMap<Key, Value> extends Map<Key, Value> {
export default class SuperMap<Key, Value> extends Map<Key, Value> {
newValue: (key: Key) => Value;
constructor(newValue: (key: Key) => Value) {

View File

@ -1,10 +1,10 @@
import { getReferences } from "../helpers/nostr/events";
import { NostrEvent } from "../types/nostr-event";
import { NostrRequest } from "./nostr-request";
import { NostrMultiSubscription } from "./nostr-multi-subscription";
import NostrRequest from "./nostr-request";
import NostrMultiSubscription from "./nostr-multi-subscription";
import { PersistentSubject } from "./subject";
export class ThreadLoader {
export default class ThreadLoader {
loading = new PersistentSubject(false);
focusId = new PersistentSubject<string>("");
rootId = new PersistentSubject<string>("");

View File

@ -2,8 +2,8 @@ import dayjs from "dayjs";
import { Debugger } from "debug";
import { NostrEvent, isATag, isETag } from "../types/nostr-event";
import { NostrQuery, NostrRequestFilter } from "../types/nostr-query";
import { NostrRequest } from "./nostr-request";
import { NostrMultiSubscription } from "./nostr-multi-subscription";
import NostrRequest from "./nostr-request";
import NostrMultiSubscription from "./nostr-multi-subscription";
import Subject, { PersistentSubject } from "./subject";
import { logger } from "../helpers/debug";
import EventStore from "./event-store";
@ -20,7 +20,7 @@ function addToQuery(filter: NostrRequestFilter, query: NostrQuery) {
const BLOCK_SIZE = 30;
export type EventFilter = (event: NostrEvent) => boolean;
export type EventFilter = (event: NostrEvent, store: EventStore) => boolean;
export class RelayTimelineLoader {
relay: string;
@ -97,7 +97,7 @@ export class RelayTimelineLoader {
}
}
export class TimelineLoader {
export default class TimelineLoader {
cursor = dayjs().unix();
query?: NostrRequestFilter;
relays: string[] = [];
@ -134,7 +134,8 @@ export class TimelineLoader {
private updateTimeline() {
if (this.eventFilter) {
this.timeline.next(this.events.getSortedEvents().filter(this.eventFilter));
const filter = this.eventFilter;
this.timeline.next(this.events.getSortedEvents().filter((e) => filter(e, this.events)));
} else this.timeline.next(this.events.getSortedEvents());
}
private handleEvent(event: NostrEvent) {
@ -207,7 +208,7 @@ export class TimelineLoader {
// update the subscription with the new query
this.subscription.setQuery(addToQuery(query, { limit: BLOCK_SIZE / 2 }));
}
setFilter(filter?: (event: NostrEvent) => boolean) {
setFilter(filter?: EventFilter) {
this.eventFilter = filter;
this.updateTimeline();
}
@ -277,6 +278,7 @@ export class TimelineLoader {
cleanup() {
this.close();
this.removeLoaders();
this.events.cleanup();
deleteEventService.stream.unsubscribe(this.handleDeleteEvent, this);
}

View File

@ -19,11 +19,12 @@ import {
Flex,
ButtonProps,
} from "@chakra-ui/react";
import relayPoolService from "../services/relay-pool";
import { useInterval } from "react-use";
import { RelayStatus } from "./relay-status";
import { RelayIcon } from "./icons";
import { Relay } from "../classes/relay";
import Relay from "../classes/relay";
import { RelayFavicon } from "./relay-favicon";
import relayScoreboardService from "../services/relay-scoreboard";
import { RelayScoreBreakdown } from "./relay-score-breakdown";

View File

@ -1,13 +1,14 @@
import { IconButton, IconButtonProps } from "@chakra-ui/react";
import { useState } from "react";
import { CheckIcon, ClipboardIcon } from "./icons";
import { IconButton, IconButtonProps } from "@chakra-ui/react";
import { CheckIcon, CopyToClipboardIcon } from "./icons";
export const CopyIconButton = ({ text, ...props }: { text?: string } & Omit<IconButtonProps, "icon">) => {
const [copied, setCopied] = useState(false);
return (
<IconButton
icon={copied ? <CheckIcon /> : <ClipboardIcon />}
icon={copied ? <CheckIcon /> : <CopyToClipboardIcon />}
onClick={() => {
if (text && navigator.clipboard && !copied) {
navigator.clipboard.writeText(text);

View File

@ -1,11 +1,12 @@
import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalCloseButton, Flex } from "@chakra-ui/react";
import { Modal, ModalOverlay, ModalContent, ModalBody, ModalCloseButton, Flex } from "@chakra-ui/react";
import { ModalProps } from "@chakra-ui/react";
import { nip19 } from "nostr-tools";
import { getReferences } from "../../helpers/nostr/events";
import { NostrEvent } from "../../types/nostr-event";
import RawJson from "./raw-json";
import RawValue from "./raw-value";
import RawPre from "./raw-pre";
import { nip19 } from "nostr-tools";
export default function NoteDebugModal({ event, ...props }: { event: NostrEvent } & Omit<ModalProps, "children">) {
return (

View File

@ -1,12 +1,13 @@
import { Flex, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay } from "@chakra-ui/react";
import { ModalProps } from "@chakra-ui/react";
import { Kind, nip19 } from "nostr-tools";
import { useUserMetadata } from "../../hooks/use-user-metadata";
import RawValue from "./raw-value";
import RawJson from "./raw-json";
import { useSharableProfileId } from "../../hooks/use-shareable-profile-id";
import useUserLNURLMetadata from "../../hooks/use-user-lnurl-metadata";
import replaceableEventLoaderService from "../../services/replaceable-event-requester";
import { Kind, nip19 } from "nostr-tools";
export default function UserDebugModal({ pubkey, ...props }: { pubkey: string } & Omit<ModalProps, "children">) {
const npub = nip19.npubEncode(pubkey);

View File

@ -1,18 +1,16 @@
import { AvatarGroup, Card, CardBody, CardHeader, CardProps, Flex, Heading, Link, Text } from "@chakra-ui/react";
import { Card, CardBody, CardHeader, CardProps, Flex, Heading, Link, Text } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { NostrEvent } from "../../../types/nostr-event";
import { getEventsFromList, getListName, getPubkeysFromList, isSpecialListKind } from "../../../helpers/nostr/lists";
import { getListName, isSpecialListKind } from "../../../helpers/nostr/lists";
import { createCoordinate } from "../../../services/replaceable-event-requester";
import { getSharableEventAddress } from "../../../helpers/nip19";
import { UserAvatarLink } from "../../user-avatar-link";
import { UserLink } from "../../user-link";
import { NoteLink } from "../../note-link";
import ListFeedButton from "../../../views/lists/components/list-feed-button";
import { ListCardContent } from "../../../views/lists/components/list-card";
export default function EmbeddedList({ list: list, ...props }: Omit<CardProps, "children"> & { list: NostrEvent }) {
const people = getPubkeysFromList(list);
const notes = getEventsFromList(list);
export default function EmbeddedList({ list, ...props }: Omit<CardProps, "children"> & { list: NostrEvent }) {
const link = isSpecialListKind(list.kind) ? createCoordinate(list.kind, list.pubkey) : getSharableEventAddress(list);
return (
@ -23,28 +21,15 @@ export default function EmbeddedList({ list: list, ...props }: Omit<CardProps, "
{getListName(list)}
</Link>
</Heading>
<ListFeedButton list={list} ml="auto" size="sm" />
</CardHeader>
<CardBody p="2">
<Flex gap="2">
<Text>Created by:</Text>
<Text>by</Text>
<UserAvatarLink pubkey={list.pubkey} size="xs" />
<UserLink pubkey={list.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
</Flex>
{people.length > 0 && (
<AvatarGroup overflow="hidden" mb="2" max={16} size="sm">
{people.map(({ pubkey, relay }) => (
<UserAvatarLink key={pubkey} pubkey={pubkey} relay={relay} />
))}
</AvatarGroup>
)}
{notes.length > 0 && (
<Flex gap="2" overflow="hidden">
{notes.map(({ id, relay }) => (
<NoteLink key={id} noteId={id} />
))}
</Flex>
)}
<ListFeedButton list={list} ml="auto" size="sm" />
</CardHeader>
<CardBody p="2">
<ListCardContent list={list} />
</CardBody>
</Card>
);

View File

@ -1,5 +1,5 @@
import { MouseEventHandler, useCallback } from "react";
import { Card, CardProps, Flex, LinkBox, LinkOverlay, Spacer } from "@chakra-ui/react";
import { Card, CardProps, Flex, LinkBox, LinkOverlay, Spacer, cssVar } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { NostrEvent } from "../../../types/nostr-event";
@ -15,13 +15,7 @@ import Timestamp from "../../timestamp";
import { getSharableEventAddress } from "../../../helpers/nip19";
import { InlineNoteContent } from "../../note/inline-note-content";
import { useNavigateInDrawer } from "../../../providers/drawer-sub-view-provider";
import styled from "@emotion/styled";
const HoverLinkOverlay = styled(LinkOverlay)`
&:hover:before {
background-color: rgba(0, 0, 0, 0.15);
}
`;
import HoverLinkOverlay from "../../hover-link-overlay";
export default function EmbeddedNote({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
const { showSignatureVerification } = useSubject(appSettings);

View File

@ -0,0 +1,101 @@
import {
Box,
Button,
ButtonGroup,
Card,
CardBody,
CardFooter,
CardHeader,
CardProps,
Flex,
IconButton,
Image,
Link,
Tag,
Tooltip,
} from "@chakra-ui/react";
import { NostrEvent } from "../../../types/nostr-event";
import { UserAvatarLink } from "../../user-avatar-link";
import { UserLink } from "../../user-link";
import { InlineNoteContent } from "../../note/inline-note-content";
import { getDownloadURL, getHashtags, getStreamURL } from "../../../helpers/nostr/stemstr";
import { DownloadIcon, ReplyIcon } from "../../icons";
import NoteZapButton from "../../note/note-zap-button";
import { QuoteRepostButton } from "../../note/components/quote-repost-button";
import Timestamp from "../../timestamp";
import { ReactNode } from "react";
import { LiveAudioPlayer } from "../../live-audio-player";
// example nevent1qqst32cnyhhs7jt578u7vp3y047dduuwjquztpvwqc43f3nvg8dh28gpzamhxue69uhhyetvv9ujuum5v4khxarj9eshquq4rxdxa
export default function EmbeddedStemstrTrack({ track, ...props }: Omit<CardProps, "children"> & { track: NostrEvent }) {
const streamUrl = getStreamURL(track);
const downloadUrl = getDownloadURL(track);
let player: ReactNode | null = null;
if (streamUrl) {
player = <LiveAudioPlayer stream={streamUrl.url} w="full" />;
} else if (downloadUrl) {
player = (
<Box as="audio" controls w="full">
<source src={downloadUrl.url} type={downloadUrl.format} />
</Box>
);
}
const hashtags = getHashtags(track);
return (
<Card {...props}>
<CardHeader display="flex" alignItems="center" p="2" pb="0" gap="2">
<UserAvatarLink pubkey={track.pubkey} size="xs" />
<UserLink pubkey={track.pubkey} isTruncated fontWeight="bold" fontSize="lg" />
<Timestamp ml="auto" timestamp={track.created_at} />
</CardHeader>
<CardBody p="2" display="flex" gap="2" flexDirection="column">
{player}
<InlineNoteContent event={track} />
{hashtags.length > 0 && (
<Flex wrap="wrap" gap="2">
{hashtags.map((hashtag) => (
<Tag>#{hashtag}</Tag>
))}
</Flex>
)}
</CardBody>
<CardFooter px="2" pt="0" pb="2" flexWrap="wrap" gap="2">
<ButtonGroup size="sm">
<Tooltip label="Coming soon...">
<Button leftIcon={<ReplyIcon />} isDisabled>
Comment
</Button>
</Tooltip>
<QuoteRepostButton event={track} />
<NoteZapButton event={track} />
</ButtonGroup>
<ButtonGroup size="sm" ml="auto">
{downloadUrl && (
<IconButton
as={Link}
icon={<DownloadIcon />}
aria-label="Download"
title="Download"
href={downloadUrl.url}
download
isExternal
/>
)}
<Button
as={Link}
leftIcon={<Image src="https://stemstr.app/favicon.svg" />}
href={`https://stemstr.app/thread/${track.id}`}
colorScheme="purple"
isExternal
>
View on Stemstr
</Button>
</ButtonGroup>
</CardFooter>
</Card>
);
}

View File

@ -1,4 +1,4 @@
import { Card, CardBody, CardProps, Flex, Heading, Image, Link, Tag, Text, useBreakpointValue } from "@chakra-ui/react";
import { Card, CardBody, CardProps, Flex, Heading, Image, Link, Tag, Text } from "@chakra-ui/react";
import { Link as RouterLink, useNavigate } from "react-router-dom";
import { parseStreamEvent } from "../../../helpers/nostr/stream";
@ -8,6 +8,7 @@ import { UserLink } from "../../user-link";
import { UserAvatar } from "../../user-avatar";
import useEventNaddr from "../../../hooks/use-event-naddr";
import Timestamp from "../../timestamp";
import { useBreakpointValue } from "../../../providers/breakpoint-provider";
export default function EmbeddedStream({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
const stream = parseStreamEvent(event);

View File

@ -1,28 +1,32 @@
import { lazy } from "react";
import type { DecodeResult } from "nostr-tools/lib/nip19";
import { CardProps } from "@chakra-ui/react";
import { Kind, nip19 } from "nostr-tools";
import EmbeddedNote from "./event-types/embedded-note";
import useSingleEvent from "../../hooks/use-single-event";
import { NoteLink } from "../note-link";
import { NostrEvent } from "../../types/nostr-event";
import { Kind, nip19 } from "nostr-tools";
import useReplaceableEvent from "../../hooks/use-replaceable-event";
import RelayCard from "../../views/relays/components/relay-card";
import { STREAM_CHAT_MESSAGE_KIND, STREAM_KIND } from "../../helpers/nostr/stream";
import { GOAL_KIND } from "../../helpers/nostr/goal";
import { safeDecode } from "../../helpers/nip19";
import EmbeddedStream from "./event-types/embedded-stream";
import { EMOJI_PACK_KIND } from "../../helpers/nostr/emoji-packs";
import { NOTE_LIST_KIND, PEOPLE_LIST_KIND } from "../../helpers/nostr/lists";
import { COMMUNITY_DEFINITION_KIND } from "../../helpers/nostr/communities";
import { STEMSTR_TRACK_KIND } from "../../helpers/nostr/stemstr";
import useReplaceableEvent from "../../hooks/use-replaceable-event";
import { safeDecode } from "../../helpers/nip19";
import RelayCard from "../../views/relays/components/relay-card";
import EmbeddedStream from "./event-types/embedded-stream";
import EmbeddedEmojiPack from "./event-types/embedded-emoji-pack";
import EmbeddedGoal, { EmbeddedGoalOptions } from "./event-types/embedded-goal";
import EmbeddedUnknown from "./event-types/embedded-unknown";
import { NOTE_LIST_KIND, PEOPLE_LIST_KIND } from "../../helpers/nostr/lists";
import EmbeddedList from "./event-types/embedded-list";
import EmbeddedArticle from "./event-types/embedded-article";
import EmbeddedBadge from "./event-types/embedded-badge";
import EmbeddedStreamMessage from "./event-types/embedded-stream-message";
import { COMMUNITY_DEFINITION_KIND } from "../../helpers/nostr/communities";
import EmbeddedCommunity from "./event-types/embedded-community";
const EmbeddedStemstrTrack = lazy(() => import("./event-types/embedded-stemstr-track"));
export type EmbedProps = {
goalProps?: EmbeddedGoalOptions;
@ -53,6 +57,8 @@ export function EmbedEvent({
return <EmbeddedStreamMessage message={event} {...cardProps} />;
case COMMUNITY_DEFINITION_KIND:
return <EmbeddedCommunity community={event} {...cardProps} />;
case STEMSTR_TRACK_KIND:
return <EmbeddedStemstrTrack track={event} {...cardProps} />;
}
return <EmbeddedUnknown event={event} {...cardProps} />;

View File

@ -0,0 +1,16 @@
import { lazy } from "react";
import { EmbedableContent, embedJSX } from "../../helpers/embeds";
import { getMatchCashu } from "../../helpers/regexp";
const InlineCachuCard = lazy(() => import("../inline-cashu-card"));
export function embedCashuTokens(content: EmbedableContent) {
return embedJSX(content, {
regexp: getMatchCashu(),
render: (match) => {
// set zIndex and position so link over dose not cover card
return <InlineCachuCard token={match[0]} zIndex={1} position="relative" />;
},
name: "emoji",
});
}

View File

@ -6,7 +6,13 @@ import { isVideoURL } from "../../helpers/url";
export function renderVideoUrl(match: URL) {
if (!isVideoURL(match)) return null;
return <video src={match.toString()} controls style={{ maxWidth: "30rem", maxHeight: "20rem", width: "100%" }} />;
return (
<video
src={match.toString()}
controls
style={{ maxWidth: "30rem", maxHeight: "20rem", width: "100%", position: "relative", zIndex: 1 }}
/>
);
}
export function renderGenericUrl(match: URL) {

View File

@ -8,7 +8,7 @@ import {
useRef,
useState,
} from "react";
import { Image, ImageProps, useBreakpointValue } from "@chakra-ui/react";
import { Image, ImageProps, Link, LinkProps } from "@chakra-ui/react";
import appSettings from "../../services/settings/app-settings";
import { useTrusted } from "../../providers/trust";
@ -19,6 +19,7 @@ import { isImageURL } from "../../helpers/url";
import PhotoGallery, { PhotoWithoutSize } from "../photo-gallery";
import { NostrEvent } from "../../types/nostr-event";
import useAppSettings from "../../hooks/use-app-settings";
import { useBreakpointValue } from "../../providers/breakpoint-provider";
function useElementBlur(initBlur = false): { style: CSSProperties; onClick: MouseEventHandler } {
const [blur, setBlur] = useState(initBlur);
@ -60,23 +61,69 @@ export const TrustImage = forwardRef<HTMLImageElement, TrustImageProps>((props,
else return <Image {...props} onClick={handleClick} style={{ ...style, ...props.style }} ref={ref} />;
});
export type EmbeddedImageProps = TrustImageProps & {
export type EmbeddedImageProps = Omit<LinkProps, "children" | "href" | "onClick"> & {
src?: string;
event?: NostrEvent;
imageProps?: TrustImageProps;
};
export const EmbeddedImage = forwardRef<HTMLImageElement, EmbeddedImageProps>(({ src, event, ...props }, ref) => {
const thumbnail = appSettings.value.imageProxy
? new URL(`/256,fit/${src}`, appSettings.value.imageProxy).toString()
: src;
function useImageThumbnail(src?: string) {
return appSettings.value.imageProxy ? new URL(`/256,fit/${src}`, appSettings.value.imageProxy).toString() : src;
}
ref = ref || useRef<HTMLImageElement | null>(null);
const { show } = useRegisterSlide(
ref as MutableRefObject<HTMLImageElement | null>,
src ? { type: "image", src, event } : undefined,
);
export const EmbeddedImage = forwardRef<HTMLImageElement, EmbeddedImageProps>(
({ src, event, imageProps, ...props }, ref) => {
const thumbnail = useImageThumbnail(src);
return <TrustImage {...props} src={thumbnail} cursor="pointer" ref={ref} onClick={show} />;
});
ref = ref || useRef<HTMLImageElement | null>(null);
const { show } = useRegisterSlide(
ref as MutableRefObject<HTMLImageElement | null>,
src ? { type: "image", src, event } : undefined,
);
const handleClick = useCallback<MouseEventHandler<HTMLElement>>(
(e) => {
!e.isPropagationStopped() && show();
e.preventDefault();
},
[show],
);
// NOTE: the parent <div> has display=block and and <a> has inline-block
// this is so that the <a> element can act like a block without being full width
return (
<div>
<Link href={src} isExternal onClick={handleClick} display="inline-block" {...props}>
<TrustImage {...imageProps} src={thumbnail} cursor="pointer" ref={ref} onClick={handleClick} />
</Link>
</div>
);
},
);
export const GalleryImage = forwardRef<HTMLImageElement, EmbeddedImageProps>(
({ src, event, imageProps, ...props }, ref) => {
const thumbnail = useImageThumbnail(src);
ref = ref || useRef<HTMLImageElement | null>(null);
const { show } = useRegisterSlide(
ref as MutableRefObject<HTMLImageElement | null>,
src ? { type: "image", src, event } : undefined,
);
const handleClick = useCallback<MouseEventHandler<HTMLElement>>(
(e) => {
!e.isPropagationStopped() && show();
e.preventDefault();
},
[show],
);
return (
<Link href={src} isExternal onClick={handleClick} {...props}>
<TrustImage src={thumbnail} cursor="pointer" ref={ref} onClick={handleClick} {...imageProps} />
</Link>
);
},
);
export function ImageGallery({ images, event }: { images: string[]; event?: NostrEvent }) {
const photos = useMemo(() => {
@ -92,7 +139,9 @@ export function ImageGallery({ images, event }: { images: string[]; event?: Nost
<PhotoGallery
layout="rows"
photos={photos}
renderPhoto={({ photo, imageProps, wrapperStyle }) => <EmbeddedImage {...imageProps} />}
renderPhoto={({ photo, imageProps, wrapperStyle }) => (
<GalleryImage src={imageProps.src} style={imageProps.style} />
)}
targetRowHeight={(containerWidth) => containerWidth / rowMultiplier}
/>
);
@ -164,5 +213,5 @@ export function embedImageGallery(content: EmbedableContent, event?: NostrEvent)
export function renderImageUrl(match: URL) {
if (!isImageURL(match)) return null;
return <EmbeddedImage src={match.toString()} maxH={["initial", "35vh"]} />;
return <EmbeddedImage src={match.toString()} imageProps={{ maxH: ["initial", "35vh"] }} />;
}

View File

@ -6,3 +6,4 @@ export * from "./youtube";
export * from "./nostr";
export * from "./emoji";
export * from "./image";
export * from "./cashu";

View File

@ -5,6 +5,6 @@ export function embedLightningInvoice(content: EmbedableContent) {
return embedJSX(content, {
name: "Lightning Invoice",
regexp: /(lightning:)?(LNBC[A-Za-z0-9]+)/gim,
render: (match) => <InlineInvoiceCard paymentRequest={match[2]} />,
render: (match) => <InlineInvoiceCard paymentRequest={match[2]} zIndex={1} position="relative" />,
});
}

View File

@ -1,5 +1,8 @@
import { CSSProperties } from "react";
import { Box, useColorMode } from "@chakra-ui/react";
const setZIndex: CSSProperties = { zIndex: 1, position: "relative" };
// nostr:nevent1qqsve4ud5v8gjds2f2h7exlmjvhqayu4s520pge7frpwe22wezny0pcpp4mhxue69uhkummn9ekx7mqprdmhxue69uhkvet9v3ejumn0wd68ytnzv9hxgtmdv4kk2mxs3z0
export function renderWavlakeUrl(match: URL) {
if (match.hostname !== "wavlake.com") return null;
@ -13,7 +16,7 @@ export function renderWavlakeUrl(match: URL) {
frameBorder="0"
title="Wavlake Embed"
src={embedUrl.toString()}
style={{ width: "100%", aspectRatio: 576 / 356, maxWidth: 573 }}
style={{ width: "100%", aspectRatio: 576 / 356, maxWidth: 573, ...setZIndex }}
></iframe>
);
}
@ -34,7 +37,7 @@ export function renderAppleMusicUrl(match: URL) {
frameBorder="0"
title={isList ? "Apple Music List Embed" : "Apple Music Embed"}
height={isList ? 450 : 175}
style={{ width: "100%", maxWidth: "660px", overflow: "hidden", background: "transparent" }}
style={{ width: "100%", maxWidth: "660px", overflow: "hidden", background: "transparent", ...setZIndex }}
src={embedUrl.toString()}
></iframe>
);
@ -55,7 +58,7 @@ export function renderSpotifyUrl(match: URL) {
return (
<iframe
style={{ borderRadius: "12px" }}
style={{ borderRadius: "12px", ...setZIndex }}
width="100%"
height={isList ? 400 : 152}
title={isList ? "Spotify List Embed" : "Spotify Embed"}
@ -84,6 +87,7 @@ export function renderTidalUrl(match: URL) {
width="100%"
height={isList ? 400 : 96}
title={isList ? "Tidal List Embed" : "Tidal Embed"}
style={setZIndex}
></iframe>
);
}
@ -102,6 +106,7 @@ export function renderSongDotLinkUrl(match: URL) {
aspectRatio={16 / 10}
src={`https://odesli.co/embed/?url=${encodeURIComponent(match.href)}&theme=${colorMode}`}
sandbox="allow-same-origin allow-scripts allow-presentation allow-popups allow-popups-to-escape-sandbox"
style={setZIndex}
></Box>
);
}

View File

@ -34,7 +34,7 @@ export function renderYoutubeUrl(match: URL) {
embedUrl.searchParams.set("list", listId);
return (
<AspectRatio ratio={560 / 315} maxWidth="40rem">
<AspectRatio ratio={560 / 315} maxWidth="40rem" zIndex={1} position="relative">
<iframe
src={embedUrl.toString()}
title="YouTube video player"
@ -51,7 +51,7 @@ export function renderYoutubeUrl(match: URL) {
const embedUrl = new URL(`/embed/${videoId}`, youtubeRedirect || "https://www.youtube-nocookie.com");
return (
<AspectRatio ratio={16 / 10} maxWidth="40rem">
<AspectRatio ratio={16 / 10} maxWidth="40rem" zIndex={1} position="relative">
<iframe
src={embedUrl.toString()}
title="YouTube video player"

View File

@ -1,5 +1,6 @@
import { Button, ButtonProps, IconButton, Image, useDisclosure } from "@chakra-ui/react";
import { useCallback, useMemo } from "react";
import { Button, ButtonProps, IconButton, Image, useDisclosure } from "@chakra-ui/react";
import { NostrEvent } from "../types/nostr-event";
import useEventReactions from "../hooks/use-event-reactions";
import { DislikeIcon, LikeIcon } from "./icons";

View File

@ -0,0 +1,208 @@
import { useState } from "react";
import {
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
ModalProps,
} from "@chakra-ui/react";
import dayjs from "dayjs";
import { Kind } from "nostr-tools";
import { DraftNostrEvent, NostrEvent, isDTag } from "../../types/nostr-event";
import clientRelaysService from "../../services/client-relays";
import { getEventRelays } from "../../services/event-relays";
import { getZapSplits } from "../../helpers/nostr/zaps";
import { unique } from "../../helpers/array";
import { RelayMode } from "../../classes/relay";
import relayScoreboardService from "../../services/relay-scoreboard";
import { getEventCoordinate, isReplaceable } from "../../helpers/nostr/events";
import { EmbedProps } from "../embed-event";
import userRelaysService from "../../services/user-relays";
import InputStep from "./input-step";
import lnurlMetadataService from "../../services/lnurl-metadata";
import userMetadataService from "../../services/user-metadata";
import signingService from "../../services/signing";
import accountService from "../../services/account";
import PayStep from "./pay-step";
import { getInvoiceFromCallbackUrl } from "../../helpers/lnurl";
export type PayRequest = { invoice?: string; pubkey: string; error?: any };
async function getPayRequestForPubkey(
pubkey: string,
event: NostrEvent | undefined,
amount: number,
comment?: string,
additionalRelays?: string[],
): Promise<PayRequest> {
const metadata = userMetadataService.getSubject(pubkey).value;
const address = metadata?.lud16 || metadata?.lud06;
if (!address) throw new Error("User missing lightning address");
const lnurlMetadata = await lnurlMetadataService.requestMetadata(address);
if (!lnurlMetadata) throw new Error("LNURL endpoint unreachable");
if (amount > lnurlMetadata.maxSendable) throw new Error("Amount to large");
if (amount < lnurlMetadata.minSendable) throw new Error("Amount to small");
const canZap = !!lnurlMetadata.allowsNostr && !!lnurlMetadata.nostrPubkey;
if (!canZap) {
// build LNURL callback url
const callback = new URL(lnurlMetadata.callback);
callback.searchParams.append("amount", String(amount));
if (comment) callback.searchParams.append("comment", comment);
const invoice = await getInvoiceFromCallbackUrl(callback);
return { invoice, pubkey };
}
const userInbox = relayScoreboardService
.getRankedRelays(
userRelaysService
.getRelays(pubkey)
.value?.relays.filter((r) => r.mode & RelayMode.READ)
.map((r) => r.url) ?? [],
)
.slice(0, 4);
const eventRelays = event ? relayScoreboardService.getRankedRelays(getEventRelays(event.id).value).slice(0, 4) : [];
const outbox = relayScoreboardService.getRankedRelays(clientRelaysService.getWriteUrls()).slice(0, 4);
const additional = relayScoreboardService.getRankedRelays(additionalRelays);
// create zap request
const zapRequest: DraftNostrEvent = {
kind: Kind.ZapRequest,
created_at: dayjs().unix(),
content: comment ?? "",
tags: [
["p", pubkey],
["relays", ...unique([...userInbox, ...eventRelays, ...outbox, ...additional])],
["amount", String(amount)],
],
};
// attach "e" or "a" tag
if (event) {
if (isReplaceable(event.kind) && event.tags.some(isDTag)) {
zapRequest.tags.push(["a", getEventCoordinate(event)]);
} else zapRequest.tags.push(["e", event.id]);
}
// TODO: move this out to a separate step so the user can choose when to sign
const account = accountService.current.value;
if (!account) throw new Error("No Account");
const signed = await signingService.requestSignature(zapRequest, account);
// build LNURL callback url
const callback = new URL(lnurlMetadata.callback);
callback.searchParams.append("amount", String(amount));
callback.searchParams.append("nostr", JSON.stringify(signed));
const invoice = await getInvoiceFromCallbackUrl(callback);
return { invoice, pubkey };
}
async function getPayRequestsForEvent(
event: NostrEvent,
amount: number,
comment?: string,
fallbackPubkey?: string,
additionalRelays?: string[],
) {
const splits = getZapSplits(event, fallbackPubkey);
const draftZapRequests: PayRequest[] = [];
for (const { pubkey, percent } of splits) {
try {
// NOTE: round to the nearest sat since there isn't support for msats yet
const splitAmount = Math.round((amount / 1000) * percent) * 1000;
draftZapRequests.push(await getPayRequestForPubkey(pubkey, event, splitAmount, comment, additionalRelays));
} catch (e) {
draftZapRequests.push({ error: e, pubkey });
}
}
return draftZapRequests;
}
export type ZapModalProps = Omit<ModalProps, "children"> & {
pubkey: string;
event?: NostrEvent;
relays?: string[];
initialComment?: string;
initialAmount?: number;
allowComment?: boolean;
showEmbed?: boolean;
embedProps?: EmbedProps;
additionalRelays?: string[];
onZapped: () => void;
};
export default function ZapModal({
event,
pubkey,
relays,
onClose,
initialComment,
initialAmount,
allowComment = true,
showEmbed = true,
embedProps,
additionalRelays = [],
onZapped,
...props
}: ZapModalProps) {
const [callbacks, setCallbacks] = useState<PayRequest[]>();
const renderContent = () => {
if (callbacks && callbacks.length > 0) {
return <PayStep callbacks={callbacks} onComplete={onZapped} />;
} else {
return (
<InputStep
pubkey={pubkey}
event={event}
initialComment={initialComment}
initialAmount={initialAmount}
showEmbed={showEmbed}
embedProps={embedProps}
allowComment={allowComment}
onSubmit={async (values) => {
const amountInMSats = values.amount * 1000;
if (event) {
setCallbacks(
await getPayRequestsForEvent(event, amountInMSats, values.comment, pubkey, additionalRelays),
);
} else {
const callback = await getPayRequestForPubkey(
pubkey,
event,
amountInMSats,
values.comment,
additionalRelays,
);
setCallbacks([callback]);
}
}}
/>
);
}
};
return (
<Modal onClose={onClose} size="xl" {...props}>
<ModalOverlay />
<ModalContent>
<ModalCloseButton />
<ModalHeader px="4" pb="0" pt="4">
Zap Event
</ModalHeader>
<ModalBody padding="4">{renderContent()}</ModalBody>
</ModalContent>
</Modal>
);
}

View File

@ -0,0 +1,119 @@
import { Box, Button, Flex, Input, Text } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
import { NostrEvent } from "../../types/nostr-event";
import { readablizeSats } from "../../helpers/bolt11";
import { LightningIcon } from "../icons";
import useUserLNURLMetadata from "../../hooks/use-user-lnurl-metadata";
import { getZapSplits } from "../../helpers/nostr/zaps";
import { EmbedEvent, EmbedProps } from "../embed-event";
import useAppSettings from "../../hooks/use-app-settings";
import CustomZapAmountOptions from "./zap-options";
import { UserAvatar } from "../user-avatar";
import { UserLink } from "../user-link";
function UserCard({ pubkey, percent }: { pubkey: string; percent?: number }) {
const { address } = useUserLNURLMetadata(pubkey);
return (
<Flex gap="2" alignItems="center" overflow="hidden">
<UserAvatar pubkey={pubkey} size="md" />
<Box overflow="hidden">
<UserLink pubkey={pubkey} fontWeight="bold" />
<Text isTruncated>{address}</Text>
</Box>
{percent && (
<Text fontWeight="bold" fontSize="lg" ml="auto">
{Math.round(percent * 10000) / 100}%
</Text>
)}
</Flex>
);
}
export type InputStepProps = {
pubkey: string;
event?: NostrEvent;
initialComment?: string;
initialAmount?: number;
allowComment?: boolean;
showEmbed?: boolean;
embedProps?: EmbedProps;
onSubmit: (values: { amount: number; comment: string }) => void;
};
export default function InputStep({
event,
pubkey,
initialComment,
initialAmount,
allowComment = true,
showEmbed = true,
embedProps,
onSubmit,
}: InputStepProps) {
const { customZapAmounts } = useAppSettings();
const {
register,
handleSubmit,
watch,
setValue,
formState: { errors, isSubmitting },
} = useForm<{
amount: number;
comment: string;
}>({
mode: "onBlur",
defaultValues: {
amount: initialAmount ?? (parseInt(customZapAmounts.split(",")[0]) || 100),
comment: initialComment ?? "",
},
});
const splits = event ? getZapSplits(event, pubkey) : [];
const { metadata: lnurlMetadata } = useUserLNURLMetadata(pubkey);
const canZap = lnurlMetadata?.allowsNostr && lnurlMetadata?.nostrPubkey;
const showComment = allowComment && (splits.length > 0 || canZap || lnurlMetadata?.commentAllowed);
const actionName = canZap ? "Zap" : "Tip";
const onSubmitZap = handleSubmit(onSubmit);
return (
<form onSubmit={onSubmitZap}>
<Flex gap="4" direction="column">
{splits.map((p) => (
<UserCard key={p.pubkey} pubkey={p.pubkey} percent={p.percent} />
))}
{showEmbed && event && <EmbedEvent event={event} {...embedProps} />}
{showComment && (
<Input
placeholder="Comment"
{...register("comment", { maxLength: lnurlMetadata?.commentAllowed ?? 150 })}
autoComplete="off"
/>
)}
<CustomZapAmountOptions onSelect={(amount) => setValue("amount", amount, { shouldDirty: true })} />
<Flex gap="2">
<Input
type="number"
placeholder="Custom amount"
isInvalid={!!errors.amount}
step={1}
flex={1}
{...register("amount", { valueAsNumber: true, min: 1 })}
/>
<Button leftIcon={<LightningIcon />} type="submit" isLoading={isSubmitting} variant="solid" size="md">
{actionName} {readablizeSats(watch("amount"))} sats
</Button>
</Flex>
</Flex>
</form>
);
}

View File

@ -0,0 +1,149 @@
import { useMount } from "react-use";
import { Alert, Box, Button, ButtonGroup, Flex, IconButton, Spacer, useDisclosure, useToast } from "@chakra-ui/react";
import { PayRequest } from ".";
import { UserAvatar } from "../user-avatar";
import { UserLink } from "../user-link";
import { ChevronDownIcon, ChevronUpIcon, CheckIcon, ErrorIcon, LightningIcon } from "../icons";
import { InvoiceModalContent } from "../invoice-modal";
import { PropsWithChildren, useEffect, useState } from "react";
import appSettings from "../../services/settings/app-settings";
function UserCard({ children, pubkey }: PropsWithChildren & { pubkey: string }) {
return (
<Flex gap="2" alignItems="center" overflow="hidden">
<UserAvatar pubkey={pubkey} size="md" />
<Box>
<UserLink pubkey={pubkey} fontWeight="bold" />
</Box>
<Spacer />
{children}
</Flex>
);
}
function PayRequestCard({ pubkey, invoice, onPaid }: { pubkey: string; invoice: string; onPaid: () => void }) {
const toast = useToast();
const showMore = useDisclosure();
const payWithWebLn = async () => {
try {
if (window.webln && invoice) {
if (!window.webln.enabled) await window.webln.enable();
await window.webln.sendPayment(invoice);
onPaid();
}
} catch (e) {
if (e instanceof Error) toast({ description: e.message, status: "error" });
}
};
return (
<Flex direction="column" gap="2">
<UserCard pubkey={pubkey}>
<ButtonGroup size="sm">
<Button
variant="outline"
colorScheme="yellow"
size="sm"
leftIcon={<LightningIcon />}
isDisabled={!window.webln}
onClick={payWithWebLn}
>
Pay
</Button>
<IconButton
icon={showMore.isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
aria-label="More Options"
onClick={showMore.onToggle}
/>
</ButtonGroup>
</UserCard>
{showMore.isOpen && <InvoiceModalContent invoice={invoice} onPaid={onPaid} />}
</Flex>
);
}
function ErrorCard({ pubkey, error }: { pubkey: string; error: any }) {
const showMore = useDisclosure();
return (
<Flex direction="column" gap="2">
<UserCard pubkey={pubkey}>
<Button size="sm" variant="outline" colorScheme="red" leftIcon={<ErrorIcon />} onClick={showMore.onToggle}>
Error
</Button>
</UserCard>
{showMore.isOpen && <Alert status="error">{error.message}</Alert>}
</Flex>
);
}
export default function PayStep({ callbacks, onComplete }: { callbacks: PayRequest[]; onComplete: () => void }) {
const [paid, setPaid] = useState<string[]>([]);
const [payingAll, setPayingAll] = useState(false);
const payAllWithWebLN = async () => {
if (!window.webln) return;
setPayingAll(true);
if (!window.webln.enabled) await window.webln.enable();
for (const { invoice, pubkey } of callbacks) {
try {
if (invoice && !paid.includes(pubkey)) {
await window.webln.sendPayment(invoice);
setPaid((a) => a.concat(pubkey));
}
} catch (e) {}
}
setPayingAll(false);
};
useEffect(() => {
if (!callbacks.filter((p) => !!p.invoice).some(({ pubkey }) => !paid.includes(pubkey))) {
onComplete();
}
}, [paid]);
// if autoPayWithWebLN is enabled, try to pay all immediately
useMount(() => {
if (appSettings.value.autoPayWithWebLN) {
payAllWithWebLN();
}
});
return (
<Flex direction="column" gap="4">
{callbacks.map(({ pubkey, invoice, error }) => {
if (paid.includes(pubkey))
return (
<UserCard key={pubkey} pubkey={pubkey}>
<Button size="sm" variant="outline" colorScheme="green" leftIcon={<CheckIcon />}>
Paid
</Button>
</UserCard>
);
if (error) return <ErrorCard key={pubkey} pubkey={pubkey} error={error} />;
if (invoice)
return (
<PayRequestCard
key={pubkey}
pubkey={pubkey}
invoice={invoice}
onPaid={() => setPaid((a) => a.concat(pubkey))}
/>
);
return null;
})}
<Button
variant="outline"
size="md"
leftIcon={<LightningIcon />}
colorScheme="yellow"
onClick={payAllWithWebLN}
isLoading={payingAll}
>
Pay All
</Button>
</Flex>
);
}

View File

@ -0,0 +1,27 @@
import { Button, Flex } from "@chakra-ui/react";
import useAppSettings from "../../hooks/use-app-settings";
import { LightningIcon } from "../icons";
export default function CustomZapAmountOptions({ onSelect }: { onSelect: (value: number) => void }) {
const { customZapAmounts } = useAppSettings();
return (
<Flex gap="2" alignItems="center" wrap="wrap">
{customZapAmounts
.split(",")
.map((v) => parseInt(v))
.map((amount, i) => (
<Button
key={amount + i}
onClick={() => onSelect(amount)}
leftIcon={<LightningIcon />}
variant="solid"
size="sm"
>
{amount}
</Button>
))}
</Flex>
);
}

View File

@ -0,0 +1,10 @@
import { LinkOverlay } from "@chakra-ui/react";
import styled from "@emotion/styled";
const HoverLinkOverlay = styled(LinkOverlay)`
&:hover:before {
background-color: var(--chakra-colors-card-hover-overlay);
}
`;
export default HoverLinkOverlay;

View File

@ -1,138 +1,101 @@
import { createIcon, IconProps } from "@chakra-ui/icons";
const defaultProps: IconProps = { fontSize: "1.2em" };
import SearchMd from "./icons/search-md";
import Settings02 from "./icons/settings-02";
import Mail01 from "./icons/mail-01";
import BookmarkCheck from "./icons/bookmark-check";
import StickerSquare from "./icons/sticker-square";
import Code01 from "./icons/code-01";
import DistributeSpacingVertical from "./icons/distribute-spacing-vertical";
import Grid01 from "./icons/grid-01";
import Microscope from "./icons/microscope";
import Server04 from "./icons/server-04";
import ChevronDown from "./icons/chevron-down";
import ChevronUp from "./icons/chevron-up";
import ChevronLeft from "./icons/chevron-left";
import ChevronRight from "./icons/chevron-right";
import Zap from "./icons/zap";
import Target04 from "./icons/target-04";
import Award01 from "./icons/award-01";
import LayoutRight from "./icons/layout-right";
import ThumbsUp from "./icons/thumbs-up";
import ThumbsDown from "./icons/thumbs-down";
import LogOut01 from "./icons/log-out-01";
import Tool02 from "./icons/tool-02";
import ImagePlus from "./icons/image-plus";
import LockUnlocked01 from "./icons/lock-unlocked-01";
import PencilLine from "./icons/pencil-line";
import Share07 from "./icons/share-07";
import Copy01 from "./icons/copy-01";
import Trash01 from "./icons/trash-01";
import Share04 from "./icons/share-04";
import FaceSmile from "./icons/face-smile";
import Eye from "./icons/eye";
import EyeOff from "./icons/eye-off";
import Colors from "./icons/colors";
import Database01 from "./icons/database-01";
import Speedometer03 from "./icons/speedometer-03";
import UserCircle from "./icons/user-circle";
import DotsHorizontal from "./icons/dots-horizontal";
import MessageCircle01 from "./icons/message-circle-01";
import Feather from "./icons/feather";
import List from "./icons/list";
import VideoRecorder from "./icons/video-recorder";
import Map01 from "./icons/map-01";
import PlayCircle from "./icons/play-circle";
import StopCircle from "./icons/stop-circle";
import CheckVerified01 from "./icons/check-verified-01";
import AlertOctagon from "./icons/alert-octagon";
import AlertTriangle from "./icons/alert-triangle";
import Key01 from "./icons/key-01";
import Check from "./icons/check";
import Bell01 from "./icons/bell-01";
import QrCode02 from "./icons/qr-code-02";
import PlusCircle from "./icons/plus-circle";
import AtSign from "./icons/at-sign";
import UserPlus01 from "./icons/user-plus-01";
import UserX01 from "./icons/user-x-01";
import Plus from "./icons/plus";
import Bookmark from "./icons/bookmark";
import BankNote01 from "./icons/bank-note-01";
import Wallet02 from "./icons/wallet-02";
import Download01 from "./icons/download-01";
export const GlobalIcon = createIcon({
displayName: "global-icon",
d: "M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z",
defaultProps,
});
const defaultProps: IconProps = { boxSize: 4 };
export const HomeIcon = createIcon({
displayName: "HomeIcon",
d: "M19 21H5a1 1 0 0 1-1-1v-9H1l10.327-9.388a1 1 0 0 1 1.346 0L23 11h-3v9a1 1 0 0 1-1 1zM6 19h12V9.157l-6-5.454-6 5.454V19z",
defaultProps,
});
export const NotesIcon = StickerSquare;
export const FeedIcon = createIcon({
displayName: "FeedIcon",
d: "M16 18v2H5v-2h11zm5-7v2H3v-2h18zm-2-7v2H8V4h11z",
defaultProps,
});
export const NoteFeedIcon = DistributeSpacingVertical;
export const MoreIcon = createIcon({
displayName: "MoreIcon",
d: "M4.5 10.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S6 12.825 6 12s-.675-1.5-1.5-1.5zm15 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S21 12.825 21 12s-.675-1.5-1.5-1.5zm-7.5 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z",
defaultProps,
});
export const MoreIcon = DotsHorizontal;
export const CodeIcon = createIcon({
displayName: "CodeIcon",
d: `M23 12l-7.071 7.071-1.414-1.414L20.172 12l-5.657-5.657 1.414-1.414L23 12zM3.828 12l5.657 5.657-1.414 1.414L1 12l7.071-7.071 1.414 1.414L3.828 12z`,
defaultProps,
});
export const CodeIcon = Code01;
export const SettingsIcon = createIcon({
displayName: "SettingsIcon",
d: "M8.686 4l2.607-2.607a1 1 0 0 1 1.414 0L15.314 4H19a1 1 0 0 1 1 1v3.686l2.607 2.607a1 1 0 0 1 0 1.414L20 15.314V19a1 1 0 0 1-1 1h-3.686l-2.607 2.607a1 1 0 0 1-1.414 0L8.686 20H5a1 1 0 0 1-1-1v-3.686l-2.607-2.607a1 1 0 0 1 0-1.414L4 8.686V5a1 1 0 0 1 1-1h3.686zM6 6v3.515L3.515 12 6 14.485V18h3.515L12 20.485 14.485 18H18v-3.515L20.485 12 18 9.515V6h-3.515L12 3.515 9.515 6H6zm6 10a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm0-2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z",
defaultProps,
});
export const SettingsIcon = Settings02;
export const LogoutIcon = LogOut01;
export const ProfileIcon = UserCircle;
export const LogoutIcon = createIcon({
displayName: "LogoutIcon",
d: "M4 18h2v2h12V4H6v2H4V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3zm2-7h7v2H6v3l-5-4 5-4v3z",
defaultProps,
});
export const CopyToClipboardIcon = Copy01;
export const ProfileIcon = createIcon({
displayName: "ProfileIcon",
d: "M4 22a8 8 0 1 1 16 0h-2a6 6 0 1 0-12 0H4zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm0-2c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4z",
defaultProps,
});
export const TrashIcon = Trash01;
export const ClipboardIcon = createIcon({
displayName: "ClipboardIcon",
d: "M7 4V2h10v2h3.007c.548 0 .993.445.993.993v16.014a.994.994 0 0 1-.993.993H3.993A.994.994 0 0 1 3 21.007V4.993C3 4.445 3.445 4 3.993 4H7zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z",
defaultProps,
});
export const AddIcon = Plus;
export const TrashIcon = createIcon({
displayName: "TrashIcon",
d: "M17 6h5v2h-2v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V8H2V6h5V3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v3zm1 2H6v12h12V8zm-9 3h2v6H9v-6zm4 0h2v6h-2v-6zM9 4v2h6V4H9z",
defaultProps,
});
export const ChevronDownIcon = ChevronDown;
export const ChevronUpIcon = ChevronUp;
export const ChevronLeftIcon = ChevronLeft;
export const ChevronRightIcon = ChevronRight;
export const AddIcon = createIcon({
displayName: "AddIcon",
d: "M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z",
defaultProps,
});
export const LightningIcon = Zap;
export const RelayIcon = Server04;
export const BroadcastEventIcon = Share07;
export const ArrowDownSIcon = createIcon({
displayName: "ArrowDownSIcon",
d: "M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z",
defaultProps,
});
export const ExternalLinkIcon = Share04;
export const ArrowUpSIcon = createIcon({
displayName: "ArrowUpSIcon",
d: "M12 10.828l-4.95 4.95-1.414-1.414L12 8l6.364 6.364-1.414 1.414z",
defaultProps,
});
export const SearchIcon = SearchMd;
export const RepostIcon = Share07;
export const ArrowLeftSIcon = createIcon({
displayName: "ArrowLeftSIcon",
d: "M10.828 12l4.95 4.95-1.414 1.414L8 12l6.364-6.364 1.414 1.414z",
defaultProps,
});
export const ArrowRightSIcon = createIcon({
displayName: "ArrowRightSIcon",
d: "M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z",
defaultProps,
});
export const LinkItem = createIcon({
displayName: "LinkItem",
d: "M18.364 15.536L16.95 14.12l1.414-1.414a5 5 0 1 0-7.071-7.071L9.879 7.05 8.464 5.636 9.88 4.222a7 7 0 0 1 9.9 9.9l-1.415 1.414zm-2.828 2.828l-1.415 1.414a7 7 0 0 1-9.9-9.9l1.415-1.414L7.05 9.88l-1.414 1.414a5 5 0 1 0 7.071 7.071l1.414-1.414 1.415 1.414zm-.708-10.607l1.415 1.415-7.071 7.07-1.415-1.414 7.071-7.07z",
defaultProps,
});
export const LightningIcon = createIcon({
displayName: "LightningIcon",
d: "M13 10h7l-9 13v-9H4l9-13z",
defaultProps: { ...defaultProps, color: "yellow.400" },
});
export const RelayIcon = createIcon({
displayName: "RelayIcon",
d: "M11 14v-3h2v3h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h5zM2.51 8.837C3.835 4.864 7.584 2 12 2s8.166 2.864 9.49 6.837l-1.898.632a8.003 8.003 0 0 0-15.184 0l-1.897-.632zm3.796 1.265a6.003 6.003 0 0 1 11.388 0l-1.898.633a4.002 4.002 0 0 0-7.592 0l-1.898-.633z",
defaultProps,
});
export const ExternalLinkIcon = createIcon({
displayName: "ExternalLinkIcon",
d: "M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z",
defaultProps,
});
export const SearchIcon = createIcon({
displayName: "SearchIcon",
d: "M18.031 16.617l4.283 4.282-1.415 1.415-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9 9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617zm-2.006-.742A6.977 6.977 0 0 0 18 11c0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7a6.977 6.977 0 0 0 4.875-1.975l.15-.15z",
defaultProps,
});
export const RepostIcon = createIcon({
displayName: "RepostIcon",
d: "M13.12 17.023l-4.199-2.29a4 4 0 1 1 0-5.465l4.2-2.29a4 4 0 1 1 .959 1.755l-4.2 2.29a4.008 4.008 0 0 1 0 1.954l4.199 2.29a4 4 0 1 1-.959 1.755zM6 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm11-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 12a2 2 0 1 0 0-4 2 2 0 0 0 0 4z",
defaultProps,
});
export const ReplyIcon = createIcon({
displayName: "ReplyIcon",
d: "M11 20L1 12L11 4V9C16.5228 9 21 13.4772 21 19C21 19.2727 20.9891 19.5428 20.9677 19.81C19.5055 17.0364 16.6381 15.119 13.313 15.0053L13 15H10.9999L11 20ZM8.99986 13H10.9999L13.0341 13.0003L13.3814 13.0065C14.6657 13.0504 15.9053 13.3165 17.0568 13.7734C15.5898 12.0749 13.4204 11 11 11H9V8.16125L4.20156 12L8.99992 15.8387L8.99986 13Z",
defaultProps,
});
export const ReplyIcon = MessageCircle01;
export const QuoteRepostIcon = createIcon({
displayName: "QuoteRepostIcon",
@ -140,17 +103,8 @@ export const QuoteRepostIcon = createIcon({
defaultProps,
});
export const VerifiedIcon = createIcon({
displayName: "VerifiedIcon",
d: "M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-.997-6l7.07-7.071-1.414-1.414-5.656 5.657-2.829-2.829-1.414 1.414L11.003 16z",
defaultProps,
});
export const VerificationFailed = createIcon({
displayName: "VerificationFailed",
d: "M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z",
defaultProps,
});
export const VerifiedIcon = CheckVerified01;
export const VerificationFailed = AlertOctagon;
export const VerificationMissing = createIcon({
displayName: "VerificationFailed",
@ -164,77 +118,22 @@ export const SpyIcon = createIcon({
defaultProps,
});
export const KeyIcon = createIcon({
displayName: "KeyIcon",
d: "M10.758 11.828l7.849-7.849 1.414 1.414-1.414 1.415 2.474 2.474-1.414 1.415-2.475-2.475-1.414 1.414 2.121 2.121-1.414 1.415-2.121-2.122-2.192 2.192a5.002 5.002 0 0 1-7.708 6.294 5 5 0 0 1 6.294-7.708zm-.637 6.293A3 3 0 1 0 5.88 13.88a3 3 0 0 0 4.242 4.242z",
defaultProps,
});
export const KeyIcon = Key01;
export const CheckIcon = Check;
export const CheckIcon = createIcon({
displayName: "CheckIcon",
d: "M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z",
defaultProps,
});
export const NotificationsIcon = Bell01;
export const NotificationIcon = createIcon({
displayName: "NotificationIcon",
d: "M5 18h14v-6.969C19 7.148 15.866 4 12 4s-7 3.148-7 7.031V18zm7-16c4.97 0 9 4.043 9 9.031V20H3v-8.969C3 6.043 7.03 2 12 2zM9.5 21h5a2.5 2.5 0 1 1-5 0z",
defaultProps,
});
export const LikeIcon = ThumbsUp;
export const DislikeIcon = ThumbsDown;
export const UndoIcon = createIcon({
displayName: "UndoIcon",
d: "M5.828 7l2.536 2.536L6.95 10.95 2 6l4.95-4.95 1.414 1.414L5.828 5H13a8 8 0 1 1 0 16H4v-2h9a6 6 0 1 0 0-12H5.828z",
defaultProps,
});
export const QrCodeIcon = QrCode02;
export const LikeIcon = createIcon({
displayName: "LikeIcon",
d: "M14.6 8H21a2 2 0 0 1 2 2v2.104a2 2 0 0 1-.15.762l-3.095 7.515a1 1 0 0 1-.925.619H2a1 1 0 0 1-1-1V10a1 1 0 0 1 1-1h3.482a1 1 0 0 0 .817-.423L11.752.85a.5.5 0 0 1 .632-.159l1.814.907a2.5 2.5 0 0 1 1.305 2.853L14.6 8zM7 10.588V19h11.16L21 12.104V10h-6.4a2 2 0 0 1-1.938-2.493l.903-3.548a.5.5 0 0 0-.261-.571l-.661-.33-4.71 6.672c-.25.354-.57.644-.933.858zM5 11H3v8h2v-8z",
defaultProps,
});
export const DirectMessagesIcon = Mail01;
export const DislikeIcon = createIcon({
displayName: "DislikeIcon",
d: "M9.4 16H3a2 2 0 0 1-2-2v-2.104a2 2 0 0 1 .15-.762L4.246 3.62A1 1 0 0 1 5.17 3H22a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-3.482a1 1 0 0 0-.817.423l-5.453 7.726a.5.5 0 0 1-.632.159L9.802 22.4a2.5 2.5 0 0 1-1.305-2.853L9.4 16zm7.6-2.588V5H5.84L3 11.896V14h6.4a2 2 0 0 1 1.938 2.493l-.903 3.548a.5.5 0 0 0 .261.571l.661.33 4.71-6.672c.25-.354.57-.644.933-.858zM19 13h2V5h-2v8z",
defaultProps,
});
export const UnlockIcon = LockUnlocked01;
export const UploadImageIcon = ImagePlus;
export const QrCodeIcon = createIcon({
displayName: "QrCodeIcon",
d: "M16 17v-1h-3v-3h3v2h2v2h-1v2h-2v2h-2v-3h2v-1h1zm5 4h-4v-2h2v-2h2v4zM3 3h8v8H3V3zm2 2v4h4V5H5zm8-2h8v8h-8V3zm2 2v4h4V5h-4zM3 13h8v8H3v-8zm2 2v4h4v-4H5zm13-2h3v2h-3v-2zM6 6h2v2H6V6zm0 10h2v2H6v-2zM16 6h2v2h-2V6z",
defaultProps,
});
export const MessagesIcon = createIcon({
displayName: "ChatIcon",
d: "M3 3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3ZM20 7.23792L12.0718 14.338L4 7.21594V19H20V7.23792ZM4.51146 5L12.0619 11.662L19.501 5H4.51146Z",
defaultProps,
});
export const UnlockIcon = createIcon({
displayName: "UnlockIcon",
d: "M7 10h13a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V11a1 1 0 0 1 1-1h1V9a7 7 0 0 1 13.262-3.131l-1.789.894A5 5 0 0 0 7 9v1zm-2 2v8h14v-8H5zm5 3h4v2h-4v-2z",
defaultProps,
});
export const ImageIcon = createIcon({
displayName: "ImageIcon",
d: "M4.828 21l-.02.02-.021-.02H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H4.828zM20 15V5H4v14L14 9l6 6zm0 2.828l-6-6L6.828 19H20v-1.172zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z",
defaultProps,
});
export const CameraIcon = createIcon({
displayName: "CameraIcon",
d: "M9.828 5l-2 2H4v12h16V7h-3.828l-2-2H9.828zM9 3h6l2 2h4a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h4l2-2zm3 15a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-2a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z",
defaultProps,
});
export const PlusCircleIcon = createIcon({
displayName: "PlusCircleIcon",
d: "M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z",
defaultProps,
});
export const PlusCircleIcon = PlusCircle;
export const GithubIcon = createIcon({
displayName: "GithubIcon",
@ -242,200 +141,90 @@ export const GithubIcon = createIcon({
defaultProps,
});
export const ToolsIcon = createIcon({
displayName: "ToolsIcon",
d: "M5.32894 3.27158C6.56203 2.8332 7.99181 3.10749 8.97878 4.09446C10.0997 5.21537 10.3014 6.90741 9.58382 8.23385L20.2925 18.9437L18.8783 20.3579L8.16933 9.64875C6.84277 10.3669 5.1502 10.1654 4.02903 9.04421C3.04178 8.05696 2.76761 6.62665 3.20652 5.39332L5.44325 7.63C6.02903 8.21578 6.97878 8.21578 7.56457 7.63C8.15035 7.04421 8.15035 6.09446 7.56457 5.50868L5.32894 3.27158ZM15.6963 5.15512L18.8783 3.38736L20.2925 4.80157L18.5247 7.98355L16.757 8.3371L14.6356 10.4584L13.2214 9.04421L15.3427 6.92289L15.6963 5.15512ZM8.97878 13.2868L10.393 14.7011L5.08969 20.0044C4.69917 20.3949 4.066 20.3949 3.67548 20.0044C3.31285 19.6417 3.28695 19.0699 3.59777 18.6774L3.67548 18.5902L8.97878 13.2868Z",
defaultProps,
});
export const ToolsIcon = Tool02;
export const EditIcon = createIcon({
displayName: "EditIcon",
d: "M6.41421 15.89L16.5563 5.74786L15.1421 4.33365L5 14.4758V15.89H6.41421ZM7.24264 17.89H3V13.6474L14.435 2.21233C14.8256 1.8218 15.4587 1.8218 15.8492 2.21233L18.6777 5.04075C19.0682 5.43128 19.0682 6.06444 18.6777 6.45497L7.24264 17.89ZM3 19.89H21V21.89H3V19.89Z",
defaultProps,
});
export const EditIcon = PencilLine;
export const WritingIcon = createIcon({
displayName: "WritingIcon",
d: "M6.93912 14.0327C6.7072 14.6562 6.51032 15.233 6.33421 15.8154C7.29345 15.1188 8.43544 14.6766 9.75193 14.512C12.2652 14.1979 14.4976 12.5384 15.6279 10.4535L14.1721 8.99878L15.5848 7.58407C15.9185 7.24993 16.2521 6.91603 16.5858 6.58237C17.0151 6.15301 17.5 5.35838 18.0129 4.21479C12.4197 5.08172 8.99484 8.50636 6.93912 14.0327ZM17 8.99728L18 9.99658C17 12.9966 14 15.9966 10 16.4966C7.33146 16.8301 5.66421 18.6635 4.99824 21.9966H3C4 15.9966 6 1.99658 21 1.99658C20.0009 4.99392 19.0018 6.99303 18.0027 7.99391C17.6662 8.33038 17.3331 8.66372 17 8.99728Z",
defaultProps,
});
export const WritingIcon = Feather;
export const AtIcon = createIcon({
displayName: "AtIcon",
d: "M20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C13.6418 20 15.1681 19.5054 16.4381 18.6571L17.5476 20.3214C15.9602 21.3818 14.0523 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12V13.5C22 15.433 20.433 17 18.5 17C17.2958 17 16.2336 16.3918 15.6038 15.4659C14.6942 16.4115 13.4158 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C13.1258 7 14.1647 7.37209 15.0005 8H17V13.5C17 14.3284 17.6716 15 18.5 15C19.3284 15 20 14.3284 20 13.5V12ZM12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9Z",
defaultProps,
});
export const AtIcon = AtSign;
export const FollowingIcon = createIcon({
displayName: "FollowingIcon",
d: "M14 14.252V16.3414C13.3744 16.1203 12.7013 16 12 16C8.68629 16 6 18.6863 6 22H4C4 17.5817 7.58172 14 12 14C12.6906 14 13.3608 14.0875 14 14.252ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11ZM17.7929 19.9142L21.3284 16.3787L22.7426 17.7929L17.7929 22.7426L14.2574 19.2071L15.6716 17.7929L17.7929 19.9142Z",
defaultProps,
});
export const FollowIcon = UserPlus01;
export const UnfollowIcon = UserX01;
export const FollowIcon = createIcon({
displayName: "FollowIcon",
d: "M14 14.252V16.3414C13.3744 16.1203 12.7013 16 12 16C8.68629 16 6 18.6863 6 22H4C4 17.5817 7.58172 14 12 14C12.6906 14 13.3608 14.0875 14 14.252ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11ZM18 17V14H20V17H23V19H20V22H18V19H15V17H18Z",
defaultProps,
});
export const ListsIcon = List;
export const LiveStreamIcon = VideoRecorder;
export const UnfollowIcon = createIcon({
displayName: "UnfollowIcon",
d: "M14 14.252V16.3414C13.3744 16.1203 12.7013 16 12 16C8.68629 16 6 18.6863 6 22H4C4 17.5817 7.58172 14 12 14C12.6906 14 13.3608 14.0875 14 14.252ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11ZM19 17.5858L21.1213 15.4645L22.5355 16.8787L20.4142 19L22.5355 21.1213L21.1213 22.5355L19 20.4142L16.8787 22.5355L15.4645 21.1213L17.5858 19L15.4645 16.8787L16.8787 15.4645L19 17.5858Z",
defaultProps,
});
export const ImageGridTimelineIcon = Grid01;
export const ListIcon = createIcon({
displayName: "ListIcon",
d: "M8 4H21V6H8V4ZM3 3.5H6V6.5H3V3.5ZM3 10.5H6V13.5H3V10.5ZM3 17.5H6V20.5H3V17.5ZM8 11H21V13H8V11ZM8 18H21V20H8V18Z",
defaultProps,
});
export const TimelineHealthIcon = Microscope;
export const LiveStreamIcon = createIcon({
displayName: "LiveStreamIcon",
d: "M16 4C16.5523 4 17 4.44772 17 5V9.2L22.2133 5.55071C22.4395 5.39235 22.7513 5.44737 22.9096 5.6736C22.9684 5.75764 23 5.85774 23 5.96033V18.0397C23 18.3158 22.7761 18.5397 22.5 18.5397C22.3974 18.5397 22.2973 18.5081 22.2133 18.4493L17 14.8V19C17 19.5523 16.5523 20 16 20H2C1.44772 20 1 19.5523 1 19V5C1 4.44772 1.44772 4 2 4H16ZM15 6H3V18H15V6ZM7.4 8.82867C7.47607 8.82867 7.55057 8.85036 7.61475 8.8912L11.9697 11.6625C12.1561 11.7811 12.211 12.0284 12.0924 12.2148C12.061 12.2641 12.0191 12.306 11.9697 12.3375L7.61475 15.1088C7.42837 15.2274 7.18114 15.1725 7.06254 14.9861C7.02169 14.9219 7 14.8474 7 14.7713V9.22867C7 9.00776 7.17909 8.82867 7.4 8.82867ZM21 8.84131L17 11.641V12.359L21 15.1587V8.84131Z",
defaultProps,
});
export const ImageGridTimelineIcon = createIcon({
displayName: "ImageGridTimelineIcon",
d: "M21 3C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H21ZM11 13H4V19H11V13ZM20 13H13V19H20V13ZM11 5H4V11H11V5ZM20 5H13V11H20V5Z",
defaultProps,
});
export const TextTimelineIcon = createIcon({
displayName: "TextTimelineIcon",
d: "M8 4H21V6H8V4ZM4.5 6.5C3.67157 6.5 3 5.82843 3 5C3 4.17157 3.67157 3.5 4.5 3.5C5.32843 3.5 6 4.17157 6 5C6 5.82843 5.32843 6.5 4.5 6.5ZM4.5 13.5C3.67157 13.5 3 12.8284 3 12C3 11.1716 3.67157 10.5 4.5 10.5C5.32843 10.5 6 11.1716 6 12C6 12.8284 5.32843 13.5 4.5 13.5ZM4.5 20.4C3.67157 20.4 3 19.7284 3 18.9C3 18.0716 3.67157 17.4 4.5 17.4C5.32843 17.4 6 18.0716 6 18.9C6 19.7284 5.32843 20.4 4.5 20.4ZM8 11H21V13H8V11ZM8 18H21V20H8V18Z",
defaultProps,
});
export const TimelineHealthIcon = createIcon({
displayName: "TimelineHealthIcon",
d: "M13.1962 2.26791L16.4462 7.89708C16.7223 8.37537 16.5584 8.98696 16.0801 9.2631L14.7806 10.0122L15.7811 11.7452L14.049 12.7452L13.0485 11.0122L11.75 11.7631C11.2717 12.0392 10.6601 11.8754 10.384 11.3971L8.5462 8.2146C6.49383 8.8373 5 10.7442 5 13C5 13.6253 5.1148 14.2238 5.32447 14.7756C6.0992 14.284 7.01643 14 8 14C9.68408 14 11.1737 14.8326 12.0797 16.1086L19.7681 11.6704L20.7681 13.4024L12.8898 17.9509C12.962 18.2892 13 18.6401 13 19C13 19.3427 12.9655 19.6773 12.8999 20.0006L21 20V22L4.00054 22.0012C3.3723 21.1653 3 20.1261 3 19C3 17.9927 3.29782 17.0551 3.81021 16.2702C3.29276 15.2948 3 14.1816 3 13C3 10.0047 4.88131 7.44875 7.52677 6.44942L7.13397 5.76791C6.58169 4.81133 6.90944 3.58815 7.86603 3.03586L10.4641 1.53586C11.4207 0.983577 12.6439 1.31133 13.1962 2.26791ZM8 16C6.34315 16 5 17.3431 5 19C5 19.3506 5.06014 19.6871 5.17067 19.9999H10.8293C10.9399 19.6871 11 19.3506 11 19C11 17.3431 9.65685 16 8 16ZM11.4641 3.26791L8.86602 4.76791L11.616 9.53105L14.2141 8.03105L11.4641 3.26791Z",
defaultProps,
});
export const MapIcon = createIcon({
displayName: "MapIcon",
d: "M4 6.14286V18.9669L9.06476 16.7963L15.0648 19.7963L20 17.6812V4.85714L21.303 4.2987C21.5569 4.18992 21.8508 4.30749 21.9596 4.56131C21.9862 4.62355 22 4.69056 22 4.75827V19L15 22L9 19L2.69696 21.7013C2.44314 21.8101 2.14921 21.6925 2.04043 21.4387C2.01375 21.3765 2 21.3094 2 21.2417V7L4 6.14286ZM16.2426 11.2426L12 15.4853L7.75736 11.2426C5.41421 8.89949 5.41421 5.10051 7.75736 2.75736C10.1005 0.414214 13.8995 0.414214 16.2426 2.75736C18.5858 5.10051 18.5858 8.89949 16.2426 11.2426ZM12 12.6569L14.8284 9.82843C16.3905 8.26633 16.3905 5.73367 14.8284 4.17157C13.2663 2.60948 10.7337 2.60948 9.17157 4.17157C7.60948 5.73367 7.60948 8.26633 9.17157 9.82843L12 12.6569Z",
defaultProps,
});
export const MapIcon = Map01;
export const StarEmptyIcon = createIcon({
displayName: "StarEmptyIcon",
d: "M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26ZM12.0006 15.968L16.2473 18.3451L15.2988 13.5717L18.8719 10.2674L14.039 9.69434L12.0006 5.27502L9.96214 9.69434L5.12921 10.2674L8.70231 13.5717L7.75383 18.3451L12.0006 15.968Z",
defaultProps,
});
export const StarFullIcon = createIcon({
displayName: "StarFullIcon",
d: "M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z",
defaultProps,
});
export const StarHalfIcon = createIcon({
displayName: "StarHalfIcon",
d: "M12.0006 15.968L16.2473 18.3451L15.2988 13.5717L18.8719 10.2674L14.039 9.69434L12.0006 5.27502V15.968ZM12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z",
defaultProps,
});
export const ErrorIcon = createIcon({
displayName: "ErrorIcon",
d: "M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 15H13V17H11V15ZM11 7H13V13H11V7Z",
defaultProps,
});
export const ErrorIcon = AlertTriangle;
export const BookmarkIcon = createIcon({
displayName: "BookmarkIcon",
d: "M5 2H19C19.5523 2 20 2.44772 20 3V22.1433C20 22.4194 19.7761 22.6434 19.5 22.6434C19.4061 22.6434 19.314 22.6168 19.2344 22.5669L12 18.0313L4.76559 22.5669C4.53163 22.7136 4.22306 22.6429 4.07637 22.4089C4.02647 22.3293 4 22.2373 4 22.1433V3C4 2.44772 4.44772 2 5 2ZM18 4H6V19.4324L12 15.6707L18 19.4324V4Z",
defaultProps,
});
export const BookmarkIcon = Bookmark;
// TODO: switch to untitled UI solid icon
export const BookmarkedIcon = createIcon({
displayName: "BookmaredkIcon",
displayName: "BookmarkedIcon",
d: "M4 2H20C20.5523 2 21 2.44772 21 3V22.2763C21 22.5525 20.7761 22.7764 20.5 22.7764C20.4298 22.7764 20.3604 22.7615 20.2963 22.7329L12 19.0313L3.70373 22.7329C3.45155 22.8455 3.15591 22.7322 3.04339 22.4801C3.01478 22.4159 3 22.3465 3 22.2763V3C3 2.44772 3.44772 2 4 2ZM12 13.5L14.9389 15.0451L14.3776 11.7725L16.7553 9.45492L13.4695 8.97746L12 6L10.5305 8.97746L7.24472 9.45492L9.62236 11.7725L9.06107 15.0451L12 13.5Z",
defaultProps,
});
export const PlayIcon = createIcon({
displayName: "PlayIcon",
d: "M16.3944 11.9998L10 7.73686V16.2628L16.3944 11.9998ZM19.376 12.4158L8.77735 19.4816C8.54759 19.6348 8.23715 19.5727 8.08397 19.3429C8.02922 19.2608 8 19.1643 8 19.0656V4.93408C8 4.65794 8.22386 4.43408 8.5 4.43408C8.59871 4.43408 8.69522 4.4633 8.77735 4.51806L19.376 11.5838C19.6057 11.737 19.6678 12.0474 19.5146 12.2772C19.478 12.3321 19.4309 12.3792 19.376 12.4158Z",
defaultProps,
});
export const StopIcon = createIcon({
displayName: "StopIcon",
d: "M7 7V17H17V7H7ZM6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H6C5.44772 19 5 18.5523 5 18V6C5 5.44772 5.44772 5 6 5Z",
defaultProps,
});
export const V4VStreamIcon = PlayCircle;
export const V4VStopIcon = StopCircle;
/** @deprecated */
export const AddReactionIcon = createIcon({
displayName: "AddReactionIcon",
d: "M19.0001 13.9999V16.9999H22.0001V18.9999H18.9991L19.0001 21.9999H17.0001L16.9991 18.9999H14.0001V16.9999H17.0001V13.9999H19.0001ZM20.2426 4.75736C22.505 7.0244 22.5829 10.636 20.4795 12.992L19.06 11.574C20.3901 10.0499 20.3201 7.65987 18.827 6.1701C17.3244 4.67092 14.9076 4.60701 13.337 6.01688L12.0019 7.21524L10.6661 6.01781C9.09098 4.60597 6.67506 4.66808 5.17157 6.17157C3.68183 7.66131 3.60704 10.0473 4.97993 11.6232L13.412 20.069L11.9999 21.485L3.52138 12.993C1.41705 10.637 1.49571 7.01901 3.75736 4.75736C6.02157 2.49315 9.64519 2.41687 12.001 4.52853C14.35 2.42 17.98 2.49 20.2426 4.75736Z",
defaultProps,
});
export const EmojiIcon = createIcon({
displayName: "EmojiIcon",
d: "M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM7 12H9C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12H17C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12Z",
defaultProps,
});
export const EmojiPacksIcon = FaceSmile;
export const GoalIcon = Target04;
export const BadgeIcon = Award01;
export const GoalIcon = createIcon({
displayName: "GoalIcon",
d: "M5 3V19H21V21H3V3H5ZM20.2929 6.29289L21.7071 7.70711L16 13.4142L13 10.415L8.70711 14.7071L7.29289 13.2929L13 7.58579L16 10.585L20.2929 6.29289Z",
defaultProps,
});
export const DrawerIcon = LayoutRight;
export const BadgeIcon = createIcon({
displayName: "BadgeIcon",
d: "M17 15.2454V22.1169C17 22.393 16.7761 22.617 16.5 22.617C16.4094 22.617 16.3205 22.5923 16.2428 22.5457L12 20L7.75725 22.5457C7.52046 22.6877 7.21333 22.6109 7.07125 22.3742C7.02463 22.2964 7 22.2075 7 22.1169V15.2454C5.17107 13.7793 4 11.5264 4 9C4 4.58172 7.58172 1 12 1C16.4183 1 20 4.58172 20 9C20 11.5264 18.8289 13.7793 17 15.2454ZM9 16.4185V19.4676L12 17.6676L15 19.4676V16.4185C14.0736 16.7935 13.0609 17 12 17C10.9391 17 9.92643 16.7935 9 16.4185ZM12 15C15.3137 15 18 12.3137 18 9C18 5.68629 15.3137 3 12 3C8.68629 3 6 5.68629 6 9C6 12.3137 8.68629 15 12 15Z",
defaultProps,
});
export const UnmuteIcon = Eye;
export const MuteIcon = EyeOff;
export const DrawerIcon = createIcon({
displayName: "DrawerIcon",
d: "M3 3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3ZM8 5H4V19H8V5ZM10 5V19H20V5H10Z",
defaultProps,
});
export const UnmuteIcon = createIcon({
displayName: "UnmuteIcon",
d: "M12.0003 3C17.3924 3 21.8784 6.87976 22.8189 12C21.8784 17.1202 17.3924 21 12.0003 21C6.60812 21 2.12215 17.1202 1.18164 12C2.12215 6.87976 6.60812 3 12.0003 3ZM12.0003 19C16.2359 19 19.8603 16.052 20.7777 12C19.8603 7.94803 16.2359 5 12.0003 5C7.7646 5 4.14022 7.94803 3.22278 12C4.14022 16.052 7.7646 19 12.0003 19ZM12.0003 16.5C9.51498 16.5 7.50026 14.4853 7.50026 12C7.50026 9.51472 9.51498 7.5 12.0003 7.5C14.4855 7.5 16.5003 9.51472 16.5003 12C16.5003 14.4853 14.4855 16.5 12.0003 16.5ZM12.0003 14.5C13.381 14.5 14.5003 13.3807 14.5003 12C14.5003 10.6193 13.381 9.5 12.0003 9.5C10.6196 9.5 9.50026 10.6193 9.50026 12C9.50026 13.3807 10.6196 14.5 12.0003 14.5Z",
defaultProps,
});
export const MuteIcon = createIcon({
displayName: "MuteIcon",
d: "M17.8827 19.2968C16.1814 20.3755 14.1638 21.0002 12.0003 21.0002C6.60812 21.0002 2.12215 17.1204 1.18164 12.0002C1.61832 9.62282 2.81932 7.5129 4.52047 5.93457L1.39366 2.80777L2.80788 1.39355L22.6069 21.1925L21.1927 22.6068L17.8827 19.2968ZM5.9356 7.3497C4.60673 8.56015 3.6378 10.1672 3.22278 12.0002C4.14022 16.0521 7.7646 19.0002 12.0003 19.0002C13.5997 19.0002 15.112 18.5798 16.4243 17.8384L14.396 15.8101C13.7023 16.2472 12.8808 16.5002 12.0003 16.5002C9.51498 16.5002 7.50026 14.4854 7.50026 12.0002C7.50026 11.1196 7.75317 10.2981 8.19031 9.60442L5.9356 7.3497ZM12.9139 14.328L9.67246 11.0866C9.5613 11.3696 9.50026 11.6777 9.50026 12.0002C9.50026 13.3809 10.6196 14.5002 12.0003 14.5002C12.3227 14.5002 12.6309 14.4391 12.9139 14.328ZM20.8068 16.5925L19.376 15.1617C20.0319 14.2268 20.5154 13.1586 20.7777 12.0002C19.8603 7.94818 16.2359 5.00016 12.0003 5.00016C11.1544 5.00016 10.3329 5.11773 9.55249 5.33818L7.97446 3.76015C9.22127 3.26959 10.5793 3.00016 12.0003 3.00016C17.3924 3.00016 21.8784 6.87992 22.8189 12.0002C22.5067 13.6998 21.8038 15.2628 20.8068 16.5925ZM11.7229 7.50857C11.8146 7.50299 11.9071 7.50016 12.0003 7.50016C14.4855 7.50016 16.5003 9.51488 16.5003 12.0002C16.5003 12.0933 16.4974 12.1858 16.4919 12.2775L11.7229 7.50857Z",
defaultProps,
});
export const AppearanceIcon = createIcon({
displayName: "AppearanceIcon",
d: "M12 2C17.5222 2 22 5.97778 22 10.8889C22 13.9556 19.5111 16.4444 16.4444 16.4444H14.4778C13.5556 16.4444 12.8111 17.1889 12.8111 18.1111C12.8111 18.5333 12.9778 18.9222 13.2333 19.2111C13.5 19.5111 13.6667 19.9 13.6667 20.3333C13.6667 21.2556 12.9 22 12 22C6.47778 22 2 17.5222 2 12C2 6.47778 6.47778 2 12 2ZM10.8111 18.1111C10.8111 16.0843 12.451 14.4444 14.4778 14.4444H16.4444C18.4065 14.4444 20 12.851 20 10.8889C20 7.1392 16.4677 4 12 4C7.58235 4 4 7.58235 4 12C4 16.19 7.2226 19.6285 11.324 19.9718C10.9948 19.4168 10.8111 18.7761 10.8111 18.1111ZM7.5 12C6.67157 12 6 11.3284 6 10.5C6 9.67157 6.67157 9 7.5 9C8.32843 9 9 9.67157 9 10.5C9 11.3284 8.32843 12 7.5 12ZM16.5 12C15.6716 12 15 11.3284 15 10.5C15 9.67157 15.6716 9 16.5 9C17.3284 9 18 9.67157 18 10.5C18 11.3284 17.3284 12 16.5 12ZM12 9C11.1716 9 10.5 8.32843 10.5 7.5C10.5 6.67157 11.1716 6 12 6C12.8284 6 13.5 6.67157 13.5 7.5C13.5 8.32843 12.8284 9 12 9Z",
defaultProps,
});
export const DatabaseIcon = createIcon({
displayName: "DatabaseIcon",
d: "M5 12.5C5 12.8134 5.46101 13.3584 6.53047 13.8931C7.91405 14.5849 9.87677 15 12 15C14.1232 15 16.0859 14.5849 17.4695 13.8931C18.539 13.3584 19 12.8134 19 12.5V10.3287C17.35 11.3482 14.8273 12 12 12C9.17273 12 6.64996 11.3482 5 10.3287V12.5ZM19 15.3287C17.35 16.3482 14.8273 17 12 17C9.17273 17 6.64996 16.3482 5 15.3287V17.5C5 17.8134 5.46101 18.3584 6.53047 18.8931C7.91405 19.5849 9.87677 20 12 20C14.1232 20 16.0859 19.5849 17.4695 18.8931C18.539 18.3584 19 17.8134 19 17.5V15.3287ZM3 17.5V7.5C3 5.01472 7.02944 3 12 3C16.9706 3 21 5.01472 21 7.5V17.5C21 19.9853 16.9706 22 12 22C7.02944 22 3 19.9853 3 17.5ZM12 10C14.1232 10 16.0859 9.58492 17.4695 8.89313C18.539 8.3584 19 7.81342 19 7.5C19 7.18658 18.539 6.6416 17.4695 6.10687C16.0859 5.41508 14.1232 5 12 5C9.87677 5 7.91405 5.41508 6.53047 6.10687C5.46101 6.6416 5 7.18658 5 7.5C5 7.81342 5.46101 8.3584 6.53047 8.89313C7.91405 9.58492 9.87677 10 12 10Z",
defaultProps,
});
export const PerformanceIcon = createIcon({
displayName: "PerformanceIcon",
d: "M20 13C20 15.2091 19.1046 17.2091 17.6569 18.6569L19.0711 20.0711C20.8807 18.2614 22 15.7614 22 13 22 7.47715 17.5228 3 12 3 6.47715 3 2 7.47715 2 13 2 15.7614 3.11929 18.2614 4.92893 20.0711L6.34315 18.6569C4.89543 17.2091 4 15.2091 4 13 4 8.58172 7.58172 5 12 5 16.4183 5 20 8.58172 20 13ZM15.293 8.29297 10.793 12.793 12.2072 14.2072 16.7072 9.70718 15.293 8.29297Z",
defaultProps,
});
export const AppearanceIcon = Colors;
export const DatabaseIcon = Database01;
export const PerformanceIcon = Speedometer03;
/** @deprecated */
export const CommunityIcon = createIcon({
displayName: "CommunityIcon",
d: "M9.55 11.5C8.30736 11.5 7.3 10.4926 7.3 9.25C7.3 8.00736 8.30736 7 9.55 7C10.7926 7 11.8 8.00736 11.8 9.25C11.8 10.4926 10.7926 11.5 9.55 11.5ZM10 19.748V16.4C10 15.9116 10.1442 15.4627 10.4041 15.0624C10.1087 15.0213 9.80681 15 9.5 15C7.93201 15 6.49369 15.5552 5.37091 16.4797C6.44909 18.0721 8.08593 19.2553 10 19.748ZM4.45286 14.66C5.86432 13.6168 7.61013 13 9.5 13C10.5435 13 11.5431 13.188 12.4667 13.5321C13.3447 13.1888 14.3924 13 15.5 13C17.1597 13 18.6849 13.4239 19.706 14.1563C19.8976 13.4703 20 12.7471 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 12.9325 4.15956 13.8278 4.45286 14.66ZM18.8794 16.0859C18.4862 15.5526 17.1708 15 15.5 15C13.4939 15 12 15.7967 12 16.4V20C14.9255 20 17.4843 18.4296 18.8794 16.0859ZM12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM15.5 12.5C14.3954 12.5 13.5 11.6046 13.5 10.5C13.5 9.39543 14.3954 8.5 15.5 8.5C16.6046 8.5 17.5 9.39543 17.5 10.5C17.5 11.6046 16.6046 12.5 15.5 12.5Z",
defaultProps,
});
/** @deprecated */
export const GhostIcon = createIcon({
displayName: "GhostIcon",
d: "M12 2C16.9706 2 21 6.02944 21 11V18.5C21 20.433 19.433 22 17.5 22C16.3001 22 15.2413 21.3962 14.6107 20.476C14.0976 21.3857 13.1205 22 12 22C10.8795 22 9.9024 21.3857 9.38728 20.4754C8.75869 21.3962 7.69985 22 6.5 22C4.63144 22 3.10487 20.5357 3.00518 18.692L3 18.5V11C3 6.02944 7.02944 2 12 2ZM12 4C8.21455 4 5.1309 7.00478 5.00406 10.7593L5 11L4.99927 18.4461L5.00226 18.584C5.04504 19.3751 5.70251 20 6.5 20C6.95179 20 7.36652 19.8007 7.64704 19.4648L7.73545 19.3478C8.57033 18.1248 10.3985 18.2016 11.1279 19.4904C11.3053 19.8038 11.6345 20 12 20C12.3651 20 12.6933 19.8044 12.8687 19.4934C13.5692 18.2516 15.2898 18.1317 16.1636 19.2151L16.2606 19.3455C16.5401 19.7534 16.9976 20 17.5 20C18.2797 20 18.9204 19.4051 18.9931 18.6445L19 18.5V11C19 7.13401 15.866 4 12 4ZM12 12C13.1046 12 14 13.1193 14 14.5C14 15.8807 13.1046 17 12 17C10.8954 17 10 15.8807 10 14.5C10 13.1193 10.8954 12 12 12ZM9.5 8C10.3284 8 11 8.67157 11 9.5C11 10.3284 10.3284 11 9.5 11C8.67157 11 8 10.3284 8 9.5C8 8.67157 8.67157 8 9.5 8ZM14.5 8C15.3284 8 16 8.67157 16 9.5C16 10.3284 15.3284 11 14.5 11C13.6716 11 13 10.3284 13 9.5C13 8.67157 13.6716 8 14.5 8Z",
defaultProps,
});
export const ECashIcon = BankNote01;
export const WalletIcon = Wallet02;
export const DownloadIcon = Download01

View File

@ -0,0 +1,12 @@
import { createIcon } from "@chakra-ui/icons";
const UpDownIcon = createIcon({
displayName: "UpDownIcon",
viewBox: "0 0 200 200",
path: [
<path fill="currentColor" d="M 100, 100 m -75, 0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0" />,
<path fill="currentColor" d="M 100, 100 m -75, 0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0" />,
],
});
export default UpDownIcon;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const ActivityHeart = createIcon({
displayName: "ActivityHeart",
viewBox: "0 0 24 24",
path: [
<path
d="M15.5 11.5H14.5L13 14.5L11 8.5L9.5 11.5H8.5M11.9932 5.13581C9.9938 2.7984 6.65975 2.16964 4.15469 4.31001C1.64964 6.45038 1.29697 10.029 3.2642 12.5604C4.75009 14.4724 8.97129 18.311 10.948 20.0749C11.3114 20.3991 11.4931 20.5613 11.7058 20.6251C11.8905 20.6805 12.0958 20.6805 12.2805 20.6251C12.4932 20.5613 12.6749 20.3991 13.0383 20.0749C15.015 18.311 19.2362 14.4724 20.7221 12.5604C22.6893 10.029 22.3797 6.42787 19.8316 4.31001C17.2835 2.19216 13.9925 2.7984 11.9932 5.13581Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default ActivityHeart;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const Activity = createIcon({
displayName: "Activity",
viewBox: "0 0 24 24",
path: [
<path
d="M22 12H18L15 21L9 3L6 12H2"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default Activity;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const Airplay = createIcon({
displayName: "Airplay",
viewBox: "0 0 24 24",
path: [
<path
d="M5 18C3.34315 18 2 16.6569 2 15V7.8C2 6.11984 2 5.27976 2.32698 4.63803C2.6146 4.07354 3.07354 3.6146 3.63803 3.32698C4.27976 3 5.11984 3 6.8 3H17.2C18.8802 3 19.7202 3 20.362 3.32698C20.9265 3.6146 21.3854 4.07354 21.673 4.63803C22 5.27976 22 6.11984 22 7.8V15C22 16.6569 20.6569 18 19 18M8.70803 21H15.292C15.8368 21 16.1093 21 16.2467 20.8889C16.3663 20.7923 16.4347 20.6461 16.4324 20.4925C16.4298 20.3157 16.2554 20.1064 15.9065 19.6879L12.6146 15.7375C12.4035 15.4842 12.298 15.3576 12.1716 15.3114C12.0608 15.2709 11.9392 15.2709 11.8284 15.3114C11.702 15.3576 11.5965 15.4842 11.3854 15.7375L8.09346 19.6879C7.74465 20.1064 7.57024 20.3157 7.56758 20.4925C7.56526 20.6461 7.63373 20.7923 7.75326 20.8889C7.89075 21 8.16318 21 8.70803 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default Airplay;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const Airpods = createIcon({
displayName: "Airpods",
viewBox: "0 0 24 24",
path: [
<path
d="M2 7.625C2 9.90317 3.84683 11.75 6.125 11.75C6.43089 11.75 6.58383 11.75 6.66308 11.7773C6.82888 11.8345 6.91545 11.9211 6.97266 12.0869C7 12.1662 7 12.2903 7 12.5386V18.875C7 19.7725 7.72754 20.5 8.625 20.5C9.52246 20.5 10.25 19.7725 10.25 18.875V7.625C10.25 5.34683 8.40317 3.5 6.125 3.5C3.84683 3.5 2 5.34683 2 7.625Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M22 7.625C22 9.90317 20.1532 11.75 17.875 11.75C17.5691 11.75 17.4162 11.75 17.3369 11.7773C17.1711 11.8345 17.0845 11.9211 17.0273 12.0869C17 12.1662 17 12.2903 17 12.5386V18.875C17 19.7725 16.2725 20.5 15.375 20.5C14.4775 20.5 13.75 19.7725 13.75 18.875V7.625C13.75 5.34683 15.5968 3.5 17.875 3.5C20.1532 3.5 22 5.34683 22 7.625Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default Airpods;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlarmClockCheck = createIcon({
displayName: "AlarmClockCheck",
viewBox: "0 0 24 24",
path: [
<path
d="M5 3L2 6M22 6L19 3M6 19L4 21M18 19L20 21M9 13.5L11 15.5L15.5 11M12 21C14.1217 21 16.1566 20.1571 17.6569 18.6569C19.1571 17.1566 20 15.1217 20 13C20 10.8783 19.1571 8.84344 17.6569 7.34315C16.1566 5.84285 14.1217 5 12 5C9.87827 5 7.84344 5.84285 6.34315 7.34315C4.84285 8.84344 4 10.8783 4 13C4 15.1217 4.84285 17.1566 6.34315 18.6569C7.84344 20.1571 9.87827 21 12 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlarmClockCheck;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlarmClockMinus = createIcon({
displayName: "AlarmClockMinus",
viewBox: "0 0 24 24",
path: [
<path
d="M5 3L2 6M22 6L19 3M6 19L4 21M18 19L20 21M9 13H15M12 21C14.1217 21 16.1566 20.1571 17.6569 18.6569C19.1571 17.1566 20 15.1217 20 13C20 10.8783 19.1571 8.84344 17.6569 7.34315C16.1566 5.84285 14.1217 5 12 5C9.87827 5 7.84344 5.84285 6.34315 7.34315C4.84285 8.84344 4 10.8783 4 13C4 15.1217 4.84285 17.1566 6.34315 18.6569C7.84344 20.1571 9.87827 21 12 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlarmClockMinus;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlarmClockOff = createIcon({
displayName: "AlarmClockOff",
viewBox: "0 0 24 24",
path: [
<path
d="M10.5 5.14185C10.991 5.04813 11.493 5 12 5C14.1217 5 16.1566 5.84285 17.6569 7.34315C19.1571 8.84344 20 10.8783 20 13C20 13.507 19.9519 14.009 19.8582 14.5M18.1356 18.1337C17.9844 18.3144 17.8247 18.489 17.6569 18.6569C16.1566 20.1571 14.1217 21 12 21C9.87827 21 7.84344 20.1571 6.34315 18.6569C4.84285 17.1566 4 15.1217 4 13C4 10.8783 4.84285 8.84344 6.34315 7.34315C6.50948 7.17682 6.68238 7.01857 6.86123 6.86865M4 4L2 6M22 6L19 3M6 19L4 21M21 21L3 3"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlarmClockOff;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlarmClockPlus = createIcon({
displayName: "AlarmClockPlus",
viewBox: "0 0 24 24",
path: [
<path
d="M5 3L2 6M22 6L19 3M6 19L4 21M18 19L20 21M12 16V10M9 13H15M12 21C14.1217 21 16.1566 20.1571 17.6569 18.6569C19.1571 17.1566 20 15.1217 20 13C20 10.8783 19.1571 8.84344 17.6569 7.34315C16.1566 5.84285 14.1217 5 12 5C9.87827 5 7.84344 5.84285 6.34315 7.34315C4.84285 8.84344 4 10.8783 4 13C4 15.1217 4.84285 17.1566 6.34315 18.6569C7.84344 20.1571 9.87827 21 12 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlarmClockPlus;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlarmClock = createIcon({
displayName: "AlarmClock",
viewBox: "0 0 24 24",
path: [
<path
d="M5 3L2 6M22 6L19 3M6 19L4 21M18 19L20 21M12 9V13L14 15M12 21C14.1217 21 16.1566 20.1571 17.6569 18.6569C19.1571 17.1566 20 15.1217 20 13C20 10.8783 19.1571 8.84344 17.6569 7.34315C16.1566 5.84285 14.1217 5 12 5C9.87827 5 7.84344 5.84285 6.34315 7.34315C4.84285 8.84344 4 10.8783 4 13C4 15.1217 4.84285 17.1566 6.34315 18.6569C7.84344 20.1571 9.87827 21 12 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlarmClock;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlertCircle = createIcon({
displayName: "AlertCircle",
viewBox: "0 0 24 24",
path: [
<path
d="M12 8V12M12 16H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlertCircle;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlertHexagon = createIcon({
displayName: "AlertHexagon",
viewBox: "0 0 24 24",
path: [
<path
d="M12 8.00008V12.0001M12 16.0001H12.01M3 7.94153V16.0586C3 16.4013 3 16.5726 3.05048 16.7254C3.09515 16.8606 3.16816 16.9847 3.26463 17.0893C3.37369 17.2077 3.52345 17.2909 3.82297 17.4573L11.223 21.5684C11.5066 21.726 11.6484 21.8047 11.7985 21.8356C11.9315 21.863 12.0685 21.863 12.2015 21.8356C12.3516 21.8047 12.4934 21.726 12.777 21.5684L20.177 17.4573C20.4766 17.2909 20.6263 17.2077 20.7354 17.0893C20.8318 16.9847 20.9049 16.8606 20.9495 16.7254C21 16.5726 21 16.4013 21 16.0586V7.94153C21 7.59889 21 7.42756 20.9495 7.27477C20.9049 7.13959 20.8318 7.01551 20.7354 6.91082C20.6263 6.79248 20.4766 6.70928 20.177 6.54288L12.777 2.43177C12.4934 2.27421 12.3516 2.19543 12.2015 2.16454C12.0685 2.13721 11.9315 2.13721 11.7985 2.16454C11.6484 2.19543 11.5066 2.27421 11.223 2.43177L3.82297 6.54288C3.52345 6.70928 3.37369 6.79248 3.26463 6.91082C3.16816 7.01551 3.09515 7.13959 3.05048 7.27477C3 7.42756 3 7.59889 3 7.94153Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlertHexagon;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlertOctagon = createIcon({
displayName: "AlertOctagon",
viewBox: "0 0 24 24",
path: [
<path
d="M12 8V12M12 16H12.01M2 8.52274V15.4773C2 15.7218 2 15.8441 2.02763 15.9592C2.05213 16.0613 2.09253 16.1588 2.14736 16.2483C2.2092 16.3492 2.29568 16.4357 2.46863 16.6086L7.39137 21.5314C7.56432 21.7043 7.6508 21.7908 7.75172 21.8526C7.84119 21.9075 7.93873 21.9479 8.04077 21.9724C8.15586 22 8.27815 22 8.52274 22H15.4773C15.7218 22 15.8441 22 15.9592 21.9724C16.0613 21.9479 16.1588 21.9075 16.2483 21.8526C16.3492 21.7908 16.4357 21.7043 16.6086 21.5314L21.5314 16.6086C21.7043 16.4357 21.7908 16.3492 21.8526 16.2483C21.9075 16.1588 21.9479 16.0613 21.9724 15.9592C22 15.8441 22 15.7218 22 15.4773V8.52274C22 8.27815 22 8.15586 21.9724 8.04077C21.9479 7.93873 21.9075 7.84119 21.8526 7.75172C21.7908 7.6508 21.7043 7.56432 21.5314 7.39137L16.6086 2.46863C16.4357 2.29568 16.3492 2.2092 16.2483 2.14736C16.1588 2.09253 16.0613 2.05213 15.9592 2.02763C15.8441 2 15.7218 2 15.4773 2H8.52274C8.27815 2 8.15586 2 8.04077 2.02763C7.93873 2.05213 7.84119 2.09253 7.75172 2.14736C7.6508 2.2092 7.56432 2.29568 7.39137 2.46863L2.46863 7.39137C2.29568 7.56432 2.2092 7.6508 2.14736 7.75172C2.09253 7.84119 2.05213 7.93873 2.02763 8.04077C2 8.15586 2 8.27815 2 8.52274Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlertOctagon;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlertSquare = createIcon({
displayName: "AlertSquare",
viewBox: "0 0 24 24",
path: [
<path
d="M12 8V12M12 16H12.01M7.8 21H16.2C17.8802 21 18.7202 21 19.362 20.673C19.9265 20.3854 20.3854 19.9265 20.673 19.362C21 18.7202 21 17.8802 21 16.2V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlertSquare;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlertTriangle = createIcon({
displayName: "AlertTriangle",
viewBox: "0 0 24 24",
path: [
<path
d="M11.9998 8.99999V13M11.9998 17H12.0098M10.6151 3.89171L2.39019 18.0983C1.93398 18.8863 1.70588 19.2803 1.73959 19.6037C1.769 19.8857 1.91677 20.142 2.14613 20.3088C2.40908 20.5 2.86435 20.5 3.77487 20.5H20.2246C21.1352 20.5 21.5904 20.5 21.8534 20.3088C22.0827 20.142 22.2305 19.8857 22.2599 19.6037C22.2936 19.2803 22.0655 18.8863 21.6093 18.0983L13.3844 3.89171C12.9299 3.10654 12.7026 2.71396 12.4061 2.58211C12.1474 2.4671 11.8521 2.4671 11.5935 2.58211C11.2969 2.71396 11.0696 3.10655 10.6151 3.89171Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlertTriangle;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignBottom01 = createIcon({
displayName: "AlignBottom01",
viewBox: "0 0 24 24",
path: [
<path
d="M3 21H21M12 3V17M12 17L19 10M12 17L5 10"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignBottom01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignBottom02 = createIcon({
displayName: "AlignBottom02",
viewBox: "0 0 24 24",
path: [
<path
d="M10 18V6C10 5.06812 10 4.60218 9.84776 4.23463C9.64477 3.74458 9.25542 3.35523 8.76537 3.15224C8.39782 3 7.93188 3 7 3C6.06812 3 5.60218 3 5.23463 3.15224C4.74458 3.35523 4.35523 3.74458 4.15224 4.23463C4 4.60218 4 5.06812 4 6V18C4 18.9319 4 19.3978 4.15224 19.7654C4.35523 20.2554 4.74458 20.6448 5.23463 20.8478C5.60218 21 6.06812 21 7 21C7.93188 21 8.39782 21 8.76537 20.8478C9.25542 20.6448 9.64477 20.2554 9.84776 19.7654C10 19.3978 10 18.9319 10 18Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M20 18V10C20 9.06812 20 8.60218 19.8478 8.23463C19.6448 7.74458 19.2554 7.35523 18.7654 7.15224C18.3978 7 17.9319 7 17 7C16.0681 7 15.6022 7 15.2346 7.15224C14.7446 7.35523 14.3552 7.74458 14.1522 8.23463C14 8.60218 14 9.06812 14 10V18C14 18.9319 14 19.3978 14.1522 19.7654C14.3552 20.2554 14.7446 20.6448 15.2346 20.8478C15.6022 21 16.0681 21 17 21C17.9319 21 18.3978 21 18.7654 20.8478C19.2554 20.6448 19.6448 20.2554 19.8478 19.7654C20 19.3978 20 18.9319 20 18Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignBottom02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignCenter = createIcon({
displayName: "AlignCenter",
viewBox: "0 0 24 24",
path: [
<path
d="M18 10H6M21 6H3M21 14H3M18 18H6"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignCenter;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignHorizontalCentre01 = createIcon({
displayName: "AlignHorizontalCentre01",
viewBox: "0 0 24 24",
path: [
<path
d="M12 3V21M22 12H15.5M15.5 12L19.5 16M15.5 12L19.5 8M2 12H8.5M8.5 12L4.5 16M8.5 12L4.5 8"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignHorizontalCentre01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignHorizontalCentre02 = createIcon({
displayName: "AlignHorizontalCentre02",
viewBox: "0 0 24 24",
path: [
<path
d="M16 10C16.9319 10 17.3978 10 17.7654 9.84776C18.2554 9.64477 18.6448 9.25542 18.8478 8.76537C19 8.39782 19 7.93188 19 7C19 6.06812 19 5.60218 18.8478 5.23463C18.6448 4.74458 18.2554 4.35523 17.7654 4.15224C17.3978 4 16.9319 4 16 4L8 4C7.06812 4 6.60218 4 6.23463 4.15224C5.74458 4.35523 5.35523 4.74458 5.15224 5.23463C5 5.60218 5 6.06812 5 7C5 7.93188 5 8.39782 5.15224 8.76537C5.35523 9.25542 5.74458 9.64477 6.23463 9.84776C6.60218 10 7.06812 10 8 10L16 10Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M18 20C18.9319 20 19.3978 20 19.7654 19.8478C20.2554 19.6448 20.6448 19.2554 20.8478 18.7654C21 18.3978 21 17.9319 21 17C21 16.0681 21 15.6022 20.8478 15.2346C20.6448 14.7446 20.2554 14.3552 19.7654 14.1522C19.3978 14 18.9319 14 18 14H6C5.06812 14 4.60218 14 4.23463 14.1522C3.74458 14.3552 3.35523 14.7446 3.15224 15.2346C3 15.6022 3 16.0681 3 17C3 17.9319 3 18.3978 3.15224 18.7654C3.35523 19.2554 3.74458 19.6448 4.23463 19.8478C4.60218 20 5.06812 20 6 20L18 20Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignHorizontalCentre02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignJustify = createIcon({
displayName: "AlignJustify",
viewBox: "0 0 24 24",
path: [
<path
d="M21 10H3M21 18H3M21 6H3M21 14H3"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignJustify;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignLeft01 = createIcon({
displayName: "AlignLeft01",
viewBox: "0 0 24 24",
path: [
<path
d="M3 3V21M21 12H7M7 12L14 19M7 12L14 5"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignLeft01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignLeft02 = createIcon({
displayName: "AlignLeft02",
viewBox: "0 0 24 24",
path: [
<path
d="M14 10C14.9319 10 15.3978 10 15.7654 9.84776C16.2554 9.64477 16.6448 9.25542 16.8478 8.76537C17 8.39782 17 7.93188 17 7C17 6.06812 17 5.60218 16.8478 5.23463C16.6448 4.74458 16.2554 4.35523 15.7654 4.15224C15.3978 4 14.9319 4 14 4L6 4C5.06812 4 4.60218 4 4.23463 4.15224C3.74458 4.35523 3.35523 4.74458 3.15224 5.23463C3 5.60218 3 6.06812 3 7C3 7.93188 3 8.39782 3.15224 8.76537C3.35523 9.25542 3.74458 9.64477 4.23463 9.84776C4.60218 10 5.06812 10 6 10L14 10Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M18 20C18.9319 20 19.3978 20 19.7654 19.8478C20.2554 19.6448 20.6448 19.2554 20.8478 18.7654C21 18.3978 21 17.9319 21 17C21 16.0681 21 15.6022 20.8478 15.2346C20.6448 14.7446 20.2554 14.3552 19.7654 14.1522C19.3978 14 18.9319 14 18 14H6C5.06812 14 4.60218 14 4.23463 14.1522C3.74458 14.3552 3.35523 14.7446 3.15224 15.2346C3 15.6022 3 16.0681 3 17C3 17.9319 3 18.3978 3.15224 18.7654C3.35523 19.2554 3.74458 19.6448 4.23463 19.8478C4.60218 20 5.06812 20 6 20L18 20Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignLeft02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignLeft = createIcon({
displayName: "AlignLeft",
viewBox: "0 0 24 24",
path: [
<path
d="M16 10H3M20 6H3M20 14H3M16 18H3"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignLeft;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignRight01 = createIcon({
displayName: "AlignRight01",
viewBox: "0 0 24 24",
path: [
<path
d="M21 21V3M3 12H17M17 12L10 5M17 12L10 19"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignRight01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignRight02 = createIcon({
displayName: "AlignRight02",
viewBox: "0 0 24 24",
path: [
<path
d="M18 10C18.9319 10 19.3978 10 19.7654 9.84776C20.2554 9.64477 20.6448 9.25542 20.8478 8.76537C21 8.39782 21 7.93188 21 7C21 6.06812 21 5.60218 20.8478 5.23463C20.6448 4.74458 20.2554 4.35523 19.7654 4.15224C19.3978 4 18.9319 4 18 4L10 4C9.06812 4 8.60218 4 8.23463 4.15224C7.74458 4.35523 7.35523 4.74458 7.15224 5.23463C7 5.60218 7 6.06812 7 7C7 7.93188 7 8.39782 7.15224 8.76537C7.35523 9.25542 7.74458 9.64477 8.23463 9.84776C8.60218 10 9.06812 10 10 10L18 10Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M18 20C18.9319 20 19.3978 20 19.7654 19.8478C20.2554 19.6448 20.6448 19.2554 20.8478 18.7654C21 18.3978 21 17.9319 21 17C21 16.0681 21 15.6022 20.8478 15.2346C20.6448 14.7446 20.2554 14.3552 19.7654 14.1522C19.3978 14 18.9319 14 18 14H6C5.06812 14 4.60218 14 4.23463 14.1522C3.74458 14.3552 3.35523 14.7446 3.15224 15.2346C3 15.6022 3 16.0681 3 17C3 17.9319 3 18.3978 3.15224 18.7654C3.35523 19.2554 3.74458 19.6448 4.23463 19.8478C4.60218 20 5.06812 20 6 20L18 20Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignRight02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignRight = createIcon({
displayName: "AlignRight",
viewBox: "0 0 24 24",
path: [
<path
d="M21 10H8M21 6H4M21 14H4M21 18H8"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignRight;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignTop01 = createIcon({
displayName: "AlignTop01",
viewBox: "0 0 24 24",
path: [
<path
d="M21 3H3M12 21V7M12 7L5 14M12 7L19 14"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignTop01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignTop02 = createIcon({
displayName: "AlignTop02",
viewBox: "0 0 24 24",
path: [
<path
d="M10 18V6C10 5.06812 10 4.60218 9.84776 4.23463C9.64477 3.74458 9.25542 3.35523 8.76537 3.15224C8.39782 3 7.93188 3 7 3C6.06812 3 5.60218 3 5.23463 3.15224C4.74458 3.35523 4.35523 3.74458 4.15224 4.23463C4 4.60218 4 5.06812 4 6V18C4 18.9319 4 19.3978 4.15224 19.7654C4.35523 20.2554 4.74458 20.6448 5.23463 20.8478C5.60218 21 6.06812 21 7 21C7.93188 21 8.39782 21 8.76537 20.8478C9.25542 20.6448 9.64477 20.2554 9.84776 19.7654C10 19.3978 10 18.9319 10 18Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M20 14V6C20 5.06812 20 4.60218 19.8478 4.23463C19.6448 3.74458 19.2554 3.35523 18.7654 3.15224C18.3978 3 17.9319 3 17 3C16.0681 3 15.6022 3 15.2346 3.15224C14.7446 3.35523 14.3552 3.74458 14.1522 4.23463C14 4.60218 14 5.06812 14 6V14C14 14.9319 14 15.3978 14.1522 15.7654C14.3552 16.2554 14.7446 16.6448 15.2346 16.8478C15.6022 17 16.0681 17 17 17C17.9319 17 18.3978 17 18.7654 16.8478C19.2554 16.6448 19.6448 16.2554 19.8478 15.7654C20 15.3978 20 14.9319 20 14Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignTop02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AlignVerticalCenter01 = createIcon({
displayName: "AlignVerticalCenter01",
viewBox: "0 0 24 24",
path: [
<path
d="M3 12H21M12 2V8.5M12 8.5L16 4.5M12 8.5L8 4.5M12 22V15.5M12 15.5L16 19.5M12 15.5L8 19.5"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignVerticalCenter01;

View File

@ -0,0 +1,27 @@
import { createIcon } from "@chakra-ui/icons";
const AlignVerticalCenter02 = createIcon({
displayName: "AlignVerticalCenter02",
viewBox: "0 0 24 24",
path: [
<path
d="M10 18V6C10 5.06812 10 4.60218 9.84776 4.23463C9.64477 3.74458 9.25542 3.35523 8.76537 3.15224C8.39782 3 7.93188 3 7 3C6.06812 3 5.60218 3 5.23463 3.15224C4.74458 3.35523 4.35523 3.74458 4.15224 4.23463C4 4.60218 4 5.06812 4 6V18C4 18.9319 4 19.3978 4.15224 19.7654C4.35523 20.2554 4.74458 20.6448 5.23463 20.8478C5.60218 21 6.06812 21 7 21C7.93188 21 8.39782 21 8.76537 20.8478C9.25542 20.6448 9.64477 20.2554 9.84776 19.7654C10 19.3978 10 18.9319 10 18Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
<path
d="M20 16V8C20 7.06812 20 6.60218 19.8478 6.23463C19.6448 5.74458 19.2554 5.35523 18.7654 5.15224C18.3978 5 17.9319 5 17 5C16.0681 5 15.6022 5 15.2346 5.15224C14.7446 5.35523 14.3552 5.74458 14.1522 6.23463C14 6.60218 14 7.06812 14 8V16C14 16.9319 14 17.3978 14.1522 17.7654C14.3552 18.2554 14.7446 18.6448 15.2346 18.8478C15.6022 19 16.0681 19 17 19C17.9319 19 18.3978 19 18.7654 18.8478C19.2554 18.6448 19.6448 18.2554 19.8478 17.7654C20 17.3978 20 16.9319 20 16Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AlignVerticalCenter02;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const Anchor = createIcon({
displayName: "Anchor",
viewBox: "0 0 24 24",
path: [
<path
d="M12 8C13.6569 8 15 6.65685 15 5C15 3.34315 13.6569 2 12 2C10.3431 2 9 3.34315 9 5C9 6.65685 10.3431 8 12 8ZM12 8V22M12 22C9.34784 22 6.8043 20.9464 4.92893 19.0711C3.05357 17.1957 2 14.6522 2 12H5M12 22C14.6522 22 17.1957 20.9464 19.0711 19.0711C20.9464 17.1957 22 14.6522 22 12H19"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default Anchor;

View File

@ -0,0 +1,19 @@
import { createIcon } from "@chakra-ui/icons";
const AnnotationAlert = createIcon({
displayName: "AnnotationAlert",
viewBox: "0 0 24 24",
path: [
<path
d="M12 10.5V7M12 14H12.01M9.9 19.2L11.36 21.1467C11.5771 21.4362 11.6857 21.5809 11.8188 21.6327C11.9353 21.678 12.0647 21.678 12.1812 21.6327C12.3143 21.5809 12.4229 21.4362 12.64 21.1467L14.1 19.2C14.3931 18.8091 14.5397 18.6137 14.7185 18.4645C14.9569 18.2656 15.2383 18.1248 15.5405 18.0535C15.7671 18 16.0114 18 16.5 18C17.8978 18 18.5967 18 19.1481 17.7716C19.8831 17.4672 20.4672 16.8831 20.7716 16.1481C21 15.5967 21 14.8978 21 13.5V7.8C21 6.11984 21 5.27976 20.673 4.63803C20.3854 4.07354 19.9265 3.6146 19.362 3.32698C18.7202 3 17.8802 3 16.2 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V13.5C3 14.8978 3 15.5967 3.22836 16.1481C3.53284 16.8831 4.11687 17.4672 4.85195 17.7716C5.40326 18 6.10218 18 7.5 18C7.98858 18 8.23287 18 8.45951 18.0535C8.76169 18.1248 9.04312 18.2656 9.2815 18.4645C9.46028 18.6137 9.60685 18.8091 9.9 19.2Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
></path>,
],
defaultProps: { boxSize: 4 },
});
export default AnnotationAlert;

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