├── src ├── components │ ├── ui │ │ ├── slider.tsx │ │ ├── swiper.tsx │ │ ├── sheet.tsx │ │ ├── slot.tsx │ │ ├── label.tsx │ │ ├── skeleton.tsx │ │ ├── aspect-ratio.tsx │ │ ├── element.tsx │ │ ├── index.ts │ │ ├── simple-select.tsx │ │ ├── progress.tsx │ │ ├── focus-guards.ts │ │ ├── checkbox.tsx │ │ ├── presence.tsx │ │ ├── collection.tsx │ │ ├── back-to-top.tsx │ │ ├── keep-alive-route-view.tsx │ │ ├── drop-area.tsx │ │ ├── toast.tsx │ │ ├── video.tsx │ │ ├── textarea.tsx │ │ ├── checkbox-group.tsx │ │ ├── form.tsx │ │ ├── focus-scope.tsx │ │ ├── image.tsx │ │ ├── scroll-view.tsx │ │ ├── tab.tsx │ │ ├── input.tsx │ │ ├── route-view.tsx │ │ ├── button.tsx │ │ ├── roving-focus.tsx │ │ ├── dialog.tsx │ │ ├── tab-header.tsx │ │ └── list-view.tsx │ ├── FolderIcon │ │ └── index.tsx │ ├── GithubIcon │ │ └── index.tsx │ ├── PageLoading │ │ └── index.tsx │ ├── List │ │ └── index.tsx │ ├── QRCode │ │ └── index.tsx │ ├── DynamicContent │ │ └── index.tsx │ └── ColorInput │ │ └── index.tsx ├── packages │ └── ui │ │ ├── show.tsx │ │ ├── portal.tsx │ │ ├── arrow.tsx │ │ ├── video.tsx │ │ ├── presence.tsx │ │ ├── collection.tsx │ │ ├── toast.tsx │ │ ├── input.tsx │ │ ├── button.tsx │ │ ├── tree.tsx │ │ ├── scroll-view.tsx │ │ ├── tabs.tsx │ │ ├── dialog.tsx │ │ └── dismissable-layer.tsx ├── vite-env.d.ts ├── domains │ ├── app │ │ └── types.ts │ ├── ui │ │ ├── direction │ │ │ └── index.ts │ │ ├── tree │ │ │ ├── constants.ts │ │ │ ├── types.ts │ │ │ ├── index.ts │ │ │ └── leaf.ts │ │ ├── select │ │ │ ├── utils.ts │ │ │ ├── value.ts │ │ │ ├── wrap.ts │ │ │ ├── trigger.ts │ │ │ ├── content.ts │ │ │ └── viewport.ts │ │ ├── form │ │ │ ├── types.ts │ │ │ ├── value.ts │ │ │ ├── field.ts │ │ │ └── index.ts │ │ ├── input │ │ │ └── connect.web.ts │ │ ├── node │ │ │ ├── connect.web.ts │ │ │ └── index.ts │ │ ├── collection │ │ │ └── index.ts │ │ ├── image │ │ │ └── connect.web.ts │ │ ├── index.ts │ │ ├── focus-scope │ │ │ └── index.ts │ │ ├── simple-select │ │ │ └── index.ts │ │ ├── scroll-view │ │ │ └── utils.ts │ │ ├── drag-zone │ │ │ └── index.ts │ │ ├── tabs │ │ │ └── index.ts │ │ ├── roving-focus │ │ │ └── index.ts │ │ ├── context-menu │ │ │ └── index.ts │ │ ├── dismissable-layer │ │ │ └── index.ts │ │ ├── dynamic-content │ │ │ └── index.ts │ │ ├── checkbox │ │ │ └── index.ts │ │ ├── progress │ │ │ └── index.ts │ │ ├── toast │ │ │ └── index.ts │ │ └── popover │ │ │ └── index.ts │ ├── error │ │ └── index.ts │ ├── timer │ │ └── index.ts │ ├── system │ │ └── index.ts │ ├── list │ │ ├── constants.ts │ │ ├── enums.ts │ │ ├── utils.ts │ │ └── typing.ts │ ├── qrcode │ │ ├── types.ts │ │ └── connect.web.ts │ ├── route_view │ │ └── __tests__ │ │ │ └── utils.test.ts │ ├── result │ │ └── index.ts │ ├── cur │ │ └── index.ts │ ├── multiple │ │ └── index.ts │ ├── http_client │ │ ├── connect.axios.ts │ │ └── index.ts │ ├── history │ │ └── connect.web.ts │ └── storage │ │ └── index.ts ├── pages │ ├── notfound │ │ └── index.tsx │ ├── login │ │ └── index.tsx │ ├── register │ │ └── index.tsx │ └── home │ │ └── layout.tsx ├── utils │ ├── nzh │ │ └── langs │ │ │ ├── cn_s.ts │ │ │ └── cn_b.ts │ ├── bezier │ │ ├── type.ts │ │ └── poly-bezier.ts │ ├── download.ts │ ├── lodash │ │ ├── throttle.ts │ │ └── debounce.ts │ └── browser.ts ├── store │ ├── request.ts │ ├── storage.ts │ ├── views.ts │ ├── types.ts │ └── routes.ts ├── biz │ ├── requests │ │ ├── index.ts │ │ └── types.ts │ ├── multiple_input │ │ └── index.ts │ ├── user │ │ └── services.ts │ ├── canvas │ │ ├── mode.test.ts │ │ ├── constants.ts │ │ ├── mode.ts │ │ ├── types.ts │ │ └── history.ts │ ├── color_input │ │ └── index.ts │ ├── path │ │ └── segment.ts │ └── point │ │ └── index.ts ├── types │ └── index.ts └── index.tsx ├── .prettierrc.js ├── public ├── icon.ico ├── tauri.png ├── 128x128.png ├── favicon.ico ├── flutter.png ├── folder.png ├── arrow-left.png ├── electronjs.png ├── logo.svg └── vite.svg ├── assets └── homepage.png ├── .husky └── pre-push.sh ├── vercel.json ├── postcss.config.cjs ├── tsconfig.node.json ├── .gitignore ├── patch └── png2icons.js ├── tsconfig.json ├── index.html ├── README.md ├── tailwind.config.js ├── vite.config.ts └── package.json /src/components/ui/slider.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/utils"; 2 | -------------------------------------------------------------------------------- /src/packages/ui/show.tsx: -------------------------------------------------------------------------------- 1 | export { Show } from "solid-js"; 2 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | }; 4 | -------------------------------------------------------------------------------- /src/components/ui/swiper.tsx: -------------------------------------------------------------------------------- 1 | export const Swiper = () => {}; 2 | -------------------------------------------------------------------------------- /src/packages/ui/portal.tsx: -------------------------------------------------------------------------------- 1 | export { Portal } from "solid-js/web"; 2 | -------------------------------------------------------------------------------- /src/domains/app/types.ts: -------------------------------------------------------------------------------- 1 | export type ThemeTypes = "dark" | "light" | "system"; 2 | -------------------------------------------------------------------------------- /public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/icon.ico -------------------------------------------------------------------------------- /public/tauri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/tauri.png -------------------------------------------------------------------------------- /public/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/128x128.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/flutter.png -------------------------------------------------------------------------------- /public/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/folder.png -------------------------------------------------------------------------------- /assets/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/assets/homepage.png -------------------------------------------------------------------------------- /public/arrow-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/arrow-left.png -------------------------------------------------------------------------------- /public/electronjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ltaoo/AppIconsHelper/HEAD/public/electronjs.png -------------------------------------------------------------------------------- /src/components/ui/sheet.tsx: -------------------------------------------------------------------------------- 1 | import { VariantProps, cva } from "class-variance-authority"; 2 | 3 | -------------------------------------------------------------------------------- /.husky/pre-push.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run check 5 | -------------------------------------------------------------------------------- /src/pages/notfound/index.tsx: -------------------------------------------------------------------------------- 1 | export const NotFoundPage = () => { 2 | return
Not Found
; 3 | }; 4 | -------------------------------------------------------------------------------- /src/domains/ui/direction/index.ts: -------------------------------------------------------------------------------- 1 | export type Direction = "ltr" | "rtl"; 2 | export type Orientation = "horizontal" | "vertical"; 3 | -------------------------------------------------------------------------------- /src/domains/ui/tree/constants.ts: -------------------------------------------------------------------------------- 1 | export enum TARGET_POSITION_TYPE { 2 | TOP = 1, 3 | BOTTOM = -1, 4 | CONTENT = 0, 5 | } 6 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/nzh/langs/cn_s.ts: -------------------------------------------------------------------------------- 1 | export const lang_cn_s = { 2 | ch: "零一二三四五六七八九", 3 | ch_u: "个十百千万亿", 4 | ch_f: "负", 5 | ch_d: "点", 6 | }; 7 | -------------------------------------------------------------------------------- /src/domains/ui/select/utils.ts: -------------------------------------------------------------------------------- 1 | export function clamp(value: number, [min, max]: [number, number]): number { 2 | return Math.min(max, Math.max(min, value)); 3 | } 4 | -------------------------------------------------------------------------------- /src/domains/ui/form/types.ts: -------------------------------------------------------------------------------- 1 | export type InputInterface = { 2 | name: string; 3 | onChange: (v: unknown) => void; 4 | onStateChange: (v: unknown) => void; 5 | }; 6 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 3 | plugins: { 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/utils/nzh/langs/cn_b.ts: -------------------------------------------------------------------------------- 1 | export const lang_cn_b = { 2 | ch: "零壹贰叁肆伍陆柒捌玖", 3 | ch_u: "个拾佰仟万亿", 4 | ch_f: "负", 5 | ch_d: "点", 6 | m_t: "人民币", 7 | m_z: "整", 8 | m_u: "元角分", 9 | }; 10 | -------------------------------------------------------------------------------- /src/domains/ui/input/connect.web.ts: -------------------------------------------------------------------------------- 1 | import { InputCore } from "./index"; 2 | 3 | export function connect(store: InputCore, $input: HTMLInputElement) { 4 | store.focus = () => { 5 | $input.focus(); 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /src/utils/bezier/type.ts: -------------------------------------------------------------------------------- 1 | export type BezierPoint = { 2 | x: number; 3 | y: number; 4 | z?: number; 5 | }; 6 | export type BezierBox = { 7 | min: number; 8 | max: number; 9 | mid: number; 10 | size: number; 11 | }; 12 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /src/components/ui/slot.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | const SlotRoot = (props: { children: JSX.Element }) => { 4 | return props.children; 5 | }; 6 | 7 | const SlotClone = (props: { children: JSX.Element }) => { 8 | return props.children; 9 | }; 10 | -------------------------------------------------------------------------------- /src/store/request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 网络请求 3 | */ 4 | import { HttpClientCore } from "@/domains/http_client/index"; 5 | import { connect } from "@/domains/http_client/connect.axios"; 6 | 7 | export const client = new HttpClientCore({ 8 | headers: {}, 9 | }); 10 | connect(client); 11 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | import { cn } from "@/utils"; 4 | 5 | export const Label = (props: JSX.HTMLAttributes & JSX.AriaAttributes) => ( 6 |
7 | {props.children} 8 |
9 | ); 10 | -------------------------------------------------------------------------------- /src/components/FolderIcon/index.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | export function GithubIcon(props: {} & JSX.HTMLAttributes) { 4 | return ( 5 |
6 |
7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/components/GithubIcon/index.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | export function GithubIcon(props: {} & JSX.HTMLAttributes) { 4 | return ( 5 |
6 |
7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | import { cn } from "@/utils"; 4 | 5 | function Skeleton(props: {} & JSX.HTMLAttributes) { 6 | return
; 7 | } 8 | 9 | export { Skeleton }; 10 | -------------------------------------------------------------------------------- /src/utils/download.ts: -------------------------------------------------------------------------------- 1 | export function downloadFile(url: string, filename: string) { 2 | const link = document.createElement("a"); 3 | link.href = url; 4 | link.download = filename; 5 | link.style.display = "none"; 6 | document.body.appendChild(link); 7 | link.click(); 8 | document.body.removeChild(link); 9 | } 10 | -------------------------------------------------------------------------------- /src/domains/ui/tree/types.ts: -------------------------------------------------------------------------------- 1 | export type SourceNode = { 2 | key: string; 3 | title: string; 4 | children?: Array; 5 | }; 6 | 7 | export type FormattedSourceNode = { 8 | key: string; 9 | title: string; 10 | pos: string; 11 | children?: Array; 12 | [propsName: string]: unknown; 13 | }; 14 | -------------------------------------------------------------------------------- /src/domains/ui/form/value.ts: -------------------------------------------------------------------------------- 1 | import { BaseDomain, Handler } from "@/domains/base"; 2 | 3 | enum Events { 4 | StateChange, 5 | } 6 | type TheTypesOfEvents = { 7 | [Events.StateChange]: FormSourceState; 8 | }; 9 | type FormSourceState = {}; 10 | type FormSourceProps = {}; 11 | 12 | export class FormSourceCore extends BaseDomain {} 13 | -------------------------------------------------------------------------------- /src/domains/error/index.ts: -------------------------------------------------------------------------------- 1 | export class BizError extends Error { 2 | message: string; 3 | code?: string | number; 4 | data: unknown | null = null; 5 | 6 | constructor(msg: string, code?: string | number, data: unknown = null) { 7 | super(msg); 8 | 9 | this.message = msg; 10 | this.code = code; 11 | this.data = data; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/utils/lodash/throttle.ts: -------------------------------------------------------------------------------- 1 | export function throttle any>(delay: number, func: T) { 2 | let lastTime = 0; 3 | return function (...args: Parameters) { 4 | const currentTime = Date.now(); 5 | if (currentTime - lastTime >= delay) { 6 | lastTime = currentTime; 7 | return func(...args); 8 | } 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | dist-admin 14 | *.local 15 | 16 | mock 17 | 18 | # Editor directories and files 19 | .vscode/* 20 | !.vscode/extensions.json 21 | .idea 22 | .DS_Store 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | -------------------------------------------------------------------------------- /src/utils/lodash/debounce.ts: -------------------------------------------------------------------------------- 1 | export function debounce any>(wait: number, func: T) { 2 | let timeoutId: NodeJS.Timeout | null = null; 3 | return function debounced(...args: Parameters) { 4 | if (timeoutId) { 5 | clearTimeout(timeoutId); 6 | } 7 | timeoutId = setTimeout(() => { 8 | func(...args); 9 | timeoutId = null; 10 | }, wait); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | 3 | export const AspectRatio = ( 4 | props: { 5 | ratio: number; 6 | } & JSX.HTMLAttributes 7 | ) => { 8 | const { ratio = 1 / 1 } = props; 9 | 10 | return ( 11 |
12 | {props.children} 13 |
14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /src/domains/timer/index.ts: -------------------------------------------------------------------------------- 1 | export class TimerCore { 2 | timer: null | NodeJS.Timeout = null; 3 | 4 | interval(fn: Function, delay: number) { 5 | if (this.timer !== null) { 6 | return; 7 | } 8 | setInterval(() => { 9 | fn(); 10 | }, delay); 11 | } 12 | clear() { 13 | if (this.timer === null) { 14 | return; 15 | } 16 | clearInterval(this.timer); 17 | this.timer = null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /patch/png2icons.js: -------------------------------------------------------------------------------- 1 | const { readFileSync, writeFileSync } = require("fs"); 2 | 3 | function main() { 4 | const filepath = "./node_modules/png2icons/lib/UPNG.js"; 5 | const content = readFileSync("./node_modules/png2icons/lib/UPNG.js", "utf-8"); 6 | const updated = content.replace("var UPNG = {};", "var UPNG = {};var UZIP;"); 7 | writeFileSync(filepath, updated); 8 | 9 | console.log(`Update ${filepath} Success`); 10 | } 11 | 12 | main(); 13 | -------------------------------------------------------------------------------- /src/domains/ui/node/connect.web.ts: -------------------------------------------------------------------------------- 1 | import { NodeCore } from "."; 2 | 3 | export function connect($img: HTMLImageElement, store: NodeCore) { 4 | const io = new IntersectionObserver( 5 | (entries) => { 6 | entries.forEach((entry) => { 7 | if (entry.isIntersecting) { 8 | store.handleShow(); 9 | io.unobserve($img); 10 | } 11 | }); 12 | }, 13 | { threshold: 0.4 } 14 | ); 15 | io.observe($img); 16 | } 17 | -------------------------------------------------------------------------------- /src/domains/ui/tree/index.ts: -------------------------------------------------------------------------------- 1 | import { BaseDomain, Handler } from "@/domains/base"; 2 | 3 | enum Events { 4 | StateChange, 5 | } 6 | type TheTypesOfEvents = { 7 | [Events.StateChange]: TreeState; 8 | }; 9 | type TreeProps = {}; 10 | type TreeState = {}; 11 | 12 | export class TreeCore extends BaseDomain { 13 | onStateChange(handler: Handler) { 14 | return this.on(Events.StateChange, handler); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "allowSyntheticDefaultImports": true, 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "strict": true, 10 | "jsx": "preserve", 11 | "jsxImportSource": "solid-js", 12 | "types": ["vite/client"], 13 | "noEmit": true, 14 | "isolatedModules": true, 15 | "baseUrl": ".", 16 | "paths": { 17 | "@/*": ["./src/*"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/components/ui/element.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 按钮 3 | */ 4 | import { JSX } from "solid-js"; 5 | 6 | import { ButtonCore } from "@/domains/ui/button"; 7 | 8 | function Element( 9 | props: { 10 | store: ButtonCore; 11 | } & JSX.HTMLAttributes 12 | ) { 13 | const { store } = props; 14 | 15 | return ( 16 |
{ 19 | store.click(); 20 | }} 21 | > 22 | {props.children} 23 |
24 | ); 25 | } 26 | 27 | export { Element }; 28 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | AppIconsHelper 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/biz/requests/index.ts: -------------------------------------------------------------------------------- 1 | import { request_factory } from "@/domains/request/utils"; 2 | import { Result } from "@/domains/result"; 3 | 4 | export const request = request_factory({ 5 | hostnames: { 6 | dev: "", 7 | test: "", 8 | prod: "", 9 | }, 10 | process(r: Result<{ code: number | string; msg: string; data: T }>) { 11 | if (r.error) { 12 | return Result.Err(r.error.message); 13 | } 14 | const { code, msg, data } = r.data; 15 | if (code !== 0) { 16 | return Result.Err(msg, code, data); 17 | } 18 | return Result.Ok(data); 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /src/domains/ui/collection/index.ts: -------------------------------------------------------------------------------- 1 | import { BaseDomain, Handler } from "@/domains/base"; 2 | 3 | enum Events {} 4 | type TheTypesOfEvents = {}; 5 | 6 | export class CollectionCore extends BaseDomain { 7 | itemMap: Map = new Map(); 8 | 9 | setWrap(wrap: unknown) { 10 | // ... 11 | } 12 | add(key: unknown, v: unknown) { 13 | this.itemMap.set(key, v); 14 | } 15 | remove(key: unknown) { 16 | this.itemMap.delete(key); 17 | } 18 | getItems() { 19 | // 找到 wrap 下的所有 item 20 | const items = Array.from(this.itemMap.values()); 21 | return items; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/biz/requests/types.ts: -------------------------------------------------------------------------------- 1 | import { UnpackedResult } from "@/domains/result/index"; 2 | import { Unpacked } from "@/types"; 3 | 4 | export type BaseApiResp = { 5 | code: number; 6 | msg: string; 7 | data: T; 8 | }; 9 | export type ListResponse = { 10 | total: number; 11 | page: number; 12 | page_size: number; 13 | no_more: boolean; 14 | list: T[]; 15 | }; 16 | export type ListResponseWithCursor = { 17 | page_size: number; 18 | next_marker?: string; 19 | total: number; 20 | list: T[]; 21 | }; 22 | export type RequestedResource any> = UnpackedResult>>; 23 | -------------------------------------------------------------------------------- /src/store/storage.ts: -------------------------------------------------------------------------------- 1 | import { StorageCore } from "@/domains/storage"; 2 | 3 | const DEFAULT_CACHE_VALUES = { 4 | user: { 5 | id: "", 6 | username: "anonymous", 7 | token: "", 8 | avatar: "", 9 | }, 10 | tab: "tauri", 11 | newuser: 1, 12 | file: null as null | { name: string; content: string }, 13 | }; 14 | const key = "global"; 15 | const e = globalThis.localStorage.getItem(key); 16 | export const storage = new StorageCore({ 17 | key, 18 | defaultValues: DEFAULT_CACHE_VALUES, 19 | values: e ? JSON.parse(e) : DEFAULT_CACHE_VALUES, 20 | client: globalThis.localStorage, 21 | }); 22 | -------------------------------------------------------------------------------- /src/components/PageLoading/index.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from "solid-js/jsx-runtime"; 2 | import { LucideLoader2 as Loader2 } from "lucide-solid"; 3 | 4 | import { cn } from "@/utils"; 5 | 6 | export function PageLoading(props: JSX.HTMLAttributes) { 7 | return ( 8 |
9 |
10 |
11 | 12 |
正在加载
13 |
14 |
15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AppIconsHelper 2 | 3 | Generate app icons for different platforms. 4 | 5 | ## Screenshots 6 | 7 |
8 | home page 9 |
10 | 11 | ## Features 12 | 13 | - Support generate ico and icns files online 14 | - Directly generate icon files needed for `Flutter` and `Tauri` 15 | 16 | ## Development 17 | 18 | modify the file `png2icons/lib/UPNG.js` in `node_modules` 19 | 20 | ```js 21 | ;(function(){ 22 | var UPNG = {}; 23 | var UZIP; // <-- adding this line 24 | ``` 25 | 26 | ## Thanks to 27 | 28 | - https://github.com/idesis-gmbh/png2icons 29 | - https://github.com/feross/buffer 30 | -------------------------------------------------------------------------------- /src/domains/system/index.ts: -------------------------------------------------------------------------------- 1 | export class CurSystem { 2 | connection: string = "unknown"; 3 | constructor() { 4 | if (typeof window === "undefined") { 5 | return; 6 | } 7 | this.connection = this.query_network(); 8 | } 9 | query_network() { 10 | // @ts-ignore 11 | if (navigator.connection) { 12 | // @ts-ignore 13 | return navigator.connection.type; 14 | } 15 | const ua = navigator.userAgent; 16 | const regExp = /NetType\/(\S*)/; 17 | const matches = ua.match(regExp); 18 | if (!matches) { 19 | return "unknown"; 20 | } 21 | return matches[1]; 22 | } 23 | } 24 | 25 | export const system = new CurSystem(); 26 | -------------------------------------------------------------------------------- /src/domains/ui/tree/leaf.ts: -------------------------------------------------------------------------------- 1 | import { BaseDomain, Handler } from "@/domains/base"; 2 | 3 | enum Events { 4 | StateChange, 5 | } 6 | type TheTypesOfEvents = { 7 | [Events.StateChange]: TreeLeafState; 8 | }; 9 | type TreeLeafProps = {}; 10 | type TreeLeafState = { 11 | expanded: boolean; 12 | }; 13 | 14 | export class TreeLeafCore extends BaseDomain { 15 | /** 如果存在子数,该子树是否展开 */ 16 | expanded = false; 17 | 18 | get state(): TreeLeafState { 19 | return { 20 | expanded: this.expanded, 21 | }; 22 | } 23 | 24 | onStateChange(handler: Handler) { 25 | return this.on(Events.StateChange, handler); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/store/views.ts: -------------------------------------------------------------------------------- 1 | import { JSXElement } from "solid-js"; 2 | 3 | import { HomeLayout } from "@/pages/home/layout"; 4 | import { HomeIndexPage } from "@/pages/home"; 5 | import { LoginPage } from "@/pages/login"; 6 | import { RegisterPage } from "@/pages/register"; 7 | import { NotFoundPage } from "@/pages/notfound"; 8 | import { ViewComponent } from "@/store/types"; 9 | 10 | import { PageKeys } from "./routes"; 11 | 12 | export const pages: Omit, "root"> = { 13 | "root.home_layout": HomeLayout, 14 | "root.home_layout.index": HomeIndexPage, 15 | "root.login": LoginPage, 16 | "root.register": RegisterPage, 17 | "root.notfound": NotFoundPage, 18 | }; 19 | -------------------------------------------------------------------------------- /src/domains/list/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 常量 3 | */ 4 | import { Response } from "./typing"; 5 | 6 | export const DEFAULT_PAGE_SIZE = 10; 7 | export const DEFAULT_CURRENT_PAGE = 1; 8 | export const DEFAULT_TOTAL = 0; 9 | 10 | export const DEFAULT_RESPONSE: Response = { 11 | dataSource: [], 12 | page: DEFAULT_CURRENT_PAGE, 13 | pageSize: DEFAULT_PAGE_SIZE, 14 | total: DEFAULT_TOTAL, 15 | search: {}, 16 | initial: true, 17 | noMore: false, 18 | loading: false, 19 | refreshing: null, 20 | empty: false, 21 | error: null, 22 | }; 23 | 24 | export const DEFAULT_PARAMS = { 25 | page: DEFAULT_CURRENT_PAGE, 26 | pageSize: DEFAULT_PAGE_SIZE, 27 | next_marker: "", 28 | }; 29 | -------------------------------------------------------------------------------- /src/domains/qrcode/types.ts: -------------------------------------------------------------------------------- 1 | import { QRCodeModel } from "./libs"; 2 | 3 | /** 4 | * @file web 端使用 canvas 绘制二维码 5 | */ 6 | export type DrawingOptions = { 7 | width: number; 8 | height: number; 9 | colorDark: string; 10 | colorLight: string; 11 | }; 12 | 13 | /** 绘制器 */ 14 | export abstract class QRcodeDrawing { 15 | constructor(options: DrawingOptions) {} 16 | 17 | /** 在二维码中间绘制 Logo */ 18 | abstract drawLogo(img: string): Promise; 19 | /** 绘制二维码 */ 20 | abstract draw(data: QRCodeModel): void; 21 | /** 清除绘制的二维码 */ 22 | abstract clear(): void; 23 | /** 是否完成绘制 */ 24 | abstract isPainted(): boolean; 25 | /** 对一个数字做处理 */ 26 | abstract round(v: number): number; 27 | } 28 | -------------------------------------------------------------------------------- /src/components/List/index.tsx: -------------------------------------------------------------------------------- 1 | import { For, createSignal } from "solid-js"; 2 | import { JSX } from "solid-js/jsx-runtime"; 3 | 4 | import { ListCore } from "@/domains/list"; 5 | 6 | export function List(props: { store: ListCore; renderItem: (v: T, index: number) => JSX.Element }) { 7 | const { store, renderItem } = props; 8 | 9 | const [dataSource, setDataSOurce] = createSignal(store.response.dataSource); 10 | 11 | store.onStateChange((nextResponse) => { 12 | setDataSOurce(nextResponse.dataSource); 13 | }); 14 | 15 | return ( 16 | 17 | {(item, index) => { 18 | return renderItem(item, index()); 19 | }} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/components/ui/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./button"; 2 | export * from "./input"; 3 | export * from "./checkbox"; 4 | export * from "./collection"; 5 | export * from "./context-menu"; 6 | export * from "./dialog"; 7 | export * from "./dropdown-menu"; 8 | export * from "./input"; 9 | export * from "./scroll-view"; 10 | export * from "./keep-alive-route-view"; 11 | export * from "./skeleton"; 12 | export * from "./textarea"; 13 | export * from "./popover"; 14 | export * from "./progress"; 15 | export * from "./image"; 16 | export * from "./back-to-top"; 17 | export * from "./checkbox-group"; 18 | export * from "./list-view"; 19 | export * from "./video"; 20 | export * from "./label"; 21 | // export * from "./toast"; 22 | -------------------------------------------------------------------------------- /src/components/QRCode/index.tsx: -------------------------------------------------------------------------------- 1 | import { createSignal, onMount, JSX } from "solid-js"; 2 | 3 | import generateQrcode from "@/utils/qrcode"; 4 | 5 | export function QRCode( 6 | props: { 7 | text: string; 8 | // width: number; 9 | // height: number; 10 | logo?: string; 11 | } & JSX.HTMLAttributes 12 | ) { 13 | const { text, logo, ...restProps } = props; 14 | 15 | const [url, setUrl] = createSignal(""); 16 | onMount(async () => { 17 | const nextUrl = await generateQrcode(text, { logo }); 18 | if (!nextUrl) { 19 | return; 20 | } 21 | setUrl(nextUrl); 22 | }); 23 | 24 | return ; 25 | } 26 | -------------------------------------------------------------------------------- /src/domains/ui/node/index.ts: -------------------------------------------------------------------------------- 1 | import { BaseDomain, Handler } from "@/domains/base"; 2 | 3 | enum Events { 4 | Click, 5 | ContextMenu, 6 | Mounted, 7 | EnterViewport, 8 | } 9 | type TheTypesOfEvents = { 10 | [Events.EnterViewport]: void; 11 | [Events.Mounted]: void; 12 | [Events.Click]: Events & { target: HTMLElement }; 13 | }; 14 | export class NodeCore extends BaseDomain { 15 | handleShow() { 16 | this.emit(Events.EnterViewport); 17 | } 18 | 19 | onVisible(handler: Handler) { 20 | return this.on(Events.EnterViewport, handler); 21 | } 22 | onClick(handler: Handler) { 23 | return this.on(Events.Click, handler); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/domains/ui/image/connect.web.ts: -------------------------------------------------------------------------------- 1 | import { ImageCore } from "./index"; 2 | 3 | export function connect($img: HTMLDivElement, store: ImageCore) { 4 | const io = new IntersectionObserver( 5 | (entries) => { 6 | entries.forEach((entry) => { 7 | if (entry.isIntersecting) { 8 | store.handleShow(); 9 | // $img.src = src; 10 | // $img.classList.add("visible"); 11 | // if (has_visible_ref.current === false) { 12 | // set_visible(true); 13 | // } 14 | // has_visible_ref.current = true; 15 | io.unobserve($img); 16 | } 17 | }); 18 | }, 19 | { threshold: 0.01 } 20 | ); 21 | io.observe($img); 22 | // store.onStartLoad(() => {}); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/ui/simple-select.tsx: -------------------------------------------------------------------------------- 1 | import { SimpleSelectCore } from "@/domains/ui/simple-select"; 2 | import { For, createSignal } from "solid-js"; 3 | 4 | export const SimpleSelect = (props: { store: SimpleSelectCore }) => { 5 | const { store } = props; 6 | 7 | const [state, setState] = createSignal(store.state); 8 | 9 | store.onStateChange((v) => { 10 | setState(v); 11 | }); 12 | 13 | return ( 14 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /src/domains/list/enums.ts: -------------------------------------------------------------------------------- 1 | export enum PluginType { 2 | preset = "preset", 3 | plugin = "plugin", 4 | } 5 | 6 | export enum ServiceStage { 7 | uninitialized, 8 | constructor, 9 | init, 10 | initPresets, 11 | initPlugins, 12 | initHooks, 13 | pluginReady, 14 | getConfig, 15 | getPaths, 16 | run, 17 | } 18 | 19 | export enum ConfigChangeType { 20 | reload = "reload", 21 | regenerateTmpFiles = "regenerateTmpFiles", 22 | } 23 | 24 | /** 25 | * 插件触发类型 26 | */ 27 | export enum ApplyPluginsType { 28 | /** 29 | * 新增 30 | */ 31 | add = "add", 32 | /** 33 | * 修改参数,返回新的参数 34 | */ 35 | modify = "modify", 36 | /** 37 | * 事件触发,会修改传入的参数 38 | */ 39 | event = "event", 40 | } 41 | 42 | export enum EnableBy { 43 | register = "register", 44 | config = "config", 45 | } 46 | -------------------------------------------------------------------------------- /src/domains/ui/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./button"; 2 | export * from "./checkbox"; 3 | export * from "./context-menu"; 4 | export * from "./dialog"; 5 | export * from "./direction"; 6 | export * from "./dismissable-layer"; 7 | export * from "./dropdown-menu"; 8 | export * from "./focus-scope"; 9 | export * from "./form"; 10 | export * from "./image"; 11 | export * from "./input"; 12 | export * from "./menu"; 13 | export * from "./node"; 14 | export * from "./popover"; 15 | export * from "./presence"; 16 | export * from "./progress"; 17 | export * from "./roving-focus"; 18 | export * from "./scroll-view"; 19 | export * from "./select"; 20 | export * from "./tabs"; 21 | export * from "./toast"; 22 | export * from "./tree"; 23 | export * from "./menu"; 24 | export * from "./menu/item"; 25 | export * from "./checkbox/group"; 26 | -------------------------------------------------------------------------------- /src/packages/ui/arrow.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 箭头 3 | */ 4 | import { children, JSX } from "solid-js"; 5 | 6 | import { Show } from "./show"; 7 | 8 | const Arrow = (props: { width?: number; height?: number; class?: string; children?: JSX.Element }) => { 9 | const { width = 10, height = 5 } = props; 10 | 11 | const c = children(() => props.children); 12 | 13 | return ( 14 | 15 | {/* We use their children if they're slotting to replace the whole svg */} 16 | }> 17 | {c()} 18 | 19 | 20 | ); 21 | }; 22 | 23 | /* -----------------------------------------------------------------------------------------------*/ 24 | 25 | export { Arrow }; 26 | -------------------------------------------------------------------------------- /src/components/DynamicContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { JSX, createSignal } from "solid-js"; 2 | 3 | import { DynamicContentCore } from "@/domains/ui/dynamic-content"; 4 | 5 | export const DynamicContent = ( 6 | props: { 7 | store: DynamicContentCore; 8 | options: { value: number; content: null | JSX.Element }[]; 9 | } & JSX.HTMLAttributes 10 | ) => { 11 | const { store, options } = props; 12 | 13 | const [state, setState] = createSignal(store.state); 14 | 15 | store.onStateChange((v) => { 16 | setState(v); 17 | }); 18 | 19 | return ( 20 |
21 | {(() => { 22 | const matched = options.find((opt) => opt.value === state().value); 23 | if (!matched) { 24 | return null; 25 | } 26 | return matched.content; 27 | })()} 28 |
29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /src/packages/ui/video.tsx: -------------------------------------------------------------------------------- 1 | import { PlayerCore } from "@/domains/player"; 2 | import { JSX } from "solid-js/jsx-runtime"; 3 | 4 | const Root = () => {}; 5 | 6 | const Video = (props: { store: PlayerCore }) => { 7 | let $video: undefined | HTMLVideoElement; 8 | 9 | return ( 10 |