Open source release UI FrontEnd and rust BackEnd
5
.changeset/polite-pants-watch.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'@pastebar/ui': minor
|
||||
---
|
||||
|
||||
Free and Opensource Release
|
2
.env
@ -2,4 +2,4 @@ DATABASE_URL=sqlite://local.pastebar-db.data
|
||||
VITE_ENABLE_REACT_QUERY_DEVTOOLS=
|
||||
VITE_DISABLE_SAVE_TRANSLATIONS=
|
||||
VITE_DISABLE_LANGUAGE_FALLBACK=
|
||||
MISSING_TRANSLATION_SAVE_PATH=../../PasteBarApp-UI/src/locales/lang
|
||||
MISSING_TRANSLATION_SAVE_PATH=../../pastebar-app-ui/src/locales/lang
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- fc8c65f: New: Integrated Audio Player with playlist support for both local and remote MP3 files.
|
||||
- New: Integrated Audio Player with playlist support for both local and remote MP3 files.
|
||||
New: Clipboard history now accessible in a separate window from the main interface.
|
||||
New: Automatically generate card links in clipboard history.
|
||||
New: Auto preview for X.com (Twitter) links in clips.
|
||||
|
1148
package-lock.json
generated
12
package.json
@ -3,15 +3,10 @@
|
||||
"version": "0.3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "tauri dev --config src-tauri/tauri.dev.conf.json",
|
||||
"dev": "tauri dev",
|
||||
"start": "tauri dev",
|
||||
"ui:dev": "vite",
|
||||
"ui:build:local": "vite build",
|
||||
"ui:build:ts": "tsc && vite build",
|
||||
"format": "npx prettier --write . --ignore-path .gitignore ",
|
||||
"app:build:local": "tauri build",
|
||||
"build:clear": "rimraf build",
|
||||
"build": "tauri build",
|
||||
"build": "npm run app:build",
|
||||
"app:build": "tauri build --config src-tauri/tauri.release.conf.json",
|
||||
"app:build:debug": "tauri build --config src-tauri/tauri.release.conf.json --debug",
|
||||
"app:build:osx:universal": "tauri build --config src-tauri/tauri.release.conf.json --target universal-apple-darwin",
|
||||
@ -146,6 +141,9 @@
|
||||
"zustand": "^4.4.6",
|
||||
"zustand-logger-middleware": "^1.0.9"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.1",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
|
5
packages/pastebar-app-ui/.env.sample
Normal file
@ -0,0 +1,5 @@
|
||||
VITE_ENABLE_REACT_QUERY_DEVTOOLS=
|
||||
VITE_DISABLE_SAVE_TRANSLATIONS=
|
||||
VITE_DISABLE_LANGUAGE_FALLBACK=
|
||||
VITE_ENABLE_DEV_AUTO_UPDATER=
|
||||
PASTEBAR_APP_PATH=../..
|
67
packages/pastebar-app-ui/.eslintrc.js
Normal file
@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
jquery: false,
|
||||
node: false,
|
||||
},
|
||||
root: false,
|
||||
plugins: ['@typescript-eslint', 'eslint-plugin-react-compiler', 'prettier', 'sonarjs'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:sonarjs/recommended',
|
||||
'plugin:import/electron',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:import/typescript',
|
||||
],
|
||||
rules: {
|
||||
'react-compiler/react-compiler': 'error',
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'no-empty-function': 'off',
|
||||
'import/no-named-as-default': 'off',
|
||||
'import/no-named-as-default-member': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
'@typescript-eslint/no-unused-vars': ['warn'],
|
||||
'@typescript-eslint/no-empty-function': 0,
|
||||
'sonarjs/no-duplicate-string': 'off',
|
||||
'sonarjs/no-duplicated-branches': 'off',
|
||||
'sonarjs/no-nested-template-literals': 'off',
|
||||
'sonarjs/no-identical-functions': 'off',
|
||||
'cypress/no-unnecessary-waiting': 'off',
|
||||
'react/prop-types': 0,
|
||||
'sonarjs/cognitive-complexity': ['error', 200],
|
||||
camelcase: ['error', { ignoreDestructuring: true }],
|
||||
'computed-property-spacing': [2, 'never'],
|
||||
'no-extend-native': 2,
|
||||
'no-trailing-spaces': 1,
|
||||
'no-mixed-spaces-and-tabs': ['warn', 'smart-tabs'],
|
||||
'no-use-before-define': [2, 'nofunc'],
|
||||
'object-curly-spacing': [2, 'always'],
|
||||
quotes: [
|
||||
2,
|
||||
'single',
|
||||
{
|
||||
avoidEscape: true,
|
||||
allowTemplateLiterals: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@babel/eslint-parser',
|
||||
requireConfigFile: false,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
typescript: {}, // this loads <rootdir>/tsconfig.json to eslint
|
||||
},
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
},
|
||||
}
|
36
packages/pastebar-app-ui/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
local.pastebar.*
|
||||
safelist.txt
|
||||
.env
|
||||
|
||||
clipboard-images/**/*
|
||||
clip-images/**/*
|
||||
src-tauri/http-cacache/**/*
|
||||
|
||||
node_modules
|
||||
dist-ui/**/*
|
||||
*.local
|
||||
*.data
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
|
||||
# Added by cargo
|
||||
|
||||
/target
|
40
packages/pastebar-app-ui/LICENSE
Normal file
@ -0,0 +1,40 @@
|
||||
# FREE TO USE LICENSE, NOT FOR RESALE OR REDISTRIBUTION
|
||||
|
||||
[[PasteBar App](https://github.com/PasteBar/PasteBar)]
|
||||
|
||||
Copyright (c) 2024 AnotherVision LLC. All rights reserved.
|
||||
|
||||
1. Definitions:
|
||||
- "Software" refers to the PasteBar FrontEnd App.
|
||||
- "License" refers to the terms and conditions for use, reproduction, and distribution as defined by this document.
|
||||
- "Licensor" refers to AnotherVision LLC.
|
||||
- "You" or "Your" refers to the individual or legal entity exercising permissions granted by this License.
|
||||
|
||||
2. Grant of License:
|
||||
This License grants you, free of charge, a non-exclusive, worldwide license to use, copy, and modify the Software for any purpose, including commercial use, subject to the restrictions outlined in this License.
|
||||
|
||||
3. Restrictions:
|
||||
You may not:
|
||||
- Sell, sublicense, or redistribute the Software as a standalone product.
|
||||
- Use the Licensor's name, trademarks, or logos to endorse or promote products derived from this Software without specific prior written permission.
|
||||
|
||||
4. Derivative Works:
|
||||
You are allowed to create and use derivative works based on the Software, including for commercial purposes. However, you must clearly indicate that such derivative works are modifications of the original Software and are not endorsed by the Licensor.
|
||||
|
||||
5. Ownership:
|
||||
The Software is protected by intellectual property laws and treaties. The Licensor retains all right, title, and interest in and to the Software, including all copyrights, patents, trade secrets, trademarks, and other intellectual property rights.
|
||||
|
||||
6. Contributions:
|
||||
Any contributions intentionally submitted for inclusion in the Software by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions.
|
||||
|
||||
7. Disclaimer of Warranty:
|
||||
The Software is provided "AS IS," without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement.
|
||||
|
||||
8. Limitation of Liability:
|
||||
In no event shall the Licensor be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
|
||||
|
||||
9. Termination:
|
||||
This License is effective until terminated. Your rights under this License will terminate automatically without notice from the Licensor if you fail to comply with any of its terms and conditions.
|
||||
|
||||
10. General:
|
||||
This License constitutes the entire agreement between you and the Licensor relating to the Software and supersedes all prior or contemporaneous oral or written communications, proposals, and representations with respect to the Software or any other subject matter covered by this License.
|
88
packages/pastebar-app-ui/assets/markdown/markdown.d.ts
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* parse reads markdown source at s and converts it to HTML.
|
||||
* When output is a byte array, it will be a reference.
|
||||
*/
|
||||
export function parse(s :Source, o? :ParseOptions & { bytes? :never|false }) :string
|
||||
export function parse(s :Source, o? :ParseOptions & { bytes :true }) :Uint8Array
|
||||
|
||||
/** Markdown source code can be provided as a JavaScript string or UTF8 encoded data */
|
||||
type Source = string | ArrayLike<number>
|
||||
|
||||
/** Options for the parse function */
|
||||
export interface ParseOptions {
|
||||
/** Customize parsing. Defaults to ParseFlags.DEFAULT */
|
||||
parseFlags? :ParseFlags
|
||||
|
||||
/** Select output format. Defaults to "html" */
|
||||
format? : "html" | "xhtml"
|
||||
|
||||
/**
|
||||
* bytes=true causes parse() to return the result as a Uint8Array instead of a string.
|
||||
*
|
||||
* The returned Uint8Array is only valid until the next call to parse().
|
||||
* If you need to keep the returned data around, call Uint8Array.slice() to make a copy,
|
||||
* as each call to parse() uses the same underlying memory.
|
||||
*
|
||||
* This only provides a performance benefit when you never need to convert the output
|
||||
* to a string. In most cases you're better off leaving this unset or false.
|
||||
*/
|
||||
bytes? :boolean
|
||||
|
||||
/** Allow "javascript:" in links */
|
||||
allowJSURIs? :boolean
|
||||
|
||||
/**
|
||||
* Optional callback which if provided is called for each code block.
|
||||
* langname holds the "language tag", if any, of the block.
|
||||
*
|
||||
* The returned value is inserted into the resulting HTML verbatim, without HTML escaping.
|
||||
* Thus, you should take care of properly escaping any special HTML characters.
|
||||
*
|
||||
* If the function returns null or undefined, or an exception occurs, the body will be
|
||||
* included as-is after going through HTML escaping.
|
||||
*
|
||||
* Note that use of this callback has an adverse impact on performance as it casues
|
||||
* calls and data to be bridged between WASM and JS on every invocation.
|
||||
*/
|
||||
onCodeBlock? :(langname :string, body :UTF8Bytes) => Uint8Array|string|null|undefined
|
||||
|
||||
/** @depreceated use "bytes" instead (v1.1.1) */
|
||||
asMemoryView? :boolean
|
||||
}
|
||||
|
||||
/** UTF8Bytes is a Uint8Array representing UTF8 text */
|
||||
export interface UTF8Bytes extends Uint8Array {
|
||||
/** toString returns a UTF8 decoded string (lazily decoded and cached) */
|
||||
toString() :string
|
||||
}
|
||||
|
||||
/** Flags that customize Markdown parsing */
|
||||
export enum ParseFlags {
|
||||
/** In TEXT, collapse non-trivial whitespace into single ' ' */ COLLAPSE_WHITESPACE,
|
||||
/** Enable $ and $$ containing LaTeX equations. */ LATEX_MATH_SPANS,
|
||||
/** Disable raw HTML blocks. */ NO_HTML_BLOCKS,
|
||||
/** Disable raw HTML (inline). */ NO_HTML_SPANS,
|
||||
/** Disable indented code blocks. (Only fenced code works.) */ NO_INDENTED_CODE_BLOCKS,
|
||||
/** Do not require space in ATX headers ( ###header ) */ PERMISSIVE_ATX_HEADERS,
|
||||
/** Recognize e-mails as links even without <...> */ PERMISSIVE_EMAIL_AUTO_LINKS,
|
||||
/** Recognize URLs as links even without <...> */ PERMISSIVE_URL_AUTO_LINKS,
|
||||
/** Enable WWW autolinks (without proto; just 'www.') */ PERMISSIVE_WWW_AUTOLINKS,
|
||||
/** Enable strikethrough extension. */ STRIKETHROUGH,
|
||||
/** Enable tables extension. */ TABLES,
|
||||
/** Enable task list extension. */ TASK_LISTS,
|
||||
/** Enable wiki links extension. */ WIKI_LINKS,
|
||||
/** Enable underline extension (disables '_' for emphasis) */ UNDERLINE,
|
||||
|
||||
/** Default flags are:
|
||||
* COLLAPSE_WHITESPACE |
|
||||
* PERMISSIVE_ATX_HEADERS |
|
||||
* PERMISSIVE_URL_AUTO_LINKS |
|
||||
* STRIKETHROUGH |
|
||||
* TABLES |
|
||||
* TASK_LISTS
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/** Shorthand for NO_HTML_BLOCKS | NO_HTML_SPANS */
|
||||
NO_HTML,
|
||||
}
|
4
packages/pastebar-app-ui/assets/markdown/markdown.js
Normal file
1
packages/pastebar-app-ui/assets/markdown/markdown.js.map
Normal file
BIN
packages/pastebar-app-ui/assets/markdown/markdown.wasm
Executable file
270
packages/pastebar-app-ui/assets/styles/boarding.css
Normal file
@ -0,0 +1,270 @@
|
||||
.boarding-coutout-svg-animated,
|
||||
div#boarding-popover-item.boarding-popover-item-animated {
|
||||
animation: boardingFadeIn 0.4s;
|
||||
}
|
||||
|
||||
body .boarding-coutout-svg {
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
position: absolute;
|
||||
border-radius: 10px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body.boarding-strict-pointer-events,
|
||||
body.boarding-strict-pointer-events
|
||||
*:not(.boarding-highlighted-element *):not(#boarding-popover-item *):not(
|
||||
.boarding-highlighted-element
|
||||
):not(#boarding-popover-item):not(.boarding-coutout-svg path),
|
||||
body.boarding-no-pointer-events,
|
||||
body.boarding-no-pointer-events
|
||||
*:not(.boarding-highlighted-element *):not(#boarding-popover-item *):not(
|
||||
.boarding-highlighted-element
|
||||
):not(#boarding-popover-item):not(.boarding-coutout-svg):not(
|
||||
.boarding-coutout-svg path
|
||||
) {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
/* enable pointer-events where it makes sense */
|
||||
div#boarding-popover-item,
|
||||
.boarding-coutout-svg path,
|
||||
body.boarding-strict-pointer-events .boarding-highlighted-element,
|
||||
body.boarding-no-pointer-events .boarding-coutout-svg {
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
|
||||
/* popover */
|
||||
div#boarding-popover-item {
|
||||
--boarding-popover-padding: 10px;
|
||||
--boarding-popover-tip-padding: 15px;
|
||||
padding: var(--boarding-popover-padding);
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1000000000;
|
||||
}
|
||||
|
||||
/* tip */
|
||||
.dark div#boarding-popover-item .boarding-popover-tip {
|
||||
border: 6px solid;
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-color: rgb(70, 81, 97);
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-tip {
|
||||
border: 6px solid rgb(249 250 251);
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-color: rgb(249 250 251);
|
||||
}
|
||||
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip:not([class^='boarding-tipside-']):not(
|
||||
[class^='boarding-tipalign-']
|
||||
):not([class*=' boarding-tipalign-']):not([class*=' boarding-tipalign-']) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* tb */
|
||||
div#boarding-popover-item .boarding-popover-tip.boarding-tipside-top {
|
||||
top: 100%;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
div#boarding-popover-item .boarding-popover-tip.boarding-tipside-bottom {
|
||||
bottom: 100%;
|
||||
border-left-color: transparent;
|
||||
border-top-color: transparent;
|
||||
border-right-color: transparent;
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-top.boarding-tipalign-center,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-bottom.boarding-tipalign-center {
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-top.boarding-tipalign-start,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-bottom.boarding-tipalign-start {
|
||||
left: var(--boarding-popover-tip-padding);
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-top.boarding-tipalign-end,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-bottom.boarding-tipalign-end {
|
||||
right: var(--boarding-popover-tip-padding);
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-footer-counter {
|
||||
font-size: 0.85rem;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* lr */
|
||||
div#boarding-popover-item .boarding-popover-tip.boarding-tipside-left {
|
||||
left: 100%;
|
||||
margin-top: 5px;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
border-top-color: transparent;
|
||||
}
|
||||
div#boarding-popover-item .boarding-popover-tip.boarding-tipside-right {
|
||||
right: 100%;
|
||||
margin-top: 5px;
|
||||
border-left-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
border-top-color: transparent;
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-left.boarding-tipalign-center,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-right.boarding-tipalign-center {
|
||||
top: 50%;
|
||||
margin-top: -5px;
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-left.boarding-tipalign-start,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-right.boarding-tipalign-start {
|
||||
top: var(--boarding-popover-tip-padding);
|
||||
}
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-left.boarding-tipalign-end,
|
||||
div#boarding-popover-item
|
||||
.boarding-popover-tip.boarding-tipside-right.boarding-tipalign-end {
|
||||
bottom: var(--boarding-popover-tip-padding);
|
||||
}
|
||||
|
||||
@keyframes boardingFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Boarding theme */
|
||||
|
||||
div#boarding-popover-item {
|
||||
margin: 0;
|
||||
border-radius: 5px;
|
||||
min-width: 250px;
|
||||
max-width: 300px;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
div#boarding-popover-item .boarding-popover-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
div#boarding-popover-item .boarding-popover-footer button {
|
||||
display: inline-block;
|
||||
padding: 3px 10px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-footer button.boarding-disabled {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
div#boarding-popover-item .boarding-popover-footer .boarding-close-btn {
|
||||
position: absolute;
|
||||
color: #999;
|
||||
top: 4px;
|
||||
right: 0;
|
||||
}
|
||||
.dark div#boarding-popover-item .boarding-popover-footer .boarding-close-btn {
|
||||
color: #cccc;
|
||||
}
|
||||
|
||||
.dark div#boarding-popover-item .boarding-popover-footer .boarding-close-btn:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-footer .boarding-close-btn:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-footer .boarding-btn-group {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-btn-group button {
|
||||
border-radius: 6px;
|
||||
padding: 3px 12px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-btn-group button:hover {
|
||||
border: 1px solid #007bff;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-btn-group button.boarding-prev-btn {
|
||||
opacity: 0.8;
|
||||
color: #0056b3;
|
||||
}
|
||||
|
||||
.dark div#boarding-popover-item .boarding-btn-group button.boarding-prev-btn {
|
||||
opacity: 0.8;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-btn-group button.boarding-prev-btn.boarding-disabled {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-btn-group button.boarding-prev-btn:hover {
|
||||
opacity: 1;
|
||||
color: #0056b3;
|
||||
border: 1px solid #0056b3;
|
||||
}
|
||||
|
||||
.dark div#boarding-popover-item .boarding-btn-group button.boarding-prev-btn:hover {
|
||||
opacity: 1;
|
||||
color: #007bff;
|
||||
border: 1px solid #007bff;
|
||||
}
|
||||
|
||||
button.boarding-next-btn,
|
||||
div#boarding-popover-item .boarding-btn-group button.boarding-next-btn {
|
||||
color: #fff;
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
button.boarding-next-btn,
|
||||
div#boarding-popover-item .boarding-btn-group button.boarding-next-btn:hover {
|
||||
background-color: #007bff;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-title {
|
||||
color: #0056b3;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.dark div#boarding-popover-item .boarding-popover-title {
|
||||
color: #70b5ff;
|
||||
}
|
||||
|
||||
div#boarding-popover-item .boarding-popover-description {
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 0;
|
||||
font-weight: normal;
|
||||
}
|
85
packages/pastebar-app-ui/drop-image.html
Normal file
@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PasteBar Drop Zone</title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
overscroll-behavior: none;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Cantarell',
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings:
|
||||
'rlig' 1,
|
||||
'calt' 1;
|
||||
}
|
||||
|
||||
.drop-zone.hover {
|
||||
background-color: #e0e0e0; /* Light gray background when hovering */
|
||||
border-color: #0088cc; /* Change border color */
|
||||
color: #0088cc; /* Change text color */
|
||||
}
|
||||
|
||||
.drop-zone {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
border: 2px dashed #cccccc;
|
||||
border-radius: 12px;
|
||||
height: calc(100% - 24px);
|
||||
width: calc(100% - 24px);
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.drop-zone-text {
|
||||
font-size: 24px;
|
||||
pointer-events: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="drop-zone" id="droptarget">
|
||||
<div class="drop-zone-text">Drag and drop image file here</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const target = document.getElementById("droptarget");
|
||||
target.addEventListener("dragenter", (event) => {
|
||||
if (event.target.classList.contains("drop-zone")) {
|
||||
target.classList.add("hover");
|
||||
}
|
||||
});
|
||||
|
||||
target.addEventListener("dragleave", (event) => {
|
||||
target.classList.remove("hover");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
85
packages/pastebar-app-ui/drop-path.html
Normal file
@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PasteBar Drop Zone</title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
overscroll-behavior: none;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Cantarell',
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings:
|
||||
'rlig' 1,
|
||||
'calt' 1;
|
||||
}
|
||||
|
||||
.drop-zone.hover {
|
||||
background-color: #e0e0e0; /* Light gray background when hovering */
|
||||
border-color: #0088cc; /* Change border color */
|
||||
color: #0088cc; /* Change text color */
|
||||
}
|
||||
|
||||
.drop-zone {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
border: 2px dashed #cccccc;
|
||||
border-radius: 12px;
|
||||
height: calc(100% - 24px);
|
||||
width: calc(100% - 24px);
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.drop-zone-text {
|
||||
font-size: 24px;
|
||||
pointer-events: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="drop-zone" id="droptarget">
|
||||
<div class="drop-zone-text">Drag and drop an app, file or folder</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const target = document.getElementById("droptarget");
|
||||
target.addEventListener("dragenter", (event) => {
|
||||
if (event.target.classList.contains("drop-zone")) {
|
||||
target.classList.add("hover");
|
||||
}
|
||||
});
|
||||
|
||||
target.addEventListener("dragleave", (event) => {
|
||||
target.classList.remove("hover");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
40
packages/pastebar-app-ui/history-index.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- react-debugger, run on dev: npx react-devtools -->
|
||||
<!-- <script src="http://localhost:8097"></script> -->
|
||||
<link rel="preload" href="src/assets/TwemojiCountryFlags.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-Regular.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-Medium.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-SemiBold.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/SourceCodePro-Regular.otf.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script defer async data-domain="app.pastebar.app" src="https://stats.pastebar.app/js/script.tagged-events.local.js"></script>
|
||||
<title>PasteBar App</title>
|
||||
</head>
|
||||
<body class="bg-transparent">
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
window.isHistoryWindow = true;
|
||||
window.isMainWindow = false;
|
||||
</script>
|
||||
<script type="module" src="src/main.tsx"></script>
|
||||
<script>
|
||||
function handleDrop(e) {
|
||||
e = e || event;
|
||||
|
||||
var isWindows = navigator.platform.indexOf('Win') > -1;
|
||||
var isDropZone = e.target.classList.contains('drop-zone');
|
||||
var isNotInputOrTextarea = e.target.tagName !== "INPUT" && e.target.tagName !== "TEXTAREA";
|
||||
|
||||
if ((isWindows || isNotInputOrTextarea) && !isDropZone) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("dragover", handleDrop, false);
|
||||
window.addEventListener("drop", handleDrop, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
41
packages/pastebar-app-ui/index.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- react-debugger, run on dev: npx react-devtools -->
|
||||
<!-- <script src="http://localhost:8097"></script> -->
|
||||
<link rel="preload" href="src/assets/TwemojiCountryFlags.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-Regular.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-Medium.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/Inter-SemiBold.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="src/assets/SourceCodePro-Regular.otf.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script defer async data-domain="app.pastebar.app" src="https://stats.pastebar.app/js/script.tagged-events.local.js"></script>
|
||||
<title>PasteBar App</title>
|
||||
</head>
|
||||
<body class="bg-transparent">
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
window.isMainWindow = true;
|
||||
window.isHistoryWindow = false;
|
||||
</script>
|
||||
<script type="module" src="src/main.tsx"></script>
|
||||
<script src="assets/markdown/markdown.js" async></script>
|
||||
<script>
|
||||
function handleDrop(e) {
|
||||
e = e || event;
|
||||
|
||||
var isWindows = navigator.platform.indexOf('Win') > -1;
|
||||
var isDropZone = e.target.classList.contains('drop-zone');
|
||||
var isNotInputOrTextarea = e.target.tagName !== "INPUT" && e.target.tagName !== "TEXTAREA";
|
||||
|
||||
if ((isWindows || isNotInputOrTextarea) && !isDropZone) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("dragover", handleDrop, false);
|
||||
window.addEventListener("drop", handleDrop, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17557
packages/pastebar-app-ui/package-lock.json
generated
Normal file
190
packages/pastebar-app-ui/package.json
Normal file
@ -0,0 +1,190 @@
|
||||
{
|
||||
"name": "@pastebar/ui",
|
||||
"version": "0.3.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"start": "npm run dev",
|
||||
"build": "vite build",
|
||||
"build:ts": "tsc && vite build",
|
||||
"format": "npx prettier --write . --ignore-path .gitignore ",
|
||||
"taze": "taze major -I",
|
||||
"taze:minor": "taze minor -w",
|
||||
"preview": "vite preview",
|
||||
"audit:prod": "npm audit --omit=dev",
|
||||
"changeset": "changeset",
|
||||
"version": "changeset version"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codastic/react-positioning-portal": "^0.7.0",
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
"@dnd-kit/modifiers": "^7.0.0",
|
||||
"@dnd-kit/sortable": "^8.0.0",
|
||||
"@emotion/css": "^11.11.2",
|
||||
"@ianvs/prettier-plugin-sort-imports": "^4.1.1",
|
||||
"@preact/signals-react": "^2.0.1",
|
||||
"@radix-ui/react-accessible-icon": "^1.0.3",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
"@radix-ui/react-aspect-ratio": "^1.0.3",
|
||||
"@radix-ui/react-avatar": "^1.0.4",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"@radix-ui/react-context-menu": "^2.1.5",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-hover-card": "^1.0.7",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-menubar": "^1.0.4",
|
||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-radio-group": "^1.1.3",
|
||||
"@radix-ui/react-scroll-area": "^1.0.5",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slider": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-toast": "^1.1.5",
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-toggle-group": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@react-aria/i18n": "^3.9.0",
|
||||
"@react-aria/utils": "^3.22.0",
|
||||
"@react-stately/utils": "^3.9.0",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@tanstack/react-query": "5.25.0",
|
||||
"@tanstack/react-query-devtools": "5.25.0",
|
||||
"@tanstack/react-query-persist-client": "5.25.0",
|
||||
"@tauri-apps/api": "^1.5.3",
|
||||
"@types/node": "^20.10.0",
|
||||
"@uiw/codemirror-extensions-langs": "^4.21.21",
|
||||
"@uiw/codemirror-theme-github": "^4.21.21",
|
||||
"@uiw/codemirror-theme-vscode": "^4.21.21",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"babel-plugin-react-compiler": "^0.0.0-experimental-696af53-20240625",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"classnames": "^2.5.1",
|
||||
"clsx": "^2.0.0",
|
||||
"cmdk": "^0.2.0",
|
||||
"codemirror": "^5.65.16",
|
||||
"date-fns": "^2.30.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"dompurify": "^3.1.3",
|
||||
"dot-prop": "^8.0.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"emery": "^1.4.2",
|
||||
"emoji-picker-react": "^4.5.16",
|
||||
"eslint-plugin-react-compiler": "^0.0.0-experimental-51a85ea-20240601",
|
||||
"events": "^3.3.0",
|
||||
"facepaint": "^1.2.1",
|
||||
"framer-motion": "^10.16.5",
|
||||
"garbados-crypt": "^3.0.0-beta",
|
||||
"glob-all": "^3.3.1",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"javascript-time-ago": "^2.5.9",
|
||||
"jotai": "^2.6.0",
|
||||
"jotai-zustand": "^0.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"linkify-it": "^5.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "0.363.0",
|
||||
"markdown-wasm": "^1.2.0",
|
||||
"marked": "^12.0.0",
|
||||
"marked-terminal": "^7.0.0",
|
||||
"next-themes": "^0.2.1",
|
||||
"overlayscrollbars": "^2.4.5",
|
||||
"overlayscrollbars-react": "^0.5.3",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^18.3.1",
|
||||
"react-canvas-confetti": "^2.0.7",
|
||||
"react-compiler-runtime": "file:./scripts/react-compiler-runtime",
|
||||
"react-complex-tree": "^2.2.3",
|
||||
"react-day-picker": "^8.9.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
"react-hotkeys-hook": "^4.4.1",
|
||||
"react-html-props": "^2.0.9",
|
||||
"react-i18next": "^14.0.5",
|
||||
"react-router-dom": "^6.20.0",
|
||||
"react-sub-unsub": "^2.2.7",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
"react-time-ago": "^7.2.1",
|
||||
"react-twitter-embed": "^4.0.4",
|
||||
"react-use-hoverintent": "^1.3.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.20",
|
||||
"react-virtuoso": "^4.6.2",
|
||||
"react-window": "^1.8.10",
|
||||
"react-window-infinite-loader": "^1.0.9",
|
||||
"recharts": "^2.10.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.10.0",
|
||||
"scriptjs": "^2.5.9",
|
||||
"short-unique-id": "^5.0.3",
|
||||
"tailwind-scrollbar": "^3.0.5",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tauri-plugin-clipboard-api": "^0.5.5",
|
||||
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log",
|
||||
"tauri-plugin-positioner-api": "github:tauri-apps/tauri-plugin-positioner",
|
||||
"ts-deepmerge": "^7.0.0",
|
||||
"url-parse": "^1.5.10",
|
||||
"use-resize-observer": "^9.1.0",
|
||||
"vite-plugin-babel": "^1.2.0",
|
||||
"vite-plugin-dynamic-import": "^1.5.0",
|
||||
"vite-plugin-static-copy": "^1.0.2",
|
||||
"zod": "^3.22.2",
|
||||
"zustand": "^4.4.6",
|
||||
"zustand-logger-middleware": "^1.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.1",
|
||||
"@preact/signals-react-transform": "^0.3.1",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@tauri-apps/cli": "^1.5.6",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/linkify-it": "^3.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/marked-terminal": "^6.1.1",
|
||||
"@types/prismjs": "^1.26.3",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-window": "^1.8.8",
|
||||
"@types/react-window-infinite-loader": "^1.0.9",
|
||||
"@types/url-parse": "^1.4.11",
|
||||
"@types/use-sync-external-store": "^0.0.6",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"postcss": "^8.4.31",
|
||||
"prettier": "^3.1.0",
|
||||
"prettier-plugin-tailwindcss": "^0.5.7",
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"taze": "^0.12.2",
|
||||
"typescript": "^5.3.2",
|
||||
"vite": "^5.0.11",
|
||||
"vite-plugin-tauri": "^3.3.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-x64-gnu": "4.14.1"
|
||||
}
|
||||
}
|
6
packages/pastebar-app-ui/postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
44
packages/pastebar-app-ui/prettier.config.js
Normal file
@ -0,0 +1,44 @@
|
||||
/** @type {import('prettier').Config} */
|
||||
module.exports = {
|
||||
printWidth: 90,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
bracketSpacing: true,
|
||||
arrowParens: 'avoid',
|
||||
endOfLine: 'auto',
|
||||
trailingComma: 'es5',
|
||||
importOrder: [
|
||||
'^(react/(.*)$)|^(react$)',
|
||||
'<THIRD_PARTY_MODULES>',
|
||||
'',
|
||||
'^~/app/(.*)$',
|
||||
'',
|
||||
'',
|
||||
'^~/lib/(.*)$',
|
||||
'',
|
||||
'^~/components/ui/(.*)$',
|
||||
'^~/components/(.*)$',
|
||||
'',
|
||||
'^~/store/(.*)$',
|
||||
'^~/config/(.*)$',
|
||||
'',
|
||||
'^~/hooks/(.*)$',
|
||||
'^~/constants/(.*)$',
|
||||
'',
|
||||
'^~/types$',
|
||||
'^~/types/(.*)$',
|
||||
'',
|
||||
'^~/styles/(.*)$',
|
||||
'',
|
||||
'^[./]',
|
||||
],
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
importOrderBuiltinModulesToTop: true,
|
||||
importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
|
||||
importOrderMergeDuplicateImports: true,
|
||||
importOrderCombineTypeAndValueImports: true,
|
||||
plugins: ['@ianvs/prettier-plugin-sort-imports'],
|
||||
}
|
216
packages/pastebar-app-ui/scripts/i18n-vite-loaded/loader.ts
Normal file
@ -0,0 +1,216 @@
|
||||
import path from 'node:path'
|
||||
import { setProperty } from 'dot-prop'
|
||||
import { marked } from 'marked'
|
||||
import TerminalRenderer from 'marked-terminal'
|
||||
import { merge } from 'ts-deepmerge'
|
||||
import { createLogger, LogLevel, Plugin } from 'vite'
|
||||
|
||||
import {
|
||||
assertExistence,
|
||||
enumerateLangs,
|
||||
findAll,
|
||||
jsNormalizedLang,
|
||||
loadAndParse,
|
||||
resolvedVirtualModuleId,
|
||||
resolvePaths,
|
||||
virtualModuleId,
|
||||
} from './utils'
|
||||
|
||||
marked.setOptions({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
renderer: new TerminalRenderer(),
|
||||
})
|
||||
|
||||
// unfortunately not exported
|
||||
export const LogLevels: Record<LogLevel, number> = {
|
||||
silent: 0,
|
||||
error: 1,
|
||||
warn: 2,
|
||||
info: 3,
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
/**
|
||||
* Set to 'info' for noisy information.
|
||||
*
|
||||
* Default: 'warn'
|
||||
*/
|
||||
logLevel?: LogLevel
|
||||
|
||||
/**
|
||||
* Glob patterns to match files
|
||||
*
|
||||
* Default: ['**\/*.json', '**\/*.yml', '**\/*.yaml']
|
||||
*/
|
||||
include?: string[]
|
||||
|
||||
/**
|
||||
* Locale top level directory paths ordered from least specialized to most specialized
|
||||
* e.g. lib locale -> app locale
|
||||
*
|
||||
* Locales loaded later will overwrite any duplicated key via a deep merge strategy.
|
||||
*/
|
||||
paths: string[]
|
||||
|
||||
/**
|
||||
* Default: none
|
||||
*/
|
||||
namespaceResolution?: 'basename' | 'relativePath'
|
||||
}
|
||||
|
||||
export interface ResBundle {
|
||||
[key: string]: string | object
|
||||
}
|
||||
|
||||
// for fast match on hot reloading check?
|
||||
let loadedFiles: string[] = []
|
||||
let allLangs: Set<string> = new Set()
|
||||
|
||||
const factory = (options: Options) => {
|
||||
const log = createLogger(options.logLevel || 'warn', { prefix: '[i18next-loader]' })
|
||||
|
||||
function loadLocales() {
|
||||
const localeDirs = resolvePaths(options.paths, process.cwd())
|
||||
assertExistence(localeDirs)
|
||||
|
||||
//
|
||||
let appResBundle: ResBundle = {}
|
||||
loadedFiles = [] // reset
|
||||
log.info('Bundling locales (ordered least specific to most):', {
|
||||
timestamp: true,
|
||||
})
|
||||
localeDirs.forEach(nextLocaleDir => {
|
||||
// all subdirectories match language codes
|
||||
const langs = enumerateLangs(nextLocaleDir)
|
||||
allLangs = new Set([...allLangs, ...langs])
|
||||
for (const lang of langs) {
|
||||
const resBundle: ResBundle = {}
|
||||
resBundle[lang] = {}
|
||||
|
||||
const langDir = path.join(nextLocaleDir, lang) // top level lang dir
|
||||
const langFiles = findAll(
|
||||
options.include || ['**/*.json', '**/*.yml', '**/*.yaml'],
|
||||
langDir
|
||||
) // all lang files matching patterns in langDir
|
||||
|
||||
for (const langFile of langFiles) {
|
||||
loadedFiles.push(langFile) // track for fast hot reload matching
|
||||
log.info('\t' + langFile, {
|
||||
timestamp: true,
|
||||
})
|
||||
|
||||
const content = loadAndParse(langFile)
|
||||
|
||||
if (options.namespaceResolution) {
|
||||
let namespaceFilepath: string = langFile
|
||||
if (options.namespaceResolution === 'relativePath') {
|
||||
namespaceFilepath = path.relative(path.join(nextLocaleDir, lang), langFile)
|
||||
} else if (options.namespaceResolution === 'basename') {
|
||||
namespaceFilepath = path.basename(langFile)
|
||||
}
|
||||
const extname = path.extname(langFile)
|
||||
const namespaceParts = namespaceFilepath.replace(extname, '').split(path.sep)
|
||||
const namespace = [lang].concat(namespaceParts).join('.')
|
||||
setProperty(resBundle, namespace, content)
|
||||
} else {
|
||||
resBundle[lang] = content
|
||||
}
|
||||
appResBundle = merge(appResBundle, resBundle)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// one bundle - works, no issues with dashes in names
|
||||
// const bundle = `export default ${JSON.stringify(appResBundle)}`
|
||||
|
||||
// named exports, requires manipulation of names
|
||||
let namedBundle = ''
|
||||
for (const lang of allLangs) {
|
||||
namedBundle += `export const ${jsNormalizedLang(lang)} = ${JSON.stringify(
|
||||
appResBundle[lang]
|
||||
)}\n`
|
||||
}
|
||||
let defaultExport = 'const resources = { \n'
|
||||
for (const lang of allLangs) {
|
||||
defaultExport += `"${lang}": ${jsNormalizedLang(lang)},\n`
|
||||
}
|
||||
defaultExport += '}'
|
||||
defaultExport += '\nexport default resources\n'
|
||||
|
||||
const bundle = namedBundle + defaultExport
|
||||
|
||||
log.info(`Locales module '${resolvedVirtualModuleId}':`, {
|
||||
timestamp: true,
|
||||
})
|
||||
|
||||
// emulate log.info for our marked terminal output
|
||||
if (LogLevels[options.logLevel || 'warn'] >= LogLevels['info']) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
marked(`
|
||||
\`\`\`js
|
||||
${bundle}
|
||||
\`\`\`
|
||||
`)
|
||||
)
|
||||
}
|
||||
return bundle
|
||||
}
|
||||
|
||||
const plugin: Plugin = {
|
||||
name: 'vite-plugin-i18next-loader', // required, will show up in warnings and errors
|
||||
resolveId(id) {
|
||||
if (id === virtualModuleId) {
|
||||
return resolvedVirtualModuleId
|
||||
}
|
||||
return null
|
||||
},
|
||||
load(id) {
|
||||
if (id !== resolvedVirtualModuleId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const bundle = loadLocales()
|
||||
for (const file of loadedFiles) {
|
||||
this.addWatchFile(file)
|
||||
}
|
||||
return bundle
|
||||
},
|
||||
|
||||
/**
|
||||
* Watch translation message files and trigger an update.
|
||||
*
|
||||
* @see https://github.com/vitejs/vite/issues/6871 <- as is implemented now, with a full reload
|
||||
* @see https://github.com/vitejs/vite/pull/10333 <- TODO this is the one that would be easiest and may not be a full reload
|
||||
*/
|
||||
handleHotUpdate({ file, server }) {
|
||||
if (loadedFiles.includes(file)) {
|
||||
log.info(`Changed locale file: ${file}`, {
|
||||
timestamp: true,
|
||||
})
|
||||
|
||||
const { moduleGraph, ws } = server
|
||||
const module = moduleGraph.getModuleById(resolvedVirtualModuleId)
|
||||
if (module) {
|
||||
log.info(
|
||||
`Invalidated module '${resolvedVirtualModuleId}' - sending full reload`,
|
||||
{
|
||||
timestamp: true,
|
||||
}
|
||||
)
|
||||
moduleGraph.invalidateModule(module)
|
||||
// server.reloadModule(module) // TODO with vite 3.2 see https://github.com/vitejs/vite/pull/10333, may also be able to remove full reload
|
||||
if (ws) {
|
||||
ws.send({
|
||||
type: 'full-reload',
|
||||
path: '*',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
return plugin
|
||||
}
|
||||
|
||||
export default factory
|
55
packages/pastebar-app-ui/scripts/i18n-vite-loaded/utils.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import globAll from 'glob-all'
|
||||
import yaml from 'js-yaml'
|
||||
|
||||
// don't export these from index so the external types are cleaner
|
||||
export const virtualModuleId = 'virtual:i18next-loader'
|
||||
export const resolvedVirtualModuleId = '\0' + virtualModuleId
|
||||
|
||||
export function jsNormalizedLang(lang: string) {
|
||||
return lang.replace(/-/, '_')
|
||||
}
|
||||
|
||||
export function enumerateLangs(dir: string) {
|
||||
return fs.readdirSync(dir).filter(function (file) {
|
||||
return fs.statSync(path.join(dir, file)).isDirectory()
|
||||
})
|
||||
}
|
||||
|
||||
//https://github.com/jpillora/node-glob-all#usage
|
||||
export function findAll(globs: string | string[], cwd: string): string[] {
|
||||
const globArray = Array.isArray(globs) ? globs : [globs]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
return globAll.sync(globArray, { cwd, realpath: true }) as string[]
|
||||
}
|
||||
|
||||
export function resolvePaths(paths: string[], cwd: string) {
|
||||
return paths.map(override => {
|
||||
if (path.isAbsolute(override)) {
|
||||
return override
|
||||
} else {
|
||||
return path.join(cwd, override)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function assertExistence(paths: string[]) {
|
||||
for (const dir of paths) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
throw new Error(`Directory does not exist: ${dir}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function loadAndParse(langFile: string) {
|
||||
const fileContent = String(fs.readFileSync(langFile))
|
||||
const extname = path.extname(langFile)
|
||||
let parsedContent: string
|
||||
if (extname === '.yaml' || extname === '.yml') {
|
||||
parsedContent = yaml.load(fileContent) as string
|
||||
} else {
|
||||
parsedContent = JSON.parse(fileContent)
|
||||
}
|
||||
return parsedContent
|
||||
}
|
23
packages/pastebar-app-ui/scripts/react-compiler-runtime/index.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// lib/react-compiler-runtime/index.js
|
||||
|
||||
import { useState } from 'react'
|
||||
|
||||
const $empty = Symbol.for('react.memo_cache_sentinel')
|
||||
/**
|
||||
* DANGER: this hook is NEVER meant to be called directly!
|
||||
*
|
||||
* Note that this is a temporary userspace implementation of this function
|
||||
* from React 19. It is not as efficient and may invalidate more frequently
|
||||
* than the official API. Please upgrade to React 19 as soon as you can.
|
||||
**/
|
||||
export function c(size) {
|
||||
return useState(() => {
|
||||
const $ = new Array(size)
|
||||
for (let ii = 0; ii < size; ii++) {
|
||||
$[ii] = $empty
|
||||
}
|
||||
// @ts-ignore
|
||||
$[$empty] = true
|
||||
return $
|
||||
})[0]
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "react-compiler-runtime",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
function cartesian(array) {
|
||||
function* cartesian(head, ...tail) {
|
||||
let remainder = tail.length ? cartesian(...tail) : [[]]
|
||||
for (let r of remainder) for (let h of head) yield [h, ...r]
|
||||
}
|
||||
|
||||
return [...cartesian(...array)]
|
||||
}
|
||||
|
||||
function deepKeys(object, separator = '.', prefix = '') {
|
||||
return Object.keys(object).reduce((result, key) => {
|
||||
if (Array.isArray(object[key])) {
|
||||
return [...result, prefix + key];
|
||||
} else if (typeof object[key] === 'object' && object[key] !== null) {
|
||||
return [...result, ...deepKeys(object[key], separator, prefix + key + separator)];
|
||||
}
|
||||
|
||||
return [...result, prefix + key];
|
||||
}, []);
|
||||
}
|
||||
|
||||
const extractTokens = pattern =>
|
||||
pattern.split(/(?={[^}]+})|(?<={[^}]+})/)
|
||||
|
||||
const expandTokens = theme => tokens => {
|
||||
return tokens.map(token => {
|
||||
if(token.startsWith('{')) {
|
||||
const cleanToken = token.replace(/{|}/g, '')
|
||||
if(cleanToken.includes('.')) {
|
||||
const color = cleanToken.split('.')[1]
|
||||
const colorToken = {
|
||||
[color]: theme(cleanToken, {})
|
||||
}
|
||||
return deepKeys(colorToken, '-')
|
||||
}
|
||||
return deepKeys(theme(cleanToken, {}), '-')
|
||||
} else {
|
||||
return [token]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const mapToClasses = expanded =>
|
||||
expanded.map(values =>
|
||||
values.join('').replace('-DEFAULT', ''))
|
||||
|
||||
module.exports = theme => patterns => {
|
||||
return patterns // ["text-{gray}", …]
|
||||
.map(extractTokens) // [["text", "{gray}"], …]
|
||||
.map(expandTokens(theme)) // [[["text"], ["gray-100", "gray-200",…]], …]
|
||||
.map(cartesian) // [[["text", "gray-100"], ["text", "gray-200"], …], …]
|
||||
.flatMap(mapToClasses) // ["text-gray-100", "text-gray-200",…]
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
const fs = require('fs')
|
||||
const pathfn = require('path')
|
||||
const plugin = require('tailwindcss/plugin')
|
||||
const generator = require('./generator')
|
||||
const crypto = require('crypto')
|
||||
|
||||
module.exports = plugin.withOptions(({ path = '', patterns = [] }) => ({ theme }) => {
|
||||
const safeList = generator(theme)(patterns).join('\n')
|
||||
console.log('path', pathfn.resolve(path))
|
||||
|
||||
try {
|
||||
const currentSafeList = fs.readFileSync(pathfn.resolve(path)).toString()
|
||||
|
||||
const hash = crypto.createHash('md5').update(JSON.stringify(safeList)).digest('hex')
|
||||
const prevHash = crypto
|
||||
.createHash('md5')
|
||||
.update(JSON.stringify(currentSafeList))
|
||||
.digest('hex')
|
||||
|
||||
if (hash !== prevHash) {
|
||||
return fs.writeFileSync(path, safeList)
|
||||
}
|
||||
} catch (e) {
|
||||
fs.writeFileSync(path, safeList)
|
||||
}
|
||||
})
|
520
packages/pastebar-app-ui/src/App.tsx
Normal file
@ -0,0 +1,520 @@
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
import { type } from '@tauri-apps/api/os'
|
||||
import { invoke } from '@tauri-apps/api/tauri'
|
||||
import { appWindow, LogicalSize, WebviewWindow } from '@tauri-apps/api/window'
|
||||
import { NavBar } from '~/layout/NavBar'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
|
||||
|
||||
import { ThemeProvider } from '~/components/theme-provider'
|
||||
|
||||
import useKeyPressAlt from '~/hooks/use-keypress-alt'
|
||||
import { useSignal } from '~/hooks/use-signal'
|
||||
|
||||
import debounce from './components/libs/react-resizable-panels/src/utils/debounce'
|
||||
import { Button, Flex } from './components/ui'
|
||||
import { useToast } from './components/ui/use-toast'
|
||||
import { copiedItem, pastedItem } from './hooks/use-copypaste-history-item'
|
||||
import { NavBarHistoryWindow } from './layout/NavBarHistoryWindow'
|
||||
import { appReady } from './lib/commands'
|
||||
import {
|
||||
APP_TOURS,
|
||||
clipboardHistoryStoreAtom,
|
||||
isAppLocked,
|
||||
listenToAudioPlayerEvents,
|
||||
listenToSettingsStoreEvents,
|
||||
listenToSignalStoreEvents,
|
||||
openOnBoardingTourName,
|
||||
openOSXSystemPermissionsModal,
|
||||
settingsStoreAtom,
|
||||
themeStoreAtom,
|
||||
uiStoreAtom,
|
||||
} from './store'
|
||||
|
||||
const appIdleEvents = ['mousemove', 'keydown', 'scroll', 'keypress', 'mousedown']
|
||||
|
||||
function App() {
|
||||
useKeyPressAlt()
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const navigate = useNavigate()
|
||||
const appLocation = useLocation()
|
||||
const uiStore = useAtomValue(uiStoreAtom)
|
||||
const appIdleTimeAutoLock = useSignal<null | number>(null)
|
||||
const settingsStore = useAtomValue(settingsStoreAtom)
|
||||
const themeStore = useAtomValue(themeStoreAtom)
|
||||
const clipboardHistoryStore = useAtomValue(clipboardHistoryStoreAtom)
|
||||
const idleTimerRef = useRef<ReturnType<typeof setTimeout>>()
|
||||
const { i18n, t } = useTranslation()
|
||||
const { toast } = useToast()
|
||||
const historyWindowOpening = useSignal(false)
|
||||
|
||||
const handleActivity = useCallback(
|
||||
debounce(() => {
|
||||
if (appIdleTimeAutoLock.value === null || isAppLocked.value) {
|
||||
return
|
||||
}
|
||||
isAppLocked.value = false
|
||||
if (idleTimerRef.current) {
|
||||
clearTimeout(idleTimerRef.current)
|
||||
}
|
||||
idleTimerRef.current = setTimeout(() => {
|
||||
isAppLocked.value = true
|
||||
}, appIdleTimeAutoLock.value)
|
||||
}, 1000),
|
||||
[appIdleTimeAutoLock]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isAppLocked.value) {
|
||||
settingsStore.setIsAppLocked(true)
|
||||
} else {
|
||||
settingsStore.setIsAppLocked(false)
|
||||
}
|
||||
}, [isAppLocked.value])
|
||||
|
||||
useEffect(() => {
|
||||
const appReadyResponse = appReady()
|
||||
|
||||
appReadyResponse.then(res => {
|
||||
if (res === null) return
|
||||
|
||||
try {
|
||||
const { constants, settings, permissionstrusted } = JSON.parse(res)
|
||||
|
||||
const {
|
||||
app_dev_data_dir: appDevDataDir,
|
||||
app_data_dir: appDataDir,
|
||||
app_detect_languages_supported: appDetectLanguageSupport,
|
||||
} = constants
|
||||
|
||||
if (
|
||||
settings.userSelectedLanguage?.valueText &&
|
||||
settings.userSelectedLanguage?.valueText !== '' &&
|
||||
i18n.language !== settings.userSelectedLanguage?.valueText
|
||||
) {
|
||||
i18n.changeLanguage(settings.userSelectedLanguage.valueText)
|
||||
}
|
||||
|
||||
if (
|
||||
settings.userSelectedLanguage?.valueText === '' &&
|
||||
i18n.resolvedLanguage !== 'en'
|
||||
) {
|
||||
i18n.changeLanguage(i18n.resolvedLanguage)
|
||||
}
|
||||
|
||||
settingsStore.initSettings({
|
||||
appDataDir: import.meta.env.TAURI_DEBUG ? appDevDataDir : appDataDir,
|
||||
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
|
||||
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
|
||||
isFirstRun: settings.isFirstRun?.valueBool,
|
||||
isFirstRunAfterUpdate: settings.isFirstRunAfterUpdate?.valueBool,
|
||||
isHistoryDetectLanguageEnabled:
|
||||
settings.isHistoryDetectLanguageEnabled?.valueBool,
|
||||
historyDetectLanguageMinLines: settings.historyDetectLanguageMinLines?.valueInt,
|
||||
historyExclusionList: settings.historyExclusionList?.valueText,
|
||||
isExclusionListEnabled: settings.isExclusionListEnabled?.valueBool,
|
||||
isAutoMaskWordsListEnabled: settings.isAutoMaskWordsListEnabled?.valueBool,
|
||||
autoMaskWordsList: settings.autoMaskWordsList?.valueText,
|
||||
historyDetectLanguagesPrioritizedList:
|
||||
settings.historyDetectLanguagesPrioritizedList?.valueText.split(','),
|
||||
historyDetectLanguagesEnabledList:
|
||||
settings.historyDetectLanguagesEnabledList?.valueText.split(','),
|
||||
appToursCompletedList: settings.appToursCompletedList?.valueText.split(','),
|
||||
appToursSkippedList: settings.appToursSkippedList?.valueText.split(','),
|
||||
isHistoryAutoUpdateOnCaputureEnabled:
|
||||
settings.isHistoryAutoUpdateOnCaputureEnabled?.valueBool,
|
||||
isHistoryEnabled: settings.isHistoryEnabled?.valueBool,
|
||||
isAutoClearSettingsEnabled: settings.isAutoClearSettingsEnabled?.valueBool,
|
||||
autoClearSettingsDuration: settings.autoClearSettingsDuration?.valueInt,
|
||||
autoClearSettingsDurationType:
|
||||
settings.autoClearSettingsDurationType?.valueText,
|
||||
copyPasteDelay: settings.copyPasteDelay?.valueInt,
|
||||
copyPasteSequencePinnedDelay:
|
||||
settings.copyPasteSequencePinnedDelay?.valueInt ?? 3,
|
||||
copyPasteSequenceIsReversOrder:
|
||||
settings.copyPasteSequenceIsReversOrder?.valueBool,
|
||||
pasteSequenceEachSeparator: settings.pasteSequenceEachSeparator?.valueText,
|
||||
isAutoCloseOnCopyPaste: settings.isAutoCloseOnCopyPaste?.valueBool,
|
||||
isAutoPreviewLinkCardsEnabled:
|
||||
settings.isAutoPreviewLinkCardsEnabled?.valueBool,
|
||||
isAutoGenerateLinkCardsEnabled:
|
||||
settings.isAutoGenerateLinkCardsEnabled?.valueBool,
|
||||
isClipNotesHoverCardsEnabled: settings.isClipNotesHoverCardsEnabled?.valueBool,
|
||||
clipNotesHoverCardsDelayMS: settings.clipNotesHoverCardsDelayMS?.valueInt,
|
||||
clipNotesMaxWidth: settings.clipNotesMaxWidth?.valueInt,
|
||||
clipNotesMaxHeight: settings.clipNotesMaxHeight?.valueInt,
|
||||
isAutoFavoriteOnDoubleCopyEnabled:
|
||||
settings.isAutoFavoriteOnDoubleCopyEnabled?.valueBool,
|
||||
|
||||
isIdleScreenAutoLockEnabled: settings.isIdleScreenAutoLockEnabled?.valueBool,
|
||||
idleScreenAutoLockTimeInMinutes:
|
||||
settings.idleScreenAutoLockTimeInMinutes?.valueInt,
|
||||
isShowHistoryCaptureOnLockedScreen:
|
||||
settings.isShowHistoryCaptureOnLockedScreen?.valueBool,
|
||||
screenLockPassCode: settings.screenLockPassCode?.valueText,
|
||||
screenLockPassCodeLength: settings.screenLockPassCodeLength?.valueInt,
|
||||
screenLockRecoveryPasswordMasked:
|
||||
settings.screenLockRecoveryPasswordMasked?.valueText,
|
||||
isAppLocked: settings.isAppLocked?.valueBool,
|
||||
isScreenLockPassCodeRequireOnStart:
|
||||
settings.isScreenLockPassCodeRequireOnStart?.valueBool,
|
||||
|
||||
isSearchNameOrLabelOnly: settings.isSearchNameOrLabelOnly?.valueBool,
|
||||
isSkipAutoStartPrompt: settings.isSkipAutoStartPrompt?.valueBool,
|
||||
isShowCollectionNameOnNavBar: settings.isShowCollectionNameOnNavBar?.valueBool,
|
||||
isShowDisabledCollectionsOnNavBarMenu:
|
||||
settings.isShowDisabledCollectionsOnNavBarMenu?.valueBool,
|
||||
userSelectedLanguage: settings.userSelectedLanguage?.valueText,
|
||||
isAppReady: true,
|
||||
})
|
||||
settingsStore.initConstants({
|
||||
APP_DETECT_LANGUAGES_SUPPORTED: appDetectLanguageSupport,
|
||||
})
|
||||
type().then(osType => {
|
||||
if (osType === 'Windows_NT' && settings.copyPasteDelay?.valueInt === 0) {
|
||||
settingsStore.updateSetting('copyPasteDelay', 2)
|
||||
}
|
||||
})
|
||||
|
||||
if (settings.isFirstRun?.valueBool) {
|
||||
appWindow.setSize(new LogicalSize(1105, 710))
|
||||
settingsStore.updateSetting('isFirstRun', false)
|
||||
}
|
||||
|
||||
if (
|
||||
settings.isIdleScreenAutoLockEnabled?.valueBool &&
|
||||
settings.idleScreenAutoLockTimeInMinutes?.valueInt > 0
|
||||
) {
|
||||
appIdleEvents.forEach(event => window.addEventListener(event, handleActivity))
|
||||
appIdleTimeAutoLock.value =
|
||||
settings.idleScreenAutoLockTimeInMinutes?.valueInt * 1000 * 60
|
||||
}
|
||||
|
||||
if (
|
||||
settings.isAppLocked?.valueBool ||
|
||||
settings.isScreenLockPassCodeRequireOnStart?.valueBool
|
||||
) {
|
||||
isAppLocked.value = true
|
||||
}
|
||||
|
||||
if (
|
||||
!settings.appToursCompletedList?.valueText
|
||||
.split(',')
|
||||
.includes(APP_TOURS.historyPanelTour) &&
|
||||
!settings.appToursSkippedList?.valueText
|
||||
.split(',')
|
||||
.includes(APP_TOURS.historyPanelTour) &&
|
||||
permissionstrusted
|
||||
) {
|
||||
const welcomeTour = toast({
|
||||
title: `${t('Welcome to PasteBar', { ns: 'help' })} 🎉`,
|
||||
id: 'welcome-tour',
|
||||
duration: 0,
|
||||
description: (
|
||||
<>
|
||||
{t(`WelcomeDescription`, { ns: 'help' })}
|
||||
<Flex className="mt-3">{t(`WelcomeTour`, { ns: 'help' })}</Flex>
|
||||
<Flex className="justify-between">
|
||||
<Button
|
||||
className="bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800 hover:bg-blue-600 px-4 mt-3 text-white"
|
||||
onClick={() => {
|
||||
openOnBoardingTourName.value = APP_TOURS.historyPanelTour
|
||||
welcomeTour?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Start Tour', { ns: 'help' })}
|
||||
</Button>
|
||||
<Flex className="gap-3">
|
||||
<Button
|
||||
variant="light"
|
||||
className="text-gray-800 px-4 mt-3 dark:bg-slate-800 dark:text-gray-400 hover:dark:text-gray-300"
|
||||
onClick={() => {
|
||||
welcomeTour?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Later', { ns: 'help' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="text-gray-800 px-4 mt-3"
|
||||
onClick={() => {
|
||||
welcomeTour?.dismiss()
|
||||
const tours = Object.values(APP_TOURS)
|
||||
settingsStore.setAppToursSkippedList([...tours])
|
||||
}}
|
||||
>
|
||||
{t('Skip All Tours', { ns: 'help' })}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
if (!settings.isSkipAutoStartPrompt?.valueBool) {
|
||||
invoke('is_autostart_enabled').then(async isAutoStartEnabled => {
|
||||
if (!isAutoStartEnabled) {
|
||||
try {
|
||||
await invoke('autostart', { enabled: true })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (permissionstrusted === false) {
|
||||
openOSXSystemPermissionsModal.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
|
||||
// Set OS type
|
||||
type().then(osType => {
|
||||
uiStore.setOSType(osType)
|
||||
})
|
||||
|
||||
appWindow.innerSize().then(size => {
|
||||
const { width, height } = size
|
||||
if (width < 740 || height < 600) {
|
||||
appWindow.setSize(new LogicalSize(750, 620))
|
||||
}
|
||||
})
|
||||
|
||||
// Set Hardware Id
|
||||
if (themeStore.deviceId === '') {
|
||||
invoke('get_device_id').then(id => {
|
||||
const hwid = id as string
|
||||
themeStore.setDeviceId(hwid)
|
||||
})
|
||||
}
|
||||
|
||||
if (!import.meta.env.TAURI_DEBUG || import.meta.env.VITE_ENABLE_DEV_AUTO_UPDATER) {
|
||||
// check for app update on app start
|
||||
settingsStore.checkForUpdate()
|
||||
}
|
||||
|
||||
const listenToClipboardUnlisten = listen(
|
||||
'clipboard://clipboard-monitor/update',
|
||||
async e => {
|
||||
if (e.payload === 'clipboard update') {
|
||||
if (copiedItem.value) {
|
||||
await new Promise(resolve => setTimeout(resolve, 600))
|
||||
copiedItem.value = ''
|
||||
}
|
||||
if (pastedItem.value) {
|
||||
await new Promise(resolve => setTimeout(resolve, 600))
|
||||
pastedItem.value = ''
|
||||
}
|
||||
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['get_clipboard_history'],
|
||||
})
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['get_clipboard_history_pinned'],
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
clipboardHistoryStore.scrollToTopHistoryList()
|
||||
}, 100)
|
||||
|
||||
setTimeout(() => {
|
||||
queryClient.setQueryData(
|
||||
['get_clipboard_history'],
|
||||
(oldData: { pages: unknown[]; pageParams: unknown[] }) => {
|
||||
if (!oldData) return undefined
|
||||
return {
|
||||
...oldData,
|
||||
pages: oldData.pages.slice(0, 1),
|
||||
pageParams: oldData.pageParams.slice(0, 1),
|
||||
}
|
||||
}
|
||||
)
|
||||
}, 1000)
|
||||
|
||||
invoke('build_system_menu')
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const listenToClipsUnlisten = listen('clips://clips-monitor/update', async e => {
|
||||
if (e.payload === 'update') {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['get_active_collection_with_clips'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const listenToWindowCloseUnlisten = listen('window-events', e => {
|
||||
if (e.payload === 'history-window-closed') {
|
||||
uiStore.setIsSplitPanelView(false)
|
||||
} else if (e.payload === 'main-window-hide') {
|
||||
uiStore.setIsHideMainWindow(true)
|
||||
} else if (e.payload === 'main-window-show') {
|
||||
uiStore.setIsHideMainWindow(false)
|
||||
}
|
||||
})
|
||||
|
||||
const listenToOSXPermissionUnlisten = listen('macosx-permissions-modal', e => {
|
||||
if (e.payload === 'show') {
|
||||
openOSXSystemPermissionsModal.value = true
|
||||
}
|
||||
})
|
||||
|
||||
const listenToSettingUnlisten = listen('setting:update', e => {
|
||||
const { name, value_bool } = e.payload as {
|
||||
name: string
|
||||
value: boolean | string | number
|
||||
value_bool?: boolean
|
||||
value_number?: number
|
||||
value_string?: string
|
||||
}
|
||||
|
||||
if (name === 'isHistoryEnabled') {
|
||||
settingsStore.updateSetting('isHistoryEnabled', Boolean(value_bool))
|
||||
}
|
||||
})
|
||||
|
||||
const listenToMenuUnlisten = listen('menu:add_first_menu_item', () => {
|
||||
navigate('/menu', { replace: true })
|
||||
})
|
||||
|
||||
const listenToNavigateUnlisten = listen('navigate-main', e => {
|
||||
const { location, isSetFocus } = e.payload as {
|
||||
location: string
|
||||
isSetFocus: boolean
|
||||
}
|
||||
if (window.isMainWindow && location !== appLocation.pathname) {
|
||||
appWindow.show()
|
||||
if (isSetFocus) {
|
||||
appWindow.setFocus()
|
||||
}
|
||||
navigate(location, { replace: true })
|
||||
}
|
||||
})
|
||||
|
||||
i18n.on('languageChanged', async function () {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['get_clipboard_history'],
|
||||
})
|
||||
})
|
||||
|
||||
window.addEventListener('unhandledrejection', event => {
|
||||
console.error('Unhandled promise rejection:', event)
|
||||
})
|
||||
|
||||
window.addEventListener('contextmenu', e => {
|
||||
if (!import.meta.env.TAURI_DEBUG) {
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
listenToNavigateUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToSignalStoreEvents.then(unlisten => {
|
||||
if (!import.meta.env.TAURI_DEBUG) {
|
||||
unlisten()
|
||||
}
|
||||
})
|
||||
|
||||
listenToSettingsStoreEvents.then(unlisten => {
|
||||
if (!import.meta.env.TAURI_DEBUG) {
|
||||
unlisten()
|
||||
}
|
||||
})
|
||||
|
||||
listenToAudioPlayerEvents.then(unlisten => {
|
||||
if (!import.meta.env.TAURI_DEBUG) {
|
||||
unlisten()
|
||||
}
|
||||
})
|
||||
|
||||
listenToWindowCloseUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToClipboardUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToMenuUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToClipsUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToSettingUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
listenToOSXPermissionUnlisten.then(unlisten => {
|
||||
unlisten()
|
||||
})
|
||||
|
||||
if (idleTimerRef.current) {
|
||||
clearTimeout(idleTimerRef.current)
|
||||
}
|
||||
appIdleEvents.forEach(event => window.removeEventListener(event, handleActivity))
|
||||
}
|
||||
}, [])
|
||||
|
||||
const uiState = useAtomValue(uiStoreAtom)
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.style.fontSize = uiState.fontSize
|
||||
}, [uiState.fontSize])
|
||||
|
||||
useEffect(() => {
|
||||
if (uiState.isSplitPanelView && window.isMainWindow) {
|
||||
const openHistoryWindow = async () => {
|
||||
invoke('open_history_window', { width: 0 }).then(() => {
|
||||
historyWindowOpening.value = false
|
||||
setTimeout(() => {
|
||||
historyWindow?.setFocus()
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
const historyWindow = WebviewWindow.getByLabel('history')
|
||||
if (!historyWindow && !historyWindowOpening.value) {
|
||||
historyWindowOpening.value = true
|
||||
openHistoryWindow()
|
||||
}
|
||||
setTimeout(() => {
|
||||
historyWindow?.setFocus()
|
||||
}, 300)
|
||||
}
|
||||
}, [uiState.isSplitPanelView])
|
||||
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<div className={`bg-transparent ${uiStore.isMacOSX ? 'p-0' : 'p-1'} rounded-md`}>
|
||||
<div
|
||||
className={`border overflow-hidden ${
|
||||
uiStore.isMacOSX
|
||||
? 'rounded-lg shadow-window border-gray-100 dark:border-gray-800'
|
||||
: 'rounded-md _shadow-window border-gray-300 dark:border-gray-800 '
|
||||
} relative`}
|
||||
>
|
||||
{window.isHistoryWindow ? <NavBarHistoryWindow /> : <NavBar />}
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
BIN
packages/pastebar-app-ui/src/assets/Inter-Bold.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/Inter-Medium.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/Inter-Regular.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/Inter-SemiBold.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/InterVariable.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/SourceCodePro-Bold.otf.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/SourceCodePro-It.otf.woff2
Normal file
BIN
packages/pastebar-app-ui/src/assets/TwemojiCountryFlags.woff2
Normal file
After Width: | Height: | Size: 5.5 MiB |
After Width: | Height: | Size: 3.1 MiB |
20
packages/pastebar-app-ui/src/assets/icons/add-path-popup.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function AddPathPopup(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="m6.033 4.294-.007 7.865M21.25 10.12v-3c0-1.16-.84-2-2-2h-7m-9 9v2c0 1.05.95 2 2 2h3" />
|
||||
<rect width="10" height="7" x="11.75" y="12.707" ry="2" />
|
||||
<path d="m2.25 8.089 7.928.007" />
|
||||
</svg>
|
||||
)
|
||||
}
|
31
packages/pastebar-app-ui/src/assets/icons/blank-square.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function BlankIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||
|
||||
<rect
|
||||
x="6.881"
|
||||
y="6.83"
|
||||
width="10.2"
|
||||
height="10.2"
|
||||
className="opacity-50"
|
||||
stroke="none"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
22
packages/pastebar-app-ui/src/assets/icons/broken-image.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function BrokenImageIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '14px'}
|
||||
className={props.className}
|
||||
height={props.height ?? '14px'}
|
||||
viewBox="30.325 6.289 29.119 25.859"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke="none"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M40.554 17.082c0-.309-.073-.627-.195-.917-.123-.29-.296-.553-.496-.754-.201-.2-.464-.373-.754-.495-.29-.123-.608-.195-.917-.195-.196 0-.406.03-.609.084-.204.055-.401.134-.571.232-.372.215-.667.541-.869.906-.203.365-.312.769-.312 1.139s.109.774.312 1.139c.202.365.497.692.869.906.371.214.801.307 1.219.299.417-.007.822-.114 1.142-.299.32-.185.616-.482.831-.84.215-.358.35-.776.35-1.205Zm-4.369-2.007c.271-.27.568-.484.9-.627.332-.143.699-.217 1.108-.207.261-.004.503.026.736.09.234.064.458.16.684.29.496.287.85.649 1.082 1.067.231.417.338.889.338 1.394 0 .506-.107.977-.338 1.394-.232.417-.586.779-1.082 1.065-.496.287-.987.414-1.464.405-.477-.008-.939-.151-1.377-.405-.438-.253-.803-.581-1.053-.99-.251-.408-.387-.896-.367-1.469-.01-.409.063-.776.206-1.108.144-.332.357-.629.627-.899Z" />
|
||||
<path d="m58.665 30.709-.014-3.279-.014-3.28-.001-.063v-.064l-2.307-3.991-2.306-3.991-1.644 2.858-1.644 2.858c-.075.17-.17.273-.288.333-.118.06-.26.078-.426.078-.166 0-.306-.018-.424-.078-.118-.061-.214-.163-.289-.333l-.891-1.531-.891-1.531-.208-.356-.208-.357-2.424 4.189-2.425 4.189c-.041.086-.085.145-.14.191-.055.047-.121.081-.205.116-.084.036-.154.06-.226.068-.072.007-.145-.002-.236-.031l-.009-.003-.009-.002-.02-.003-.019-.002c-1.888-.219-3.672-.086-5.284.19-1.611.276-3.051.695-4.248 1.047l-.53.153-.529.153v2.472c.01.115.044.248.093.37s.114.234.188.307c.073.074.185.139.307.188.123.049.255.082.37.093h25.943c.115-.011.247-.044.37-.093.122-.049.234-.114.307-.188.074-.073.139-.185.188-.307.049-.122.082-.255.093-.37Zm.383-16.343.169-.177.168-.177c.11-.115.049-.009-.038.126-.088.135-.203.298-.203.298v16.273c.011.215-.023.398-.095.562-.072.165-.182.311-.326.454-.143.143-.289.254-.454.326-.164.072-.346.106-.562.095H31.764c-.215.011-.398-.022-.562-.095-.164-.072-.31-.183-.454-.326-.143-.143-.253-.289-.326-.454-.072-.164-.105-.346-.095-.562V11.713c-.01-.216.023-.399.095-.563.073-.164.183-.31.326-.453.144-.143.29-.254.454-.326.164-.073.347-.106.562-.096h14.394c.024.113.041.193.065.287.025.095.057.205.112.377.024.075 0 .028-.03-.037s-.066-.148-.066-.148H31.764c-.115.011-.247.044-.37.093-.122.049-.233.114-.307.188-.073.073-.138.185-.188.307-.049.123-.082.255-.093.371v16.029l.307-.09.307-.09.156-.046.155-.045c1.256-.369 2.717-.802 4.348-1.083 1.632-.281 3.434-.409 5.371-.166l.157.02.157.02.08-.137.079-.138 2.232-3.878 2.232-3.878c.075-.169.17-.272.288-.333.118-.06.259-.078.425-.078.166 0 .307.018.425.079.117.06.212.163.287.333l1.1 1.902 1.101 1.902.208-.356.208-.357 1.452-2.494 1.452-2.495a.4813.4813 0 0 1 .039-.063c.015-.02.03-.039.048-.058.079-.118.164-.198.265-.247.1-.048.216-.064.357-.053.128-.011.237.005.334.05.098.045.183.117.263.217.026.023.046.044.063.067.017.022.031.047.047.078l1.958 3.389 1.958 3.389v-8.435c.125-.103.234-.197.347-.3.113-.104.229-.217.367-.36l-.17.175-.169.176.004.003Z" />
|
||||
<path
|
||||
fill="red"
|
||||
d="M53.247 6.641c-.374.007-.681.049-.951.119-.271.071-.505.171-.736.294l-.206.112-.207.112-.208.112-.209.112-.039-.039-.039-.04-.045.085-.046.085-.076.042-.076.041.035.036.035.035-.222.418-.223.418c-.152.29-.266.587-.335.919-.068.332-.09.698-.059 1.126.102.666.366 1.272.736 1.776s.846.905 1.372 1.163c.539.22 1.088.327 1.626.314.539-.013 1.067-.146 1.564-.403l.206-.112.206-.112.208-.112.208-.112.048.048.047.048.3-.597.299-.597c.276-.582.394-1.2.375-1.798-.019-.599-.174-1.177-.445-1.677-.309-.495-.754-.94-1.292-1.266-.539-.326-1.17-.532-1.851-.55Zm2.741 6.611-2.864-2.862-2.864-2.863.13-.122.13-.123c.366-.339.798-.588 1.264-.751.466-.163.965-.242 1.464-.242.69 0 1.369.157 1.967.486.598.329 1.116.829 1.484 1.514.214.331.37.676.47 1.021.1.345.144.691.134 1.024-.01.335-.075.671-.182.997-.107.326-.257.641-.437.932a3.872 3.872 0 0 1-.21.359c-.076.114-.156.224-.241.328l-.122.151Zm-5.559-.186c-.377-.36-.669-.779-.865-1.248-.196-.47-.296-.99-.291-1.554-.002-.36.042-.708.132-1.042.09-.333.225-.652.406-.955.065-.129.134-.252.208-.367.075-.116.153-.224.235-.325l.123-.152.122-.152 2.864 2.861 2.863 2.862-.128.123-.129.123c-.333.318-.739.573-1.199.746-.46.173-.974.264-1.525.254-.566.006-1.09-.101-1.563-.302-.473-.202-.894-.499-1.253-.872Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
18
packages/pastebar-app-ui/src/assets/icons/clip.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WrapIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 25 25"
|
||||
className={props.className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M7.2626 3.26045C7.38219 2.13044 8.33828 1.25 9.5 1.25H14.5C15.6617 1.25 16.6178 2.13044 16.7374 3.26045C17.5005 3.27599 18.1603 3.31546 18.7236 3.41895C19.4816 3.55818 20.1267 3.82342 20.6517 4.34835C21.2536 4.95027 21.5125 5.70814 21.6335 6.60825C21.75 7.47522 21.75 8.57754 21.75 9.94513V16.0549C21.75 17.4225 21.75 18.5248 21.6335 19.3918C21.5125 20.2919 21.2536 21.0497 20.6517 21.6517C20.0497 22.2536 19.2919 22.5125 18.3918 22.6335C17.5248 22.75 16.4225 22.75 15.0549 22.75H8.94513C7.57754 22.75 6.47522 22.75 5.60825 22.6335C4.70814 22.5125 3.95027 22.2536 3.34835 21.6517C2.74643 21.0497 2.48754 20.2919 2.36652 19.3918C2.24996 18.5248 2.24998 17.4225 2.25 16.0549V9.94513C2.24998 8.57754 2.24996 7.47522 2.36652 6.60825C2.48754 5.70814 2.74643 4.95027 3.34835 4.34835C3.87328 3.82342 4.51835 3.55818 5.27635 3.41895C5.83973 3.31546 6.49952 3.27599 7.2626 3.26045ZM7.26496 4.76087C6.54678 4.7762 5.99336 4.81234 5.54735 4.89426C4.98054 4.99838 4.65246 5.16556 4.40901 5.40901C4.13225 5.68577 3.9518 6.07435 3.85315 6.80812C3.75159 7.56347 3.75 8.56458 3.75 10V16C3.75 17.4354 3.75159 18.4365 3.85315 19.1919C3.9518 19.9257 4.13225 20.3142 4.40901 20.591C4.68577 20.8678 5.07435 21.0482 5.80812 21.1469C6.56347 21.2484 7.56458 21.25 9 21.25H15C16.4354 21.25 17.4365 21.2484 18.1919 21.1469C18.9257 21.0482 19.3142 20.8678 19.591 20.591C19.8678 20.3142 20.0482 19.9257 20.1469 19.1919C20.2484 18.4365 20.25 17.4354 20.25 16V10C20.25 8.56458 20.2484 7.56347 20.1469 6.80812C20.0482 6.07434 19.8678 5.68577 19.591 5.40901C19.3475 5.16556 19.0195 4.99838 18.4527 4.89426C18.0066 4.81234 17.4532 4.7762 16.735 4.76087C16.6058 5.88062 15.6544 6.75 14.5 6.75H9.5C8.34559 6.75 7.39424 5.88062 7.26496 4.76087ZM9.5 2.75C9.08579 2.75 8.75 3.08579 8.75 3.5V4.5C8.75 4.91421 9.08579 5.25 9.5 5.25H14.5C14.9142 5.25 15.25 4.91421 15.25 4.5V3.5C15.25 3.08579 14.9142 2.75 14.5 2.75H9.5ZM6.25 10.5C6.25 10.0858 6.58579 9.75 7 9.75H17C17.4142 9.75 17.75 10.0858 17.75 10.5C17.75 10.9142 17.4142 11.25 17 11.25H7C6.58579 11.25 6.25 10.9142 6.25 10.5ZM7.25 14C7.25 13.5858 7.58579 13.25 8 13.25H16C16.4142 13.25 16.75 13.5858 16.75 14C16.75 14.4142 16.4142 14.75 16 14.75H8C7.58579 14.75 7.25 14.4142 7.25 14ZM8.25 17.5C8.25 17.0858 8.58579 16.75 9 16.75H15C15.4142 16.75 15.75 17.0858 15.75 17.5C15.75 17.9142 15.4142 18.25 15 18.25H9C8.58579 18.25 8.25 17.9142 8.25 17.5Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
22
packages/pastebar-app-ui/src/assets/icons/clipboard-run.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function ClipboardRun(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '16'}
|
||||
height={props.height ?? '16'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<rect width="8" height="4" x="8" y="2" rx="1" ry="1" />
|
||||
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
|
||||
<path d="m9.392 10.005 6.16 3.697-6.16 3.697v-7.394Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 28 32" width="700px" height="800px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Icon-Set" transform="translate(-466.000000, -99.000000)" fill="#000000">
|
||||
<path d="M 487 113 L 473 113 C 472.447 113 472 113.448 472 114 C 472 114.553 472.447 115 473 115 L 487 115 C 487.553 115 488 114.553 488 114 C 488 113.448 487.553 113 487 113 Z M 492 127 C 492 128.104 491.104 129 490 129 L 470 129 C 468.896 129 468 128.104 468 127 L 468 107 C 468 105.896 468.896 105 470 105 L 473 105 L 473 109 L 487 109 L 487 105 L 490 105 C 491.104 105 492 105.896 492 107 L 492 127 Z M 475 103 L 477.223 103 C 477.223 101.896 478.466 101 480 101 C 481.534 101 482.777 101.896 482.777 103 L 485 103 L 485 107 L 475 107 L 475 103 Z M 490 103 L 487 103 C 487 103 481.846 99 480 99 C 478.154 99 473 103 473 103 L 470 103 C 467.791 103 466 104.791 466 107 L 466 127 C 466 129.209 467.791 131 470 131 L 490 131 C 492.209 131 494 129.209 494 127 L 494 107 C 494 104.791 492.209 103 490 103 Z M 487 123 L 473 123 C 472.447 123 472 123.448 472 124 C 472 124.553 472.447 125 473 125 L 487 125 C 487.553 125 488 124.553 488 124 C 488 123.448 487.553 123 487 123 Z M 487 118 L 473 118 C 472.447 118 472 118.448 472 119 C 472 119.553 472.447 120 473 120 L 487 120 C 487.553 120 488 119.553 488 119 C 488 118.448 487.553 118 487 118 Z" id="clipboard"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0.561 2.298 23.05 25.683" width="23.05" height="25.683" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 4.512 7.237 C 4.512 6.692 4.955 6.248 5.501 6.248 L 16.038 6.248 C 16.583 6.248 17.026 6.692 17.026 7.237 C 17.026 7.782 16.583 8.224 16.038 8.224 L 5.501 8.224 C 4.955 8.224 4.512 7.782 4.512 7.237 Z M 8.182 14.152 L 5.501 14.152 C 4.955 14.152 4.512 14.595 4.512 15.139 C 4.512 15.684 4.955 16.127 5.501 16.127 L 8.182 16.127 C 8.729 16.127 9.171 15.684 9.171 15.139 C 9.171 14.595 8.729 14.152 8.182 14.152 Z M 5.501 12.176 L 12.767 12.176 C 13.313 12.176 13.756 11.734 13.756 11.188 C 13.756 10.643 13.313 10.2 12.767 10.2 L 5.501 10.2 C 4.955 10.2 4.512 10.643 4.512 11.188 C 4.512 11.734 4.955 12.176 5.501 12.176 Z M 18.612 19.42 L 17.026 19.42 L 17.026 17.728 C 17.026 17.182 16.583 16.739 16.038 16.739 C 15.491 16.739 15.049 17.182 15.049 17.728 L 15.049 20.408 C 15.049 20.953 15.491 21.396 16.038 21.396 L 18.612 21.396 C 19.158 21.396 19.6 20.953 19.6 20.408 C 19.6 19.862 19.158 19.42 18.612 19.42 Z M 23.611 20.408 C 23.611 24.583 20.214 27.981 16.038 27.981 C 14.458 27.981 12.991 27.494 11.776 26.664 L 4.183 26.664 C 2.185 26.664 0.561 25.04 0.561 23.042 L 0.561 5.92 C 0.561 3.921 2.185 2.298 4.183 2.298 L 17.355 2.298 C 19.353 2.298 20.978 3.921 20.978 5.92 L 20.978 14.68 C 22.586 16.069 23.611 18.12 23.611 20.408 Z M 4.183 24.688 L 9.795 24.688 C 8.956 23.47 8.464 21.997 8.464 20.408 C 8.464 16.232 11.86 12.835 16.038 12.835 C 17.089 12.835 18.092 13.05 19.001 13.439 L 19.001 5.92 C 19.001 5.012 18.262 4.273 17.355 4.273 L 4.183 4.273 C 3.276 4.273 2.538 5.012 2.538 5.92 L 2.538 23.042 C 2.538 23.95 3.276 24.688 4.183 24.688 Z M 21.634 20.408 C 21.634 17.322 19.125 14.811 16.038 14.811 C 12.949 14.811 10.439 17.322 10.439 20.408 C 10.439 23.493 12.949 26.005 16.038 26.005 C 19.125 26.005 21.634 23.493 21.634 20.408 Z" style="stroke-opacity: 1; stroke-width: 0px;"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0.294 3.317 24.273 26.397" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1, 0, 0, 1, 0.006468, -0.486171)">
|
||||
<path d="M 19.14 29.714 L 8.502 29.714 C 6.143 29.714 4.231 27.802 4.231 25.443 L 4.231 14.934 C 0.821 13.47 0.273 8.863 3.247 6.641 C 5.347 5.072 8.316 5.467 9.932 7.533 L 19.139 7.533 C 21.498 7.533 23.41 9.445 23.41 11.804 L 23.41 25.443 C 23.41 27.802 21.499 29.713 19.14 29.714 Z M 6.162 6.904 C 3.384 6.904 1.647 9.911 3.037 12.318 C 4.425 14.723 7.899 14.723 9.288 12.318 C 9.604 11.769 9.772 11.146 9.772 10.513 C 9.769 8.521 8.155 6.906 6.162 6.904 Z M 22.191 11.804 C 22.191 10.119 20.825 8.752 19.14 8.752 L 10.648 8.752 C 11.912 11.918 9.57 15.358 6.162 15.342 C 5.924 15.336 5.686 15.312 5.452 15.272 L 5.452 25.443 C 5.452 27.128 6.818 28.493 8.502 28.493 L 19.14 28.493 C 20.825 28.493 22.191 27.128 22.191 25.443 L 22.191 11.804 Z M 18.788 23.24 C 18.788 22.903 18.515 22.631 18.178 22.631 L 9.465 22.631 C 8.997 22.631 8.703 23.139 8.937 23.545 C 9.047 23.735 9.248 23.85 9.465 23.85 L 18.178 23.85 C 18.515 23.85 18.788 23.577 18.788 23.24 Z M 18.788 18.624 C 18.788 18.287 18.515 18.014 18.178 18.014 L 9.465 18.014 C 8.997 18.014 8.703 18.522 8.937 18.928 C 9.047 19.117 9.248 19.233 9.465 19.233 L 18.178 19.233 C 18.515 19.233 18.788 18.96 18.788 18.624 Z M 18.788 14.008 C 18.788 13.671 18.515 13.399 18.178 13.399 L 12.372 13.399 C 11.902 13.399 11.608 13.907 11.844 14.313 C 11.953 14.502 12.153 14.618 12.372 14.618 L 18.178 14.618 C 18.515 14.618 18.788 14.344 18.788 14.008 Z M 6.771 12.308 L 6.771 10.513 C 6.771 10.176 6.498 9.902 6.162 9.902 L 4.842 9.902 C 4.372 9.902 4.079 10.411 4.313 10.818 C 4.423 11.006 4.624 11.122 4.842 11.122 L 5.552 11.122 L 5.552 12.308 C 5.552 12.776 6.06 13.07 6.466 12.836 C 6.655 12.727 6.771 12.524 6.771 12.308 Z" style="" transform="matrix(-1, 0, 0, -1, 24.720675, 35.395358)"/>
|
||||
<path d="M 7.992 4.719 L 13.802 4.719 C 14.201 4.719 14.525 5.042 14.525 5.443 L 14.525 7.121 C 14.525 7.52 14.201 7.845 13.802 7.845 L 7.992 7.845 C 7.591 7.845 7.268 7.52 7.268 7.121 L 7.268 5.443 C 7.268 5.042 7.591 4.719 7.992 4.719 Z" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0.294 3.317 24.273 26.397" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 19.464 29.576 L 9.633 29.576 C 7.453 29.576 5.686 27.809 5.686 25.629 L 5.686 15.917 C 2.534 14.564 2.028 10.306 4.776 8.253 C 6.717 6.803 9.461 7.168 10.954 9.077 L 19.463 9.077 C 21.643 9.077 23.41 10.844 23.41 13.024 L 23.41 25.629 C 23.41 27.809 21.644 29.575 19.464 29.576 Z M 7.47 8.496 C 4.903 8.496 3.298 11.275 4.582 13.499 C 5.865 15.722 9.075 15.722 10.359 13.499 C 10.651 12.992 10.806 12.416 10.806 11.831 C 10.804 9.99 9.312 8.498 7.47 8.496 Z M 22.283 13.024 C 22.283 11.467 21.021 10.204 19.464 10.204 L 11.616 10.204 C 12.784 13.13 10.62 16.309 7.47 16.294 C 7.25 16.288 7.03 16.266 6.814 16.229 L 6.814 25.629 C 6.814 27.186 8.076 28.448 9.633 28.448 L 19.464 28.448 C 21.021 28.448 22.283 27.186 22.283 25.629 L 22.283 13.024 Z M 19.139 23.593 C 19.139 23.282 18.886 23.03 18.575 23.03 L 10.523 23.03 C 10.09 23.03 9.818 23.5 10.035 23.875 C 10.136 24.05 10.322 24.157 10.523 24.157 L 18.575 24.157 C 18.886 24.157 19.139 23.904 19.139 23.593 Z M 19.139 19.327 C 19.139 19.016 18.886 18.763 18.575 18.763 L 10.523 18.763 C 10.09 18.763 9.818 19.233 10.035 19.608 C 10.136 19.783 10.322 19.89 10.523 19.89 L 18.575 19.89 C 18.886 19.89 19.139 19.638 19.139 19.327 Z M 19.139 15.061 C 19.139 14.75 18.886 14.498 18.575 14.498 L 13.209 14.498 C 12.775 14.498 12.503 14.968 12.721 15.343 C 12.822 15.518 13.007 15.625 13.209 15.625 L 18.575 15.625 C 18.886 15.625 19.139 15.372 19.139 15.061 Z M 8.033 13.49 L 8.033 11.831 C 8.033 11.52 7.781 11.267 7.47 11.267 L 6.25 11.267 C 5.816 11.267 5.545 11.737 5.761 12.113 C 5.863 12.287 6.049 12.394 6.25 12.394 L 6.906 12.394 L 6.906 13.49 C 6.906 13.923 7.376 14.194 7.751 13.978 C 7.926 13.877 8.033 13.69 8.033 13.49 Z" style="" transform="matrix(-1, 0, 0, -1, 26.39677, 36.942104)"/>
|
||||
<path d="M 9.191 6.36 H 14.776 A 0.695 0.695 0 0 1 15.471 7.055 V 8.669 A 0.695 0.695 0 0 1 14.776 9.364 H 9.191 A 0.695 0.695 0 0 1 8.496 8.669 V 7.055 A 0.695 0.695 0 0 1 9.191 6.36 Z" style="stroke: rgb(0, 0, 0); fill: rgb(255, 255, 255);"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
22
packages/pastebar-app-ui/src/assets/icons/external-open.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function ExternalOpenIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.8"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M21.272 8.567v-6m0 0h-6m6 0L10.87 13.308M9.729 5.432h-2.2c-1.68 0-2.52 0-3.162.327-.564.288-1.023.747-1.311 1.311-.327.642-.327 1.482-.327 3.162v6.4c0 1.68 0 2.52.327 3.162.288.565.747 1.023 1.311 1.311.642.327 1.482.327 3.162.327h6.4c1.68 0 2.52 0 3.162-.327a2.9984 2.9984 0 0 0 1.311-1.311c.327-.642.327-1.482.327-3.162v-2.2"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
23
packages/pastebar-app-ui/src/assets/icons/find.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function FindIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 25 27"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0.3"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M12.2852 4.057c-4.5443 0-8.2282 3.684-8.2282 8.2282 0 4.5443 3.684 8.2282 8.2282 8.2282 4.5443 0 8.2282-3.6839 8.2282-8.2282S16.8295 4.057 12.2852 4.057ZM2 12.2852C2 6.6049 6.6048 2 12.2852 2s10.2852 4.6048 10.2852 10.2852-4.6048 10.2852-10.2852 10.2852C6.6049 22.5704 2 17.9656 2 12.2852Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
<path d="m19.8786 18.3487 5.8043 5.8043c.4228.4228.4228 1.1083 0 1.5311-.4228.4228-1.1083.4228-1.5311 0l-5.8043-5.8043 1.5311-1.5311Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function BlankIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
viewBox="0 0 24 24"
|
||||
onClick={props.onClick}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
d="m18.4044 17.0597-1.3474 1.3474H8.2988l1.3474-1.3474h8.7582ZM14.52 5.0053l3.811 3.811-.5695.7343-1.0281 1.3106-.6031.7568-.5374.6632-.3597.436-.4222.4997-.2734.3133-.2364.2606-.1994.2081-.4734.4683-.9742.9883-.514.5288-.1854-.0092-.1944-.003c-.3311 0-.699.0257-1.1035.077l-.2536.0356-.2478.0408-.237.0439-.3247.067-.6212.1496-2.021 1.0105-1.3475.3369.3369-1.3474 1.0105-2.0211.032-.076.0564-.1558.0474-.1502.0516-.187a6.8003 6.8003 0 0 0 .1495-.7784 10.6177 10.6177 0 0 0 .088-1.797l.1045-.1176.1065-.1134.497-.5086 1.1954-1.1882.3684-.3535.4097-.3752.3575-.3158.3839-.3296.4103-.3434.4366-.3573.4631-.3711.7442-.5827.529-.4057.5556-.4196.5819-.4335ZM8.7067 12.357a11.8664 11.8664 0 0 1-.036.4396l-.0472.4013a8.6212 8.6212 0 0 1-.112.649l-.1351.572.5888.5408.5814-.0902c.3209-.0649.6365-.1185.9407-.157.1784-.0227.3517-.041.52-.055L8.7067 12.357Zm5.6858-5.5734-.19.144-.7708.5933-.4798.3773-.4525.3626-.425.3476-.3975.3325-.3696.3172-.3416.3015-.4179.383-.3182.3058-.8657.8602 2.861 2.861.1762-.1794.5993-.5981.1285-.1254.174-.181.2194-.2415.2594-.297.412-.4874.3522-.4267.5305-.655.5967-.7486.8638-1.1014-2.1444-2.1445Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
23
packages/pastebar-app-ui/src/assets/icons/history.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WrapIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
className={props.className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0.294 3.317 24.273 26.397"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19.14 29.714H8.502a4.27 4.27 0 0 1-4.271-4.271V14.934C.821 13.47.273 8.863 3.247 6.641a4.822 4.822 0 0 1 6.685.892h9.207a4.27 4.27 0 0 1 4.271 4.271v13.639a4.27 4.27 0 0 1-4.27 4.271ZM6.162 6.904c-2.778 0-4.515 3.007-3.125 5.414 1.388 2.405 4.862 2.405 6.251 0a3.622 3.622 0 0 0 .484-1.805 3.614 3.614 0 0 0-3.61-3.609Zm16.029 4.9a3.052 3.052 0 0 0-3.051-3.052h-8.492c1.264 3.166-1.078 6.606-4.486 6.59a4.963 4.963 0 0 1-.71-.07v10.171a3.05 3.05 0 0 0 3.05 3.05H19.14a3.05 3.05 0 0 0 3.051-3.05V11.804ZM18.788 23.24a.609.609 0 0 0-.61-.609H9.465a.61.61 0 0 0 0 1.219h8.713a.61.61 0 0 0 .61-.61Zm0-4.616a.61.61 0 0 0-.61-.61H9.465a.61.61 0 0 0 0 1.219h8.713a.61.61 0 0 0 .61-.609Zm0-4.616a.609.609 0 0 0-.61-.609h-5.806a.609.609 0 1 0 0 1.219h5.806a.61.61 0 0 0 .61-.61Zm-12.017-1.7v-1.795a.61.61 0 0 0-.609-.611h-1.32a.611.611 0 0 0 0 1.22h.71v1.186a.61.61 0 0 0 1.219 0Z"
|
||||
transform="rotate(180 12.364 17.455)"
|
||||
/>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
fill={`${props.lightingColor || 'white'}`}
|
||||
d="M7.992 4.719h5.81c.399 0 .723.323.723.724v1.678a.724.724 0 0 1-.723.724h-5.81a.724.724 0 0 1-.724-.724V5.443c0-.401.323-.724.724-.724Z"
|
||||
transform="translate(.006 -.486)"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
33
packages/pastebar-app-ui/src/assets/icons/mask-square.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function BlankIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
onClick={props.onClick}
|
||||
className={props.className}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||
|
||||
<rect
|
||||
x="7.3"
|
||||
y="7.3"
|
||||
rx="5"
|
||||
ry="5"
|
||||
width="9.3"
|
||||
height="9.3"
|
||||
className="opacity-90"
|
||||
stroke="none"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
19
packages/pastebar-app-ui/src/assets/icons/nowrap.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WrapIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width={props.width ?? '14px'}
|
||||
height={props.height ?? '14px'}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M 3 8.992 L 19.686 8.988" />
|
||||
<polyline points="16 16.992000579833984" />
|
||||
<line x1="3" x2="13.406" y1="14.992" y2="14.992" />
|
||||
</svg>
|
||||
)
|
||||
}
|
25
packages/pastebar-app-ui/src/assets/icons/open-app.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function OpenAppIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<rect width="18.953" height="16" x="2.524" y="4" rx="2" />
|
||||
<path d="M10.524 4v4m-8 0h18.953M6.524 4v4" />
|
||||
{/* <path d="m9.431 17.386 3-3-3-3" /> */}
|
||||
|
||||
{/* <path d="M2.066 17.386v-1c0-1.104.896-2 2-2h6" /> */}
|
||||
{/* <path d="M2 11.417V4.894c0-1.105.895-2 2-2h16c1.105 0 2 .895 2 2v14.213c0 1.105-.895 2-2 2H2.654m7.412-18.213V7.13M2 7.13h20M6 2.894V7.13" />
|
||||
<path d="m9.431 17.386 3-3-3-3" />
|
||||
<path d="M2.066 17.386v-1c0-1.104.896-2 2-2h6" /> */}
|
||||
</svg>
|
||||
)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function OpenExecutableIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<rect width="18.953" height="16" x="2.524" y="4" rx="2" />
|
||||
<path d="M10.524 4v4m-8 0h18.953M6.524 4v4m1.442 7.043 2-2-2-2m4 6h4" />
|
||||
</svg>
|
||||
)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function OpenFileShellIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="M14.5 2.693H6c-1.105 0-2 .833-2 1.861v14.891c0 1.028.895 1.861 2 1.861h12c1.105 0 2-.833 2-1.861V7.812l-5.5-5.119Z" />
|
||||
<path d="M14 2.693v6h6M7.998 15.421l2-2-2-2m4 6h4" />
|
||||
</svg>
|
||||
)
|
||||
}
|
19
packages/pastebar-app-ui/src/assets/icons/open-file.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function OpenFileIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="M14.5 2.693H6c-1.105 0-2 .833-2 1.861v14.891c0 1.028.895 1.861 2 1.861h12c1.105 0 2-.833 2-1.861V7.812l-5.5-5.119Z" />
|
||||
<path d="M14 2.693v6h6" />
|
||||
</svg>
|
||||
)
|
||||
}
|
23
packages/pastebar-app-ui/src/assets/icons/open-folder.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function OpenFolderIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
{/* <path d="M2 9.5v-4c0-1.1.9-2 2-2h3.93c.669.003 1.292.341 1.66.9l.82 1.2c.368.559.991.897 1.66.9h6.337c1.105 0 2 .895 2 2v10c0 1.105-.895 2-2 2H2" />
|
||||
<path d="m9.37 16.5 3-3-3-3" />
|
||||
<path d="M2 16.5v-1c0-1.105.895-2 2-2h6" /> */}
|
||||
<path d="m6.391 14.336 1.402-2.71a1.867 1.867 0 0 1 1.626-1.028h10.056c1.223-.002 2.119 1.152 1.813 2.337l-1.439 5.607c-.215.83-.966 1.408-1.823 1.402H4.522c-1.033 0-1.87-.837-1.87-1.869V5.925c0-1.032.837-1.869 1.87-1.869h3.644c.636-.006 1.23.311 1.58.841l.757 1.122c.346.525.932.841 1.561.841h5.542c1.032 0 1.869.837 1.869 1.869v1.869" />
|
||||
{/* <path d="M19.645 20.123c1.056 0 1.911-.855 1.911-1.911V8.655c0-1.056-.855-1.911-1.911-1.911h-7.549c-.65.007-1.258-.317-1.615-.86l-.775-1.147c-.353-.537-.952-.86-1.595-.86H4.355c-1.056 0-1.911.855-1.911 1.911v12.424c0 1.056.855 1.911 1.911 1.911h15.29Z" /> */}
|
||||
{/* <path d="M20 20.5c1.105 0 2-.895 2-2v-10c0-1.105-.895-2-2-2h-7.9c-.68.007-1.316-.332-1.69-.9L9.6 4.4c-.37-.562-.997-.9-1.67-.9H4c-1.105 0-2 .895-2 2v13c0 1.105.895 2 2 2h16Z" /> */}
|
||||
</svg>
|
||||
)
|
||||
}
|
18
packages/pastebar-app-ui/src/assets/icons/spider.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WebSpiderIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="M22.968 10.69h-5.797c-.074-.148-.223-.37-.297-.52l3.865-2.304c.297-.148.445-.446.445-.818V2.291c0-.52-.445-.966-.966-.966-.519 0-.967.446-.967.966v4.237l-3.79 2.23c-.074-.074-.223-.149-.297-.222.223-.447.372-.968.372-1.563 0-2.007-1.636-3.568-3.569-3.568C9.96 3.405 8.4 5.041 8.4 6.973c0 .522.148 1.041.296 1.563-.073.073-.223.148-.296.222l-3.791-2.23V2.291c0-.52-.446-.966-.967-.966-.521 0-.967.446-.967.966v4.757c0 .298.15.67.446.818l3.866 2.304c-.148.15-.223.372-.298.52H.966c-.52 0-.966.446-.966.967v6.765c0 .519.446.966.966.966.521 0 .966-.447.966-.966v-5.799h4.163c-.074.297-.074.595-.074.967l-2.379.817c-.223.075-.446.223-.521.52-.073.223-.148.521 0 .744L5.5 21.915c.15.371.521.594.893.594.073 0 .223 0 .296-.073.446-.15.745-.744.522-1.19l-2.007-5.353 1.114-.372c.743 2.529 3.047 4.386 5.798 4.386s5.055-1.857 5.798-4.386l1.114.372-2.007 5.353c-.147.446.076 1.04.522 1.19.073.073.223.073.296.073.372 0 .743-.223.893-.594l2.379-6.244c.073-.223.073-.521 0-.744-.075-.223-.298-.371-.521-.52l-2.379-.817c0-.298-.074-.67-.074-.967H22.3v5.799c0 .519.445.966.966.966.52 0 .966-.447.966-.966v-6.765c-.372-.521-.818-.967-1.264-.967ZM11.967 17.9c-2.304 0-4.162-1.857-4.162-4.236 0-1.71 1.04-3.271 2.602-3.939.297-.15.52-.373.594-.67.074-.297 0-.595-.223-.818-.297-.296-.52-.742-.52-1.189 0-.966.743-1.709 1.709-1.709.967 0 1.71.743 1.71 1.709 0 .447-.149.893-.52 1.189-.223.223-.298.521-.223.818.073.297.297.52.594.67 1.562.668 2.602 2.155 2.602 3.865 0 2.453-1.858 4.31-4.163 4.31Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
22
packages/pastebar-app-ui/src/assets/icons/spinner-icon.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
export default function SpinnerIcon() {
|
||||
return (
|
||||
<div className={'flex items-center justify-center h-[16px] w-[16px]'}>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="w-full h-full text-gray-200 animate-spin dark:text-gray-600 fill-green-600"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
22
packages/pastebar-app-ui/src/assets/icons/web-request.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WebRequestIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
strokeWidth="1.8"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
stroke="none"
|
||||
d="M3.564 1.745c-.272.011-.521.142-.688.355C1.311 4.127.456 6.622.456 9.185c0 2.654.906 5.222 2.576 7.286.318.393.894.451 1.288.131.39-.315.449-.887.134-1.279-1.404-1.736-2.168-3.902-2.168-6.138 0-2.158.712-4.258 2.034-5.967.307-.4.234-.971-.164-1.281-.169-.132-.378-.197-.592-.192Zm16.906.005a.8757.8757 0 0 0-.531.187c-.4.304-.474.879-.169 1.281 1.324 1.709 2.035 3.809 2.035 5.967 0 2.236-.763 4.402-2.168 6.138a.9087.9087 0 0 0 .133 1.279c.394.32.97.262 1.286-.131 1.668-2.064 2.574-4.632 2.574-7.286 0-2.563-.845-5.058-2.411-7.085-.149-.19-.366-.315-.603-.344-.05-.006-.097-.011-.146-.006ZM7.092 3.742a.9272.9272 0 0 0-.631.29C5.169 5.436 4.447 7.28 4.447 9.185c0 2.003.792 3.917 2.204 5.345.354.356.935.361 1.293.007.356-.357.359-.933.003-1.287-1.068-1.084-1.674-2.542-1.674-4.065 0-1.447.549-2.848 1.529-3.913.339-.369.313-.945-.055-1.288-.175-.161-.412-.252-.655-.242Zm9.904 0c-.242-.01-.475.081-.654.242-.368.343-.394.919-.055 1.288.982 1.065 1.531 2.466 1.531 3.913 0 1.523-.599 2.981-1.671 4.065-.35.356-.35.93.009 1.287.354.349.931.346 1.286-.007 1.408-1.428 2.202-3.342 2.202-5.345 0-1.905-.723-3.749-2.014-5.153a.9197.9197 0 0 0-.634-.29Zm-4.951 1.71c-2.047 0-3.724 1.684-3.724 3.733 0 1.736 1.203 3.206 2.815 3.61v8.776c0 .509.405.919.909.919.506.002.918-.41.918-.919v-8.776c1.612-.405 2.816-1.874 2.816-3.61 0-2.049-1.687-3.733-3.734-3.733Zm0 1.828c1.063 0 1.906.844 1.906 1.905 0 1.063-.843 1.901-1.906 1.901s-1.899-.838-1.899-1.901c0-1.061.836-1.905 1.899-1.905Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
18
packages/pastebar-app-ui/src/assets/icons/web-scraper.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WebScraperIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="M12.008 1.666c-7.955 0-12.926 8.613-8.949 15.501 3.977 6.889 13.92 6.889 17.897 0 .907-1.57 1.386-3.352 1.386-5.166 0-5.707-4.627-10.335-10.334-10.335Zm-9.27 10.855h3.169c.035 1.322.263 2.634.675 3.893H3.829a9.1934 9.1934 0 0 1-1.091-3.893Zm9.789-5.973V2.913a8.3791 8.3791 0 0 1 3.375 3.635h-3.375Zm3.817 1.039c.447 1.251.693 2.566.727 3.893h-4.544V7.587h3.817Zm-4.856-4.648v3.609H8.114a8.377 8.377 0 0 1 3.374-3.609Zm0 4.674v3.867H6.944c.035-1.327.28-2.642.728-3.893l3.816.026ZM5.907 11.48H2.738c.07-1.362.443-2.693 1.091-3.893h2.753a13.692 13.692 0 0 0-.675 3.893Zm1.037 1.041h4.544v3.893H7.672a12.5295 12.5295 0 0 1-.728-3.893Zm4.544 4.932v3.635a8.3769 8.3769 0 0 1-3.374-3.635h3.374Zm1.039 3.635v-3.635h3.375a8.3771 8.3771 0 0 1-3.375 3.608v.027Zm0-4.674v-3.893h4.544c-.034 1.327-.28 2.642-.727 3.893h-3.817Zm5.582-3.893h3.169a9.2368 9.2368 0 0 1-1.091 3.893h-2.754c.412-1.259.639-2.571.676-3.893Zm0-1.041a13.7635 13.7635 0 0 0-.676-3.893h2.754a9.2327 9.2327 0 0 1 1.091 3.893h-3.169Zm1.428-4.932h-2.493a9.8857 9.8857 0 0 0-2.543-3.506 9.3305 9.3305 0 0 1 5.01 3.506h.026ZM9.514 3.069A9.9123 9.9123 0 0 0 6.97 6.548H4.504a9.3282 9.3282 0 0 1 5.01-3.479Zm-5.01 14.384h2.493a9.8678 9.8678 0 0 0 2.543 3.505 9.3285 9.3285 0 0 1-5.036-3.505Zm9.997 3.479a9.894 9.894 0 0 0 2.543-3.479h2.493a9.3153 9.3153 0 0 1-5.036 3.479Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
19
packages/pastebar-app-ui/src/assets/icons/web-search.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export default function WebSearchIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width={props.width ?? '24px'}
|
||||
height={props.height ?? '24px'}
|
||||
className={props.className}
|
||||
onClick={props.onClick}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path d="M21.219.805H2.681C1.145.805-.1 2.05-.1 3.586V20.27c0 1.536 1.245 2.781 2.781 2.781h18.538c1.535 0 2.781-1.245 2.781-2.781V3.586C24 2.05 22.754.805 21.219.805ZM1.754 3.586c0-.512.414-.927.927-.927h18.538c.512 0 .927.415.927.927v2.78H1.754v-2.78Zm19.465 17.611H2.681a.9257.9257 0 0 1-.927-.927V8.22h20.392v12.05c0 .513-.415.927-.927.927Z" />
|
||||
<path d="M5.086 3.782c-.504-.506-1.366-.279-1.553.41a.9079.9079 0 0 0-.032.248c.006.245.102.48.268.659.09.082.193.148.306.194.225.099.48.099.705 0 .112-.047.215-.113.306-.194.081-.09.147-.194.194-.306a.8739.8739 0 0 0 0-.705.982.982 0 0 0-.194-.306Zm2.78 0a.9455.9455 0 0 0-.834-.25.5179.5179 0 0 0-.176.056.5145.5145 0 0 0-.157.083 1.03 1.03 0 0 0-.149.111.947.947 0 0 0-.194.306c-.1.225-.1.48 0 .705.046.112.112.216.194.306.09.082.193.148.306.194.224.099.479.099.705 0 .112-.047.215-.113.305-.194.082-.09.148-.194.195-.306.051-.11.076-.231.074-.353a.9526.9526 0 0 0-.074-.352.967.967 0 0 0-.195-.306Zm1.465 0c-.083.091-.148.194-.195.306a.5303.5303 0 0 0-.055.176c-.011.059-.018.118-.019.176 0 .122.026.241.074.353.047.112.112.216.195.306.365.358.95.358 1.316 0 .082-.09.148-.194.195-.306.051-.11.076-.231.074-.353.004-.712-.767-1.163-1.386-.81a.8972.8972 0 0 0-.199.152Zm5.558 12.83c1.967-2.976-.025-6.966-3.586-7.182-3.561-.215-6.02 3.505-4.427 6.697 1.243 2.489 4.381 3.33 6.702 1.796l2.351 2.35c.513.496 1.37.251 1.543-.442a.93.93 0 0 0-.232-.868l-2.351-2.351Zm-5.832-.589c-1.515-1.513-.822-4.098 1.246-4.653 2.067-.554 3.96 1.338 3.405 3.406-.126.472-.374.902-.719 1.247-1.101 1.05-2.832 1.05-3.932 0Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
19
packages/pastebar-app-ui/src/assets/icons/wrap.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from 'react'
|
||||
|
||||
export default function WrapIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width={props.width ?? '14px'}
|
||||
height={props.height ?? '14px'}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M 3 8.992 L 18 8.992 C 20.309 8.992 21.753 11.492 20.598 13.492 C 20.062 14.42 19.072 14.992 18 14.992 L 14 14.992" />
|
||||
<polyline points="16 12.992 14 14.992 16 16.992" />
|
||||
<line x1="3" x2="10" y1="14.992" y2="14.992" />
|
||||
</svg>
|
||||
)
|
||||
}
|
3
packages/pastebar-app-ui/src/assets/images/app-error.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="3.1249 4.0034 93.751 91.9929">
|
||||
<path d="M92.996 22.832H63.871L54.5038 6.605c-.9531-1.6523-2.5938-2.6016-4.5039-2.6016s-3.5508.9492-4.5039 2.6016l-9.3672 16.227H7.0038c-2.1406 0-3.8789 1.7422-3.8789 3.8789v56.352c0 2.1367 1.7383 3.8789 3.8789 3.8789h32.922v5.5781c-3.5508.3164-7.0117.8008-10.363 1.457-.5508.1094-.914.6445-.8047 1.1953.1094.5508.6445.914 1.1953.8047 6.3242-1.2344 13.07-1.8633 20.047-1.8633s13.723.625 20.047 1.8594a1.141 1.141 0 0 0 .1953.0195c.4766 0 .9024-.336 1-.8242.1094-.5508-.2539-1.0859-.8047-1.1953-3.3477-.6523-6.8125-1.1367-10.363-1.457v-5.5781h32.922c2.1367 0 3.879-1.7383 3.879-3.8789V26.711c0-2.1367-1.7384-3.8789-3.879-3.8789zM47.262 7.625c.5898-1.0195 1.5625-1.582 2.7383-1.582s2.1484.5625 2.7383 1.582l14.133 24.48c.5898 1.0195.5898 2.1445 0 3.1641s-1.5625 1.582-2.7383 1.582h-28.266c-1.1758 0-2.1484-.5625-2.7383-1.582s-.5898-2.1445 0-3.1641zM31.364 36.289c.9531 1.6523 2.5977 2.6016 4.5039 2.6016h28.27c1.9102 0 3.5508-.9492 4.5039-2.6016.9531-1.6523.9531-3.5469 0-5.1992l-1.3398-2.3242h23.445v52.25l-81.488-.004v-52.25h23.445l-1.3398 2.3243c-.9531 1.6523-.9531 3.5469 0 5.203zm26.672 56.066c-2.6367-.1836-5.3203-.2773-8.0352-.2773s-5.3984.0937-8.0352.2773v-5.4141h16.074zm36.801-9.2891c0 1.0156-.8242 1.8398-1.8398 1.8398l-85.992-.004c-1.0156 0-1.8398-.8241-1.8398-1.8397V26.71c0-1.0156.8242-1.8398 1.8398-1.8398h27.949l-1.0703 1.8516H8.2389c-.5625 0-1.0195.457-1.0195 1.0195v54.289c0 .5625.457 1.0195 1.0195 1.0195h83.523c.5625 0 1.0195-.457 1.0195-1.0195v-54.289c0-.5625-.457-1.0195-1.0195-1.0195h-25.645l-1.0703-1.8516h27.949c1.0156 0 1.8398.8242 1.8398 1.8398zm-46.969-56.234h4.2656c.5625 0 1.0195-.457 1.0195-1.0195v-12.562c0-.5625-.457-1.0195-1.0195-1.0195H47.868c-.5625 0-1.0195.457-1.0195 1.0195v12.562c0 .5625.457 1.0195 1.0195 1.0195zm1.0195-12.562h2.2266v10.523h-2.2266zm1.1133 21.203c2.0938 0 3.7969-1.7031 3.7969-3.7969s-1.7031-3.7969-3.7969-3.7969-3.7969 1.7031-3.7969 3.7969 1.7031 3.7969 3.7969 3.7969zm0-5.5586c.9687 0 1.7578.789 1.7578 1.7578s-.789 1.7578-1.7578 1.7578-1.7578-.789-1.7578-1.7578c0-.9648.789-1.7578 1.7578-1.7578zm-17.594 25.562 2.9531-2.9531-2.9531-2.9531a1.0185 1.0185 0 0 1 0-1.4414 1.0185 1.0185 0 0 1 1.4414 0l2.9531 2.9531 2.9531-2.9531a1.0185 1.0185 0 0 1 1.4414 0 1.0185 1.0185 0 0 1 0 1.4414l-2.9531 2.9531 2.9531 2.9531a1.0185 1.0185 0 0 1 0 1.4414 1.0209 1.0209 0 0 1-.7227.3008 1.0209 1.0209 0 0 1-.7226-.3008l-2.9531-2.9531-2.9531 2.9531a1.0209 1.0209 0 0 1-.7227.3008 1.0209 1.0209 0 0 1-.7226-.3008c-.3907-.3984-.3907-1.0469.0078-1.4414zm26.398 0 2.9531-2.9531-2.9531-2.9531a1.0185 1.0185 0 0 1 0-1.4414 1.0185 1.0185 0 0 1 1.4414 0l2.9531 2.9531 2.9531-2.9531a1.0185 1.0185 0 0 1 1.4414 0 1.0185 1.0185 0 0 1 0 1.4414l-2.9531 2.9531 2.9531 2.9531a1.0185 1.0185 0 0 1 0 1.4414 1.0209 1.0209 0 0 1-.7227.3008 1.0209 1.0209 0 0 1-.7226-.3008l-2.9531-2.9531-2.9531 2.9531c-.1992.1992-.461.3008-.7227.3008s-.5234-.1016-.7226-.3008c-.3907-.3984-.3907-1.0469.0078-1.4414zm-17.996 14.957c2.2109-2.8867 5.5586-4.543 9.1914-4.543s6.9805 1.6562 9.1914 4.543c.3398.4453.2578 1.0859-.1914 1.4297-.4453.3398-1.086.2578-1.4297-.1914-1.8164-2.379-4.5781-3.7461-7.5703-3.7461s-5.754 1.3672-7.5703 3.746c-.1992.2618-.504.3985-.8086.3985a1.017 1.017 0 0 1-.6172-.211 1.009 1.009 0 0 1-.1953-1.4257z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
BIN
packages/pastebar-app-ui/src/assets/images/image-not-found.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
packages/pastebar-app-ui/src/assets/images/image-not-found.psdb
Normal file
BIN
packages/pastebar-app-ui/src/assets/images/no-image.png
Normal file
After Width: | Height: | Size: 33 KiB |