diff options
Diffstat (limited to 'packages/prosody-ui')
175 files changed, 4276 insertions, 0 deletions
diff --git a/packages/prosody-ui/.gitignore b/packages/prosody-ui/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/packages/prosody-ui/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/packages/prosody-ui/README.md b/packages/prosody-ui/README.md new file mode 100644 index 0000000..e38a0b1 --- /dev/null +++ b/packages/prosody-ui/README.md @@ -0,0 +1,15 @@ +# prosody-ui + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.2.2. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/packages/prosody-ui/bun.lock b/packages/prosody-ui/bun.lock new file mode 100644 index 0000000..c276ddd --- /dev/null +++ b/packages/prosody-ui/bun.lock @@ -0,0 +1,318 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "prosody-ui", + "dependencies": { + "franc-all": "^7.2.0", + "glotscript": "file:../glotscript", + "motion": "^12.11.3", + "sortug": "file:../sortug", + "sortug-ai": "file:../models", + }, + "devDependencies": { + "@types/bun": "^1.3.2", + "@types/react": "^19.2.6", + }, + "peerDependencies": { + "react": ">=19.0.0", + "typescript": "^5.0.0", + }, + }, + }, + "packages": { + "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.36.3", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-+c0mMLxL/17yFZ4P5+U6bTWiCSFZUKJddrv01ud2aFBWnTPLdRncYV76D3q1tqfnL7aCnhRtykFnoCFzvr4U3Q=="], + + "@google/genai": ["@google/genai@0.13.0", "", { "dependencies": { "google-auth-library": "^9.14.2", "ws": "^8.18.0", "zod": "^3.22.4", "zod-to-json-schema": "^3.22.4" } }, "sha512-eaEncWt875H7046T04mOpxpHJUM+jLIljEf+5QctRyOeChylE/nhpwm1bZWTRWoOu/t46R9r+PmgsJFhTpE7tQ=="], + + "@google/generative-ai": ["@google/generative-ai@0.21.0", "", {}, "sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg=="], + + "@grpc/grpc-js": ["@grpc/grpc-js@1.13.3", "", { "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg=="], + + "@grpc/proto-loader": ["@grpc/proto-loader@0.7.15", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ=="], + + "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + + "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + + "@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="], + + "@types/node": ["@types/node@22.13.5", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg=="], + + "@types/node-fetch": ["@types/node-fetch@2.6.12", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA=="], + + "@types/react": ["@types/react@19.2.6", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w=="], + + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + + "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], + + "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="], + + "bignumber.js": ["bignumber.js@9.3.0", "", {}, "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA=="], + + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "file-type": ["file-type@18.7.0", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", "token-types": "^5.0.1" } }, "sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw=="], + + "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + + "form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + + "form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="], + + "formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="], + + "framer-motion": ["framer-motion@12.11.3", "", { "dependencies": { "motion-dom": "^12.11.2", "motion-utils": "^12.9.4", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-ksUtDFBZtrbQFt4bEMFrFgo7camhmXcLeuylKQxEYSd9czkZ4tZmFROxWczWeu51WqC2m91ifpvgGCBLd0uviQ=="], + + "franc-all": ["franc-all@7.2.0", "", { "dependencies": { "trigram-utils": "^2.0.0" } }, "sha512-ZR6ciLQTDBaOvBdkOd8+vqDzaLtmIXRa9GCzcAlaBpqNAKg9QrtClPmqiKac5/xZXfCZGMo1d8dIu1T0BLhHEg=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], + + "gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "glotscript": ["glotscript@file:../glotscript", { "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5.0.0" } }], + + "google-auth-library": ["google-auth-library@9.15.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^6.1.1", "gcp-metadata": "^6.1.0", "gtoken": "^7.0.0", "jws": "^4.0.0" } }, "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng=="], + + "google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "groq-sdk": ["groq-sdk@0.15.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-aYDEdr4qczx3cLCRRe+Beb37I7g/9bD5kHF+EEDxcrREWw1vKoRcfP3vHEkJB7Ud/8oOuF0scRwDpwWostTWuQ=="], + + "gtoken": ["gtoken@7.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" } }, "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "iso-639-3": ["iso-639-3@3.0.1", "", {}, "sha512-SdljCYXOexv/JmbQ0tvigHN43yECoscVpe2y2hlEqy/CStXQlroPhZLj7zKLRiGqLJfw8k7B973UAMDoQczVgQ=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], + + "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "motion": ["motion@12.11.3", "", { "dependencies": { "framer-motion": "^12.11.3", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-R9t8IYJ5hSl+Ao5rj6XGS4lJN+fXQstcpwKOcFA5aWjlwjf3IHcHr8DUjPV0My6T/5ZCQ1jqh0pmjggO4zUpEA=="], + + "motion-dom": ["motion-dom@12.11.2", "", { "dependencies": { "motion-utils": "^12.9.4" } }, "sha512-wZ396XNNTI9GOkyrr80wFSbZc1JbIHSHTbLdririSbkEgahWWKmsHzsxyxqBBvuBU/iaQWVu1YCjdpXYNfo2yQ=="], + + "motion-utils": ["motion-utils@12.9.4", "", {}, "sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "n-gram": ["n-gram@2.0.2", "", {}, "sha512-S24aGsn+HLBxUGVAUFOwGpKs7LBcG4RudKU//eWzt/mQ97/NMKQxDWHyHx63UNWk/OOdihgmzoETn1tf5nQDzQ=="], + + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "openai": ["openai@4.98.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" }, "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-TmDKur1WjxxMPQAtLG5sgBSCJmX7ynTsGmewKzoDwl1fRxtbLOsiR0FA/AOAAtYUmP6azal+MYQuOENfdU+7yg=="], + + "peek-readable": ["peek-readable@5.4.2", "", {}, "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg=="], + + "playht": ["playht@0.16.0", "", { "dependencies": { "@grpc/grpc-js": "^1.9.4", "axios": "^1.4.0", "cross-fetch": "^4.0.0", "file-type": "^18.5.0", "protobufjs": "^7.2.5", "tslib": "^2.1.0" } }, "sha512-gwKqGcmUwrd3NaG6B2z5RZCjxPM0CI915Bmej+GXWZU2PSdN2g4hXsDMnjts+uakLaqGEY8YaIqNokyYH7SnvQ=="], + + "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], + + "protobufjs": ["protobufjs@7.5.2", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-f2ls6rpO6G153Cy+o2XQ+Y0sARLOZ17+OGVLHrc3VUKcLHYKEKWbkSujdBWQXM7gKn5NTfp0XnRPZn1MIu8n9w=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], + + "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="], + + "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + + "readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="], + + "replicate": ["replicate@1.0.1", "", { "optionalDependencies": { "readable-stream": ">=4.0.0" } }, "sha512-EY+rK1YR5bKHcM9pd6WyaIbv6m2aRIvHfHDh51j/LahlHTLKemTYXF6ptif2sLa+YospupAsIoxw8Ndt5nI3vg=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "sortug": ["sortug@file:../sortug", { "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } }], + + "sortug-ai": ["models@file:../models", { "dependencies": { "@anthropic-ai/sdk": "^0.36.3", "@google/genai": "^0.13.0", "@google/generative-ai": "^0.21.0", "bcp-47": "^2.1.0", "franc-all": "^7.2.0", "groq-sdk": "^0.15.0", "iso-639-3": "^3.0.1", "openai": "^4.84.0", "playht": "^0.16.0", "replicate": "^1.0.1", "sortug": "file://home/y/code/npm/sortug" }, "devDependencies": { "@types/bun": "^1.2.12" }, "peerDependencies": { "typescript": "^5.7.3" } }], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strtok3": ["strtok3@7.1.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^5.1.3" } }, "sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg=="], + + "token-types": ["token-types@5.0.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "trigram-utils": ["trigram-utils@2.0.1", "", { "dependencies": { "collapse-white-space": "^2.0.0", "n-gram": "^2.0.0" } }, "sha512-nfWIXHEaB+HdyslAfMxSqWKDdmqY9I32jS7GnqpdWQnLH89r6A5sdk3fDVYqGAZ0CrT8ovAFSAo6HRiWcWNIGQ=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "ws": ["ws@8.18.2", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="], + + "@anthropic-ai/sdk/@types/node": ["@types/node@18.19.100", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-ojmMP8SZBKprc3qGrGk8Ujpo80AXkrP7G2tOT4VWr5jlr5DHjsJF+emXJz+Wm0glmy4Js62oKMdZZ6B9Y+tEcA=="], + + "groq-sdk/@types/node": ["@types/node@18.19.100", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-ojmMP8SZBKprc3qGrGk8Ujpo80AXkrP7G2tOT4VWr5jlr5DHjsJF+emXJz+Wm0glmy4Js62oKMdZZ6B9Y+tEcA=="], + + "openai/@types/node": ["@types/node@18.19.100", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-ojmMP8SZBKprc3qGrGk8Ujpo80AXkrP7G2tOT4VWr5jlr5DHjsJF+emXJz+Wm0glmy4Js62oKMdZZ6B9Y+tEcA=="], + + "sortug-ai/@types/bun": ["@types/bun@1.2.13", "", { "dependencies": { "bun-types": "1.2.13" } }, "sha512-u6vXep/i9VBxoJl3GjZsl/BFIsvML8DfVDO0RYLEwtSZSp981kEO1V5NwRcO1CPJ7AmvpbnDCiMKo3JvbDEjAg=="], + + "sortug-ai/sortug": ["sortug@file:../../../npm/sortug", { "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } }], + + "@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + + "groq-sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + + "openai/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + + "sortug-ai/@types/bun/bun-types": ["bun-types@1.2.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-rRjA1T6n7wto4gxhAO/ErZEtOXyEZEmnIHQfl0Dt1QQSB4QV0iP6BZ9/YB5fZaHFQ2dwHFrmPaRQ9GGMX01k9Q=="], + } +} diff --git a/packages/prosody-ui/index.ts b/packages/prosody-ui/index.ts new file mode 100644 index 0000000..f7339a2 --- /dev/null +++ b/packages/prosody-ui/index.ts @@ -0,0 +1,6 @@ +import LangText from "./src/LangText.tsx"; +import FontChanger from "./src/fonts/FontChanger.tsx"; +import Paragraph from "./src/Paragraph.tsx"; +import * as Zoom from "./src/zoom"; + +export { LangText, FontChanger, Paragraph, Zoom }; diff --git a/packages/prosody-ui/package.json b/packages/prosody-ui/package.json new file mode 100644 index 0000000..cf9ad48 --- /dev/null +++ b/packages/prosody-ui/package.json @@ -0,0 +1,22 @@ +{ + "name": "@sortug/prosody-ui", + "version": "0.1.0", + "module": "index.ts", + "type": "module", + "peerDependencies": { + "typescript": "^5.0.0", + "react": ">=19.0.0" + }, + "dependencies": { + "franc-all": "^7.2.0", + "motion": "^12.11.3", + "@sortug/lib": "workspace:*", + "@sortug/langlib": "workspace:*", + "@sortug/ai": "workspace:*" + }, + "private": true, + "devDependencies": { + "@types/bun": "^1.3.2", + "@types/react": "^19.2.6" + } +} diff --git a/packages/prosody-ui/src/LangText.tsx b/packages/prosody-ui/src/LangText.tsx new file mode 100644 index 0000000..790c499 --- /dev/null +++ b/packages/prosody-ui/src/LangText.tsx @@ -0,0 +1,78 @@ +import { franc } from "franc-all"; +import React, { useEffect, useState } from "react"; +import ThaiText from "./thai/ThaiText"; +import { ColoredText } from "./components/Sentence"; +import type { AnalyzeRes, WordData } from "./logic/types"; +import { detectScript, scriptFromLang } from "./logic/utils"; +import LatinText from "./latin/LatinText"; +import { buildWiktionaryURL, parseWiktionary } from "./logic/wiki"; +import type { Result } from "sortug"; + +export default function LangText({ + text, + lang, + theme, + fetchWiki, + handleWord, +}: { + text: string; + lang?: string; + theme?: string; + fetchWiki?: (url: string) => Promise<string>; + handleWord?: (wd: Result<WordData>) => any; +}) { + const [llang, setLang] = useState(""); + const [script, setScript] = useState(scriptFromLang(lang || "", text)); + useEffect(() => { + if (!lang) { + const res = franc(text); + setLang(res); + } else setLang(lang); + }, [text]); + console.log("langtext", { text, llang, script }); + + async function openWord(word: string) { + // console.log("looking up", word); + // const url = buildWiktionaryURL(word); + // const html = await fetchWiki(url); + // const parsed = parseWiktionary(html, url); + // console.log({ parsed }); + // if ("error" in parsed) handleWord(parsed); + // else { + // const wd: WordData = { + // spelling: word, + // lang: llang, + // ipa: parsed.ok.ipa[0], + // meanings: parsed.ok.meanings, + // references: { url: parsed.ok.url }, + // }; + // handleWord({ ok: wd }); + // } + // // const d = data[s]; + // // setModal(d); + // // setModal(<WordModal data={d} lang={lang} />); + } + + return ( + <div className="lang-text-container"> + {script === "Thai" ? ( + <ThaiText text={text} openWord={openWord} /> + ) : script === "Latin" ? ( + <LatinText text={text} lang={llang} openWord={openWord} /> + ) : ( + <Generic text={text} lang={llang} /> + )} + </div> + ); +} +function Generic({ text, lang }: { text: string; lang: string }) { + const [data, setData] = useState<AnalyzeRes>(); + useEffect(() => { + // segmentate(text, lang) + }, [text, lang]); + console.log({ lang }, "generic"); + // <p className="lang-lang">{lang}</p> + // <p className="lang-text">{text}</p> + // {data && <ColoredText frags={Object.keys(data)} />} + return <div className="lang-text-div"></div>; +} diff --git a/packages/prosody-ui/src/Paragraph.tsx b/packages/prosody-ui/src/Paragraph.tsx new file mode 100644 index 0000000..72c43a7 --- /dev/null +++ b/packages/prosody-ui/src/Paragraph.tsx @@ -0,0 +1,56 @@ +import { franc } from "franc-all"; +import React, { useCallback, useEffect, useState } from "react"; +import ThaiText from "./thai/ThaiText"; +import { ColoredText } from "./components/Sentence"; +import type { AnalyzeRes, WordData } from "./logic/types"; +import { detectScript, langFromScript } from "./logic/utils"; +import LatinText from "./latin/LatinText"; +import { buildWiktionaryURL, parseWiktionary } from "./logic/wiki"; +import type { Result } from "sortug"; +import * as Stanza from "./logic/stanza"; +import { iso6393To1 } from "./logic/iso6393to1"; + +export default function Paragraph({ + text, +}: { + text: string; + handleWord?: (wd: Result<WordData>) => any; +}) { + useEffect(() => { + segmentString(); + }, [text]); + const [lang, setLang] = useState(""); + const [script, setScript] = useState(""); + const [segs, setSegs] = useState<Stanza.StanzaSegment[]>([]); + useEffect(() => { + const res = franc(text); + console.log(); + console.log({ res, text }); + if (res === "und") detectLanguage(); + else { + const smol = iso6393To1[res]; + if (!smol) console.log("lang", res); + else setLang(smol); + } + }, [text]); + + const segmentString = useCallback(async () => { + if (lang) { + const res = await Stanza.segmenter(text, lang); + if ("ok" in res) setSegs(res.ok.segments); + console.log("stanza", res); + } + }, [text, lang]); + const detectLanguage = useCallback(async () => { + const script = detectScript(text); + if ("error" in script) console.log("ded"); + else { + setScript(script.ok); + const lng = langFromScript(script.ok); + if ("error" in lng) console.log("ded again!"); + else setLang(lng.ok); + } + }, [text]); + + return <div className="segmented-text">{text}</div>; +} diff --git a/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf b/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf Binary files differnew file mode 100644 index 0000000..5ada19c --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf Binary files differnew file mode 100644 index 0000000..2606d1c --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf Binary files differnew file mode 100644 index 0000000..49f5405 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf Binary files differnew file mode 100644 index 0000000..5da538b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf Binary files differnew file mode 100644 index 0000000..4b7e9bc --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf Binary files differnew file mode 100644 index 0000000..44f6a9f --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf b/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf Binary files differnew file mode 100644 index 0000000..8eb1209 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf Binary files differnew file mode 100644 index 0000000..1f16ba8 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf Binary files differnew file mode 100644 index 0000000..e86fb96 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf Binary files differnew file mode 100644 index 0000000..76812d7 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf Binary files differnew file mode 100644 index 0000000..db381ed --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf Binary files differnew file mode 100644 index 0000000..e30cdd8 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf Binary files differnew file mode 100644 index 0000000..8be49fc --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf Binary files differnew file mode 100644 index 0000000..f45d4ec --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf Binary files differnew file mode 100644 index 0000000..2a62b97 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf Binary files differnew file mode 100644 index 0000000..bc3e266 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf Binary files differnew file mode 100644 index 0000000..832c29f --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-VariableFont_wght.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-VariableFont_wght.ttf Binary files differnew file mode 100644 index 0000000..47f2c84 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-VariableFont_wght.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf Binary files differnew file mode 100644 index 0000000..b59a399 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf b/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf Binary files differnew file mode 100644 index 0000000..9364f2d --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf Binary files differnew file mode 100644 index 0000000..e2d4fad --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/dingliezhuhaifont-20240831GengXinBan)-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/dingliezhuhaifont-20240831GengXinBan)-2.ttf Binary files differnew file mode 100644 index 0000000..b387fc5 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/dingliezhuhaifont-20240831GengXinBan)-2.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Hani/style.css b/packages/prosody-ui/src/assets/fonts/Hani/style.css new file mode 100644 index 0000000..2048617 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/style.css @@ -0,0 +1,223 @@ +/* https://www.fonts.net.cn/fonts-zh/tag-yankai-1.html */ + + +@font-face { + font-family: "BeiShiDaJiaGuWen"; + src: url(./BeiShiDaJiaGuWenZiTi-1.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "ShanShouGuHuangTi"; + src: url(./No.300-ShangShouGuHuangTi-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "DinglieZhuhai"; + src: url(./dingliezhuhaifont-20240831GengXinBan-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "ShouJin"; + src: url(./GaiLiangShouJinTi-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "GudianMingChaoKai"; + src: url(./GuDianMingChaoKai-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-SemiBold.ttf); + font-weight: 500; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Black.ttf); + font-weight: 900; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Thin.ttf); + font-weight: 200; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Bold.ttf); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-VariableFont_wght.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-ExtraBold.ttf); + font-weight: 800; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-ExtraLight.ttf); + font-weight: 100; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Light.ttf); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Regular.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(./NotoSansHK-Medium.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Iansui"; + src: url(./Iansui-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "YeZiGongXingCao"; + src: url(./YeZiGongChangZuiHanJiangXingCao-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "LiuJianMaoCao"; + src: url(./LiuJianMaoCao-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "YiShanBeiZhuanti"; + src: url(./YiShanBeiZhuanTi.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "LongCang"; + src: url(./LongCang-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "ZhiMangXing"; + src: url(./ZhiMangXing-Regular.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Meirenzhuan"; + src: url(./Meirenzhuan.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "TianlongXingkai"; + src: url(./字魂天龙行楷.ttf); + font-weight: 300; + font-style: normal; +} + + +.font-Hani-0 { + font-family: "ShouJin"; +} + +.font-Hani-1 { + font-family: "DinglieZhuhai"; +} + +.font-Hani-2 { + font-family: "GudianMingChaokai"; +} + +.font-Hani-3 { + font-family: "NotoSansHK"; +} + +.font-Hani-4 { + font-family: "ShanShouGuHuangTi"; +} + +.font-Hani-5 { + font-family: "Iansui"; +} + +.font-Hani-6 { + font-family: "YeZiGongXingCao"; +} + +.font-Hani-7 { + font-family: "LiuJianMaoCao"; +} + +.font-Hani-8 { + font-family: "YiShanBeiZhuanti"; +} + +.font-Hani-9 { + font-family: "LongCang"; +} + +.font-Hani-10 { + font-family: "ZhiMangXing"; +} + +.font-Hani-11 { + font-family: "Meirenzhuan"; +} + +.font-Hani-12 { + font-family: "TianlongXingkai"; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/fonts/Hani/字魂天龙行楷.ttf b/packages/prosody-ui/src/assets/fonts/Hani/字魂天龙行楷.ttf Binary files differnew file mode 100644 index 0000000..b565e37 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Hani/字魂天龙行楷.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf Binary files differnew file mode 100755 index 0000000..4b977b0 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf Binary files differnew file mode 100755 index 0000000..b2ea190 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf Binary files differnew file mode 100755 index 0000000..a1cbb58 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf Binary files differnew file mode 100755 index 0000000..4e962ee --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf Binary files differnew file mode 100755 index 0000000..f7d0d78 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf Binary files differnew file mode 100755 index 0000000..36aa975 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/IPA/style.css b/packages/prosody-ui/src/assets/fonts/IPA/style.css new file mode 100644 index 0000000..ecc0a8a --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/IPA/style.css @@ -0,0 +1,33 @@ +@font-face { + font-family: "Voces"; + src: url(./Voces-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "Judson"; + src: url(./Judson-Regular.ttf); + font-weight: 300; + font-style: normal +} + +/* TODO check the specifics of variable fonts */ +@font-face { + font-family: "Noto Sans"; + src: url(./NotoSans-VariableFont_wdth,wght.ttf); + font-weight: 300; + font-style: normal +} + +.font-IPA-0 { + font-family: "Voces"; +} + +.font-IPA-1 { + font-family: "Judson"; +} + +.font-IPA-2 { + font-family: "Noto Sans"; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/DelaGothicOne-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/DelaGothicOne-Regular.ttf Binary files differnew file mode 100644 index 0000000..475c4dd --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/DelaGothicOne-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf Binary files differnew file mode 100644 index 0000000..7d13d05 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf Binary files differnew file mode 100644 index 0000000..1e35712 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf Binary files differnew file mode 100644 index 0000000..7d68508 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf Binary files differnew file mode 100644 index 0000000..c78f7d6 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf Binary files differnew file mode 100644 index 0000000..cb3044e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/style.css b/packages/prosody-ui/src/assets/fonts/Jpan/style.css new file mode 100644 index 0000000..cd1b79f --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Jpan/style.css @@ -0,0 +1,223 @@ +/* https://www.fonts.net.cn/fonts-zh/tag-yankai-1.html */ + + +@font-face { + font-family: "BeiShiDaJiaGuWen"; + src: url(../Hani/BeiShiDaJiaGuWenZiTi-1.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "ShanShouGuHuangTi"; + src: url(../Hani/No.300-ShangShouGuHuangTi-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "DinglieZhuhai"; + src: url(../Hani/dingliezhuhaifont-20240831GengXinBan-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "ShouJin"; + src: url(../Hani/GaiLiangShouJinTi-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "GudianMingChaoKai"; + src: url(../Hani/GuDianMingChaoKai-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-SemiBold.ttf); + font-weight: 500; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Black.ttf); + font-weight: 900; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Thin.ttf); + font-weight: 200; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Bold.ttf); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-VariableFont_wght.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-ExtraBold.ttf); + font-weight: 800; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-ExtraLight.ttf); + font-weight: 100; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Light.ttf); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Regular.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "NotoSansHK"; + src: url(../Hani/NotoSansHK-Medium.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Iansui"; + src: url(../Hani/Iansui-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "YeZiGongXingCao"; + src: url(../Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "LiuJianMaoCao"; + src: url(../Hani/LiuJianMaoCao-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "YiShanBeiZhuanti"; + src: url(../Hani/YiShanBeiZhuanTi.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "LongCang"; + src: url(../Hani/LongCang-Regular.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "ZhiMangXing"; + src: url(../Hani/ZhiMangXing-Regular.ttf); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: "Meirenzhuan"; + src: url(../Hani/Meirenzhuan.ttf); + font-weight: 300; + font-style: normal; +} + + +@font-face { + font-family: "TianlongXingkai"; + src: url(../Hani/字魂天龙行楷.ttf); + font-weight: 300; + font-style: normal; +} + + +.font-Hani-0 { + font-family: "ShouJin"; +} + +.font-Hani-1 { + font-family: "DinglieZhuhai"; +} + +.font-Hani-2 { + font-family: "GudianMingChaokai"; +} + +.font-Hani-3 { + font-family: "NotoSansHK"; +} + +.font-Hani-4 { + font-family: "ShanShouGuHuangTi"; +} + +.font-Hani-5 { + font-family: "Iansui"; +} + +.font-Hani-6 { + font-family: "YeZiGongXingCao"; +} + +.font-Hani-7 { + font-family: "LiuJianMaoCao"; +} + +.font-Hani-8 { + font-family: "YiShanBeiZhuanti"; +} + +.font-Hani-9 { + font-family: "LongCang"; +} + +.font-Hani-10 { + font-family: "ZhiMangXing"; +} + +.font-Hani-11 { + font-family: "Meirenzhuan"; +} + +.font-Hani-12 { + font-family: "TianlongXingkai"; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/OFL.txt b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/OFL.txt new file mode 100644 index 0000000..3e92931 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Black.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Black.ttf Binary files differnew file mode 100644 index 0000000..71c0f99 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Black.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BlackItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BlackItalic.ttf Binary files differnew file mode 100644 index 0000000..7aeb58b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BlackItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf Binary files differnew file mode 100644 index 0000000..00559ee --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BoldItalic.ttf Binary files differnew file mode 100644 index 0000000..e61e8e8 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBold.ttf Binary files differnew file mode 100644 index 0000000..df70936 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..14d2b37 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLight.ttf Binary files differnew file mode 100644 index 0000000..e76ec69 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLightItalic.ttf Binary files differnew file mode 100644 index 0000000..89513d9 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Italic.ttf Binary files differnew file mode 100644 index 0000000..12b7b3c --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Light.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Light.ttf Binary files differnew file mode 100644 index 0000000..bc36bcc --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-LightItalic.ttf Binary files differnew file mode 100644 index 0000000..9e70be6 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-LightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Medium.ttf Binary files differnew file mode 100644 index 0000000..6bcdcc2 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-MediumItalic.ttf Binary files differnew file mode 100644 index 0000000..be67410 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-MediumItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Regular.ttf Binary files differnew file mode 100644 index 0000000..9f0c71b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf Binary files differnew file mode 100644 index 0000000..74c726e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..3e6c942 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf Binary files differnew file mode 100644 index 0000000..03e7366 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ThinItalic.ttf b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ThinItalic.ttf Binary files differnew file mode 100644 index 0000000..e26db5d --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ThinItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Latn/style.css b/packages/prosody-ui/src/assets/fonts/Latn/style.css new file mode 100644 index 0000000..e2aef9b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Latn/style.css @@ -0,0 +1,11 @@ +@font-face { + font-family: "Poppins"; + src: url(./Poppins.ttf); + font-weight: 300; + font-style: normal; +} + + +.font-Latn-0 { + font-family: "Poppins"; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Charm-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Bold.ttf Binary files differnew file mode 100755 index 0000000..d32f072 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf Binary files differnew file mode 100755 index 0000000..02013a4 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf Binary files differnew file mode 100755 index 0000000..52fedc7 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf Binary files differnew file mode 100755 index 0000000..3a8583f --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf Binary files differnew file mode 100755 index 0000000..c4161bd --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf Binary files differnew file mode 100755 index 0000000..a676550 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf Binary files differnew file mode 100755 index 0000000..75e62df --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf Binary files differnew file mode 100755 index 0000000..c31b8c2 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf Binary files differnew file mode 100755 index 0000000..9812b5a --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf Binary files differnew file mode 100755 index 0000000..2cc968f --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf Binary files differnew file mode 100755 index 0000000..2e37a00 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf Binary files differnew file mode 100755 index 0000000..dc81853 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf Binary files differnew file mode 100755 index 0000000..4686906 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf Binary files differnew file mode 100755 index 0000000..17eda2a --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf Binary files differnew file mode 100755 index 0000000..5240d38 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..037187a --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf Binary files differnew file mode 100755 index 0000000..404c1e0 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf Binary files differnew file mode 100755 index 0000000..5d575cc --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf Binary files differnew file mode 100755 index 0000000..e6d868b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf Binary files differnew file mode 100755 index 0000000..3c9d4b5 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf Binary files differnew file mode 100755 index 0000000..59a3f2e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf Binary files differnew file mode 100755 index 0000000..50413d0 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf Binary files differnew file mode 100755 index 0000000..2c6aa14 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf Binary files differnew file mode 100755 index 0000000..ef204c1 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf Binary files differnew file mode 100755 index 0000000..7501a2e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..2284650 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf Binary files differnew file mode 100755 index 0000000..5c835ad --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf Binary files differnew file mode 100755 index 0000000..25fd1f9 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf Binary files differnew file mode 100755 index 0000000..cd36ffc --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf Binary files differnew file mode 100755 index 0000000..f86a715 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf Binary files differnew file mode 100755 index 0000000..af416d2 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf Binary files differnew file mode 100755 index 0000000..3478406 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf Binary files differnew file mode 100755 index 0000000..3032d77 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf Binary files differnew file mode 100755 index 0000000..b3db128 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf Binary files differnew file mode 100755 index 0000000..5acfdd5 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf Binary files differnew file mode 100755 index 0000000..de8f843 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf Binary files differnew file mode 100755 index 0000000..2c0cb1e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf Binary files differnew file mode 100755 index 0000000..b6cb5d5 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf Binary files differnew file mode 100755 index 0000000..917a988 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..36d3579 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf Binary files differnew file mode 100755 index 0000000..db8c190 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf Binary files differnew file mode 100755 index 0000000..a67a0ae --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf Binary files differnew file mode 100755 index 0000000..0e3f955 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf Binary files differnew file mode 100755 index 0000000..6f4d3d3 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf Binary files differnew file mode 100755 index 0000000..479a8e8 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf Binary files differnew file mode 100755 index 0000000..aaad3b6 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf Binary files differnew file mode 100755 index 0000000..cdfa5c6 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf Binary files differnew file mode 100755 index 0000000..658a6a1 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf Binary files differnew file mode 100755 index 0000000..4b88574 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf Binary files differnew file mode 100755 index 0000000..70cd35b --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf Binary files differnew file mode 100755 index 0000000..acdce49 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..fc76e74 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf Binary files differnew file mode 100755 index 0000000..4d6bf36 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf Binary files differnew file mode 100755 index 0000000..42857a5 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf Binary files differnew file mode 100755 index 0000000..27ba997 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..bc36f97 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf Binary files differnew file mode 100755 index 0000000..060c6c1 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf Binary files differnew file mode 100755 index 0000000..beaa024 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf Binary files differnew file mode 100755 index 0000000..51d6dbe --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf Binary files differnew file mode 100755 index 0000000..d2f2291 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf Binary files differnew file mode 100755 index 0000000..75eb8d8 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf Binary files differnew file mode 100755 index 0000000..e03148e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf Binary files differnew file mode 100755 index 0000000..b172a09 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf Binary files differnew file mode 100755 index 0000000..50fa707 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf Binary files differnew file mode 100755 index 0000000..7b760ce --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf Binary files differnew file mode 100755 index 0000000..ecc5fb6 --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf Binary files differnew file mode 100755 index 0000000..cdaabcb --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf Binary files differnew file mode 100755 index 0000000..e96d17e --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf diff --git a/packages/prosody-ui/src/assets/fonts/Thai/style.css b/packages/prosody-ui/src/assets/fonts/Thai/style.css new file mode 100644 index 0000000..14b828c --- /dev/null +++ b/packages/prosody-ui/src/assets/fonts/Thai/style.css @@ -0,0 +1,76 @@ +@font-face { + font-family: "Kanit"; + src: url(./Kanit-Regular.ttf); +} + +@font-face { + font-family: "Sarabun"; + src: url(./Sarabun-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "IBM Plex Sans Thai"; + src: url(./IBMPlexSansThai-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "Mali"; + src: url(./Mali-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "Kodchasan"; + src: url(./Kodchasan-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "Chonburi"; + src: url(./Chonburi-Regular.ttf); + font-weight: 300; + font-style: normal +} + +@font-face { + font-family: "Charm"; + src: url(./Charm-Regular.ttf); + font-weight: 300; + font-style: normal +} + + + +.font-Thai-0 { + font-family: "Sarabun"; +} + +.font-Thai-1 { + font-family: "Kanit"; +} + +.font-Thai-2 { + font-family: "IBM Plex Sans Thai"; +} + +.font-Thai-3 { + font-family: "Mali"; +} + +.font-Thai-4 { + font-family: "Kodchasan"; +} + +.font-Thai-5 { + font-family: "Charm"; +} + +.font-Thai-6 { + font-family: "Chonburi"; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/icons/bookmark.svg b/packages/prosody-ui/src/assets/icons/bookmark.svg new file mode 100755 index 0000000..07c1129 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/bookmark.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5 19.6693V4C5 3.44772 5.44772 3 6 3H18C18.5523 3 19 3.44772 19 4V19.6693C19 20.131 18.4277 20.346 18.1237 19.9985L12 13L5.87629 19.9985C5.57227 20.346 5 20.131 5 19.6693Z" stroke="#000000" stroke-linejoin="round"/>
+</svg>
diff --git a/packages/prosody-ui/src/assets/icons/font.svg b/packages/prosody-ui/src/assets/icons/font.svg new file mode 100755 index 0000000..d4d5c72 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/font.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M4.51 2.6.25 13.67h1.34l1.49-3.86h4l1.52 3.86h1.34L5.68 2.6a.63.63 0 0 0-1.17 0zm-.95 6 1.54-4 1.53 4zm9.35-2.54a2.8 2.8 0 0 0-3 2.08l1.21.31a1.6 1.6 0 0 1 1.78-1.14c.77 0 1.59.26 1.59 1v.75c-.27 0-.63.09-.94.13a9.12 9.12 0 0 0-2.5.52 2.06 2.06 0 0 0-1.41 2.23 1.94 1.94 0 0 0 .88 1.44 3 3 0 0 0 1.62.43 4.39 4.39 0 0 0 1.36-.22 2.92 2.92 0 0 0 1-.52v.61h1.25V8.3c0-1.3-1.14-2.24-2.84-2.24zm.22 6.33a2.4 2.4 0 0 1-1.91-.07.64.64 0 0 1-.32-.52c-.1-.89.82-1.16 2.8-1.38l.76-.1c-.19 1.68-.94 1.94-1.33 2.07z"/></svg>
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/icons/heart.svg b/packages/prosody-ui/src/assets/icons/heart.svg new file mode 100755 index 0000000..f728e1e --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/heart.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M21 8.99998C21 12.7539 15.7156 17.9757 12.5857 20.5327C12.2416 20.8137 11.7516 20.8225 11.399 20.5523C8.26723 18.1523 3 13.1225 3 8.99998C3 2.00001 12 2.00002 12 8C12 2.00001 21 1.99999 21 8.99998Z" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/packages/prosody-ui/src/assets/icons/play.svg b/packages/prosody-ui/src/assets/icons/play.svg new file mode 100755 index 0000000..9a56073 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/play.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 -2 19 19" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#000000" fill-rule="evenodd" d="M657,246.007484 C657,245.451066 657.450925,245 657.994771,245 L675.005229,245 C675.554626,245 676,245.44892 676,246.007484 L676,258.992516 C676,259.548934 675.549075,260 675.005229,260 L657.994771,260 C657.445374,260 657,259.55108 657,258.992516 L657,246.007484 Z M658,246 L675,246 L675,259 L658,259 L658,246 Z M670.113445,252.056723 C670.603076,252.301538 670.603593,252.698203 670.113445,252.943277 L664.886555,255.556723 C664.396924,255.801538 664,255.562119 664,254.997071 L664,250.002929 C664,249.449027 664.396407,249.198203 664.886555,249.443277 L670.113445,252.056723 Z" transform="translate(-657 -245)"/>
+</svg>
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/icons/quote.svg b/packages/prosody-ui/src/assets/icons/quote.svg new file mode 100755 index 0000000..34f5de9 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/quote.svg @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
+<g id="Quotemarks-right">
+ <path d="M14.1933422,9.4116497c-7.8260994,0-14.1922989,6.3662004-14.1922989,14.1924
+ c0,7.5498009,5.9247999,13.7420998,13.3690996,14.169899c0.1288996,1.3916016,0.0321999,5.1797028-3.5977001,10.4491997
+ C9.4980431,48.6206512,9.547843,49.1567497,9.888648,49.497551c1.4853945,1.4853973,2.4033947,2.4208984,3.0458946,3.0751991
+ c0.8408995,0.8554993,1.2247,1.2461014,1.7861996,1.7559013c0.1904001,0.1727982,0.4306002,0.259697,0.6719055,0.259697
+ c0.2342949,0,0.4676943-0.0819969,0.6561956-0.2450981c6.3251991-5.5038986,13.3515987-16.8759995,12.3349991-30.8115005
+ C27.7881413,15.3501501,21.820343,9.4116497,14.1933422,9.4116497z M15.4023428,52.2221489
+ c-0.2723999-0.2684975-0.5830002-0.5848999-1.0410004-1.0508003c-0.5565996-0.5672989-1.3203001-1.3446999-2.4784994-2.5067978
+ c4.4053001-6.7881012,3.5731993-11.6230011,3.2089996-12.3164024c-0.1729002-0.3290977-0.5274-0.5507965-0.8985004-0.5507965
+ c-6.7225995,0-12.1922989-5.4697018-12.1922989-12.1933022c0-6.7227001,5.4696999-12.1924,12.1922989-12.1924
+ c6.5489006,0,11.6777992,5.1582012,12.1963062,12.2646008C27.5322418,39.3501511,18.2168427,49.5268517,15.4023428,52.2221489z"/>
+ <path d="M63.9004402,23.5317497v-0.0009995C63.302742,15.3501501,57.3340416,9.4116497,49.7090416,9.4116497
+ c-7.8261986,0-14.1933937,6.3662004-14.1933937,14.1924c0,7.5498009,5.9257927,13.7420998,13.3710938,14.169899
+ c0.1289062,1.3906021,0.0312004,5.1767006-3.5996017,10.4491997c-0.2743988,0.3975029-0.2245979,0.9336014,0.1162033,1.2744026
+ c1.4794998,1.4794998,2.3955002,2.4130974,3.0380974,3.0663986c0.8446999,0.8613014,1.2304993,1.2538986,1.7949028,1.7656021
+ c0.1903992,0.1718979,0.4315987,0.2587967,0.6718979,0.2587967c0.2344055,0,0.4678001-0.0819969,0.6562004-0.2460976
+ C57.8896484,48.8383484,64.9160385,37.4663506,63.9004402,23.5317497z M50.917942,52.2221489
+ c-0.2743988-0.2705002-0.5877991-0.5887985-1.0498009-1.0594978c-0.5565987-0.5665016-1.3172989-1.3418007-2.4706993-2.4981003
+ c4.4053001-6.7891006,3.5742989-11.6230011,3.2109985-12.3164024c-0.1728973-0.3280983-0.5282974-0.5507965-0.8993988-0.5507965
+ c-6.7237015,0-12.1933937-5.4697018-12.1933937-12.1933022c0-6.7227001,5.4696922-12.1924,12.1933937-12.1924
+ c6.5477982,0,11.6777,5.1582012,12.1972008,12.2656002v-0.0009995
+ C63.0478401,39.3481483,53.7324409,49.5268517,50.917942,52.2221489z"/>
+</g>
+</svg>
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/icons/react.svg b/packages/prosody-ui/src/assets/icons/react.svg new file mode 100755 index 0000000..6c87de9 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/react.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
\ No newline at end of file diff --git a/packages/prosody-ui/src/assets/icons/share.svg b/packages/prosody-ui/src/assets/icons/share.svg new file mode 100755 index 0000000..92c2b94 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/share.svg @@ -0,0 +1,28 @@ +<!--?xml version="1.0" encoding="utf-8"?--> +<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> + +<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#4B4B4B;} +</style> +<g> + <path class="st0" d="M398.73,227.402c62.563,0,113.27-50.793,113.27-113.359c0-62.656-50.707-113.36-113.27-113.36 + c-62.656,0-113.364,50.704-113.364,113.36c0,11.587,1.733,22.711,4.926,33.292l-114.914,69.397 + c-18.512-20.154-44.959-32.739-74.417-32.739C45.146,183.993,0,229.228,0,284.954c0,55.816,45.146,100.962,100.962,100.962 + c30.736,0,58.278-13.778,76.79-35.482l86.824,45.787c-2.646,8.39-4.106,17.323-4.106,26.63 + c0.093,48.878,39.673,88.466,88.555,88.466c48.976,0,88.556-39.588,88.556-88.466c0-48.976-39.58-88.554-88.556-88.554 + c-26.812,0-50.886,11.942-67.122,30.825l-84.726-49.431c3.104-9.672,4.742-19.976,4.742-30.736c0-10.393-1.55-20.43-4.56-29.827 + l118.013-64.294C335.985,213.268,365.715,227.402,398.73,227.402z M344.282,59.687c14.045-13.956,33.11-22.524,54.448-22.524 + c21.251,0,40.31,8.567,54.356,22.524c13.862,13.956,22.434,33.016,22.434,54.356c0,21.25-8.572,40.399-22.434,54.354 + c-14.046,13.956-33.105,22.525-54.356,22.525c-19.059,0-36.298-6.84-49.794-18.419h-0.094c-1.55-1.273-3.099-2.645-4.56-4.106 + c-10.852-10.946-18.422-24.991-21.246-40.852c-0.824-4.382-1.189-8.942-1.189-13.502C321.846,92.703,330.419,73.644,344.282,59.687 + z M164.343,296.532c-2.28,13.138-8.661,24.902-17.781,34.022c-0.731,0.73-1.55,1.461-2.373,2.192 + c-11.49,10.393-26.536,16.69-43.227,16.69c-17.874,0-33.928-7.205-45.6-18.881c-11.676-11.765-18.881-27.725-18.881-45.6 + c0-17.874,7.205-33.834,18.881-45.6c11.672-11.676,27.726-18.881,45.6-18.881c16.232,0,30.825,5.932,42.225,15.782 + c1.185,0.997,2.28,2.004,3.376,3.099c9.027,9.12,15.413,20.698,17.781,33.746c0.73,3.83,1.095,7.748,1.095,11.854 + C165.438,288.873,165.074,292.801,164.343,296.532z M297.773,413.73c1.915-10.767,7.022-20.253,14.499-27.725 + c0.638-0.641,1.367-1.372,2.098-1.915c9.21-8.39,21.251-13.314,34.654-13.314c14.504,0,27.36,5.745,36.846,15.23 + c9.485,9.485,15.23,22.346,15.23,36.845c0,14.411-5.745,27.272-15.23,36.748c-9.486,9.486-22.342,15.238-36.846,15.238 + c-14.406,0-27.266-5.753-36.752-15.238c-9.485-9.476-15.23-22.337-15.322-36.748C296.95,419.751,297.225,416.643,297.773,413.73z"></path> +</g> +</svg> diff --git a/packages/prosody-ui/src/assets/icons/speaker.svg b/packages/prosody-ui/src/assets/icons/speaker.svg new file mode 100644 index 0000000..a16db51 --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/speaker.svg @@ -0,0 +1,32 @@ +<!--?xml version="1.0" encoding="utf-8"?--> +<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> + +<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#4B4B4B;} +</style> +<g> + <path class="st0" d="M242.908,77.65c-14.745,0-28.695,6.578-41.1,18.231L84.032,170.798H51.761c-4.486,0-8.883,0.893-12.887,2.457 + c-7.042,2.77-12.814,7.426-17.569,12.941c-7.113,8.319-12.225,18.73-15.808,30.554C1.939,228.592,0,241.889,0,256 + c0,10.751,1.126,21.037,3.235,30.546c3.19,14.28,8.418,26.855,16.086,36.828c3.861,4.969,8.382,9.312,13.816,12.556 + c5.407,3.244,11.876,5.29,18.624,5.272h32.271l117.785,74.917c12.396,11.653,26.346,18.231,41.091,18.231 + c51.529,0,93.3-79.849,93.3-178.35S294.437,77.65,242.908,77.65z M78.732,311.023H51.761c-0.58-0.009-1.116-0.09-1.894-0.394 + c-1.313-0.491-3.378-1.823-5.684-4.512c-3.468-3.986-7.185-10.84-9.785-19.562c-2.628-8.723-4.219-19.258-4.219-30.555 + c0-8.615,0.921-16.774,2.52-24.031c2.387-10.884,6.444-19.714,10.492-24.862c2.002-2.601,3.932-4.244,5.38-5.094 + c1.483-0.858,2.342-1.01,3.19-1.037h26.971c-1.752,3.968-3.297,8.178-4.629,12.61c-3.808,12.646-5.925,27.069-5.925,42.414 + C68.196,276.742,72.03,295.759,78.732,311.023z M166.32,357.771l-66.372-42.217c-3.915-5.648-7.463-13.101-10.081-21.877 + c-3.289-10.948-5.228-23.861-5.228-37.677c-0.027-21.046,4.531-40.036,11.386-53.066c1.233-2.359,2.538-4.522,3.878-6.462 + l66.417-42.244c-10.518,28.866-16.694,63.924-16.694,101.771C149.627,293.838,155.812,328.906,166.32,357.771z M242.908,404.161 + c-25.719,0-63.102-57.712-63.102-148.161c0-90.448,37.383-148.17,63.102-148.17c25.738,0,63.111,57.722,63.111,148.17 + C306.018,346.448,268.645,404.161,242.908,404.161z" style="fill: rgb(75, 75, 75);"></path> + <path class="st0" d="M243.605,212.684v-0.09c-0.169,0-0.33,0.045-0.491,0.054c-0.233-0.009-0.474-0.054-0.715-0.054v0.134 + c-11.18,1.322-20.063,21.001-20.063,45.139s8.883,43.816,20.063,45.148v0.125c0.24,0,0.482-0.045,0.715-0.054 + c0.161,0.009,0.322,0.054,0.491,0.054v-0.09c16.676-0.92,30.01-20.76,30.01-45.184 + C273.614,233.452,260.281,213.604,243.605,212.684z" style="fill: rgb(75, 75, 75);"></path> + <path class="st0" d="M481.696,142.996l-25.085,13.986c17.185,30.859,26.658,65.524,26.666,103.013 + c-0.008,37.472-9.481,72.137-26.666,102.996l25.085,13.995v-0.009c19.491-34.942,30.313-74.63,30.304-116.981 + C512.009,217.626,501.187,177.938,481.696,142.996z" style="fill: rgb(75, 75, 75);"></path> + <path class="st0" d="M383.026,195.588c9.384,19.456,14.558,41.073,14.567,64.398c-0.009,23.325-5.183,44.952-14.567,64.389 + l25.862,12.484c11.225-23.244,17.427-49.268,17.418-76.873c0.008-27.614-6.194-53.629-17.418-76.882L383.026,195.588z" style="fill: rgb(75, 75, 75);"></path> +</g> +</svg> diff --git a/packages/prosody-ui/src/assets/icons/spinner.svg b/packages/prosody-ui/src/assets/icons/spinner.svg new file mode 100755 index 0000000..2a516de --- /dev/null +++ b/packages/prosody-ui/src/assets/icons/spinner.svg @@ -0,0 +1 @@ +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_z9k8{transform-origin:center;animation:spinner_StKS .75s infinite linear}@keyframes spinner_StKS{100%{transform:rotate(360deg)}}</style><path d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25"/><path d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" class="spinner_z9k8"/></svg> diff --git a/packages/prosody-ui/src/components/Sentence.tsx b/packages/prosody-ui/src/components/Sentence.tsx new file mode 100644 index 0000000..33144ac --- /dev/null +++ b/packages/prosody-ui/src/components/Sentence.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { notRandomFromArray } from "sortug"; +import "./sentence.css"; + +export function ColoredText({ + frags, + fn, + lang, +}: { + frags: string[]; + fn?: (s: string) => void; + lang?: string; +}) { + return ( + <> + {frags.map((s, i) => { + const prev = frags[i - 1]; + const prevC = prev ? notRandomFromArray(prev, colors) : "lol"; + const color = notRandomFromArray(s, colors); + const opacity = prev && prevC === color ? 0.8 : 1; + const style = { color, opacity }; + console.log({ style }); + return <CTInner lang={lang} key={s + i} s={s} style={style} fn={fn} />; + })} + </> + ); +} + +export function CTInner({ + s, + style, + fn, + lang, +}: { + s: string; + style: any; + fn?: (s: string) => void; + lang?: string; +}) { + function handleClick(e: React.MouseEvent<HTMLSpanElement>) { + console.log(!!fn, "fn"); + if (fn) fn(e.currentTarget.innerText.trim()); + } + return ( + <span lang={lang} onClick={handleClick} className="word cp" style={style}> + {s} + </span> + ); +} +export const colors = [ + "#8c2c2c", + "#000000", + "#ffd400", + "#1513a0", + "#7e7e7e", + "1eb52d", +]; diff --git a/packages/prosody-ui/src/components/Word.tsx b/packages/prosody-ui/src/components/Word.tsx new file mode 100644 index 0000000..82939ce --- /dev/null +++ b/packages/prosody-ui/src/components/Word.tsx @@ -0,0 +1,119 @@ +import React, { useCallback, useEffect, useState } from "react"; +import spinner from "../assets/icons/spinner.svg"; +import likeIcon from "../assets/icons/heart.svg"; +import commentsIcon from "../assets/icons/quote.svg"; +import shareIcon from "../assets/icons/share.svg"; +import fontIcon from "../assets/icons/font.svg"; +import bookmarkIcon from "../assets/icons/bookmark.svg"; +import speakerIcon from "../assets/icons/speaker.svg"; +import type { AnalyzeRes, Meaning } from "../logic/types"; +import { ColoredText } from "./Sentence.tsx"; +import { P, Span, useSpeechSynthesis } from "../hooks/useLang.tsx"; + +function Word({ data, lang }: { data: AnalyzeRes; lang: string }) { + async function load() { + // const wiki = await fetchWiki(data.word); + // console.log(wiki, "wiki res"); + // if ("ok" in wiki) setM(wiki.ok.meanings); + // else setError(wiki.error); + // setLoading(false); + } + useEffect(() => { + load(); + }, []); + const [error, setError] = useState(""); + const [loading, setLoading] = useState(true); + const [meanings, setM] = useState<Meaning[]>([]); + const [font, setFont] = useState(0); + + function changeFont() { + if (font === 6) setFont(0); + else setFont(font + 1); + } + const { voices, speaking, speak, stop } = useSpeechSynthesis(); + function playAudio() { + console.log({ voices, speaking }); + console.log("word", data.word); + speak(data.word); + } + + async function saveW() {} + + return ( + <div className={`font-${font}`} id="word-modal" title={data.word}> + <img className="font-icon cp" onClick={changeFont} src={fontIcon} /> + <img className="save-icon cp" onClick={saveW} src={bookmarkIcon} /> + <div className="original"> + <ColoredText frags={data.syllables} /> + </div> + <div className="pronunciation IPA flex1 flex-center"> + <P>{`/${data.ipa.replace(/\s/g, "")}/`}</P> + <img onClick={playAudio} className="icon cp" src={speakerIcon} /> + </div> + <div className="meanings"> + {loading ? ( + <img src={spinner} className="spinner bc" /> + ) : ( + meanings.map((m) => ( + <div key={JSON.stringify(m)} className="meaning"> + <div className="pos"> + <Span>{m.pos}</Span> + </div> + <ol> + {m.meaning.map((t, i) => ( + <li key={t + i} className="translation"> + <P>{t}</P> + </li> + ))} + </ol> + </div> + )) + )} + {error && <div className="error">{error}</div>} + </div> + </div> + ); +} + +export default Word; + +// function FloatingButtons({ +// tweet, +// avatar, +// changeFont, +// }: { +// tweet: Tweet; +// avatar: string; +// changeFont: any; +// }) { +// const { apiKeys, prompts, setModal } = useGlobalState(); +// function openUser() {} +// function openComments() {} +// function openShare() {} +// async function doLike() { +// const key = apiKeys.openai; +// // TODO hide button if key not set +// console.log(tweet.text, "whole text"); +// console.log(tweet.media, "media"); +// if (tweet.media[0] && !tweet.media[0].isVideo) { +// const res = await vision(tweet.media[0].url, "", key); +// console.log(res, "vision res"); +// } +// // const res = await translate(tweet.text, prompts.translate,key); +// // if ("ok" in res) +// // setModal(<TranslationModal text={res.ok.choices[0].message.content}/>) +// } +// async function doBookmark() {} +// return ( +// <div id="entry-icons"> +// <div className="avatar"> +// <img className="cp" onClick={openUser} src={avatar} /> +// </div> +// <img className="cp" onClick={doLike} src={likeIcon} /> +// <img className="cp" onClick={openComments} src={commentsIcon} /> +// <img className="cp" onClick={doBookmark} src={bookmarkIcon} /> +// <img className="cp" onClick={openShare} src={shareIcon} /> +// <img className="cp" onClick={changeFont} src={fontIcon} /> +// </div> +// ); +// } diff --git a/packages/prosody-ui/src/components/sentence.css b/packages/prosody-ui/src/components/sentence.css new file mode 100644 index 0000000..0bd0a49 --- /dev/null +++ b/packages/prosody-ui/src/components/sentence.css @@ -0,0 +1,272 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +#root>.spinner { + width: 100px; + height: 100px; +} + +#entry>.spinner { + width: 80px; + height: 80px; +} + + + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} + +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} + +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +#cookies { + & .active { + background-color: var(--huang); + } + + & input { + margin-left: 1rem; + width: 100%; + } + + & textarea { + width: 100%; + height: 500px; + resize: none; + outline: none; + } +} + +#entry { + width: 100%; + height: 100%; + position: relative; + padding: 1rem; + /* prov */ + border: 2px solid black; + + & div[lang="th"] { + + & .tw-text, + & .tw-hashtag { + font-size: 3rem; + } + } + + & .text-wrapper { + display: block; + margin: 0.5rem 0; + /* overflow: hidden; */ + } + + & .word { + display: inline-block; + transition: transform 0.3s ease; + } + + & .word:hover { + transform: scale(1.4); + background-color: white; + } + + & #tw-media { + max-width: 100%; + + & img, + & video { + max-width: 100%; + } + } +} + +#inner { + height: 100%; + max-height: 100%; + overflow-y: auto; +} + +#entry-icons { + position: absolute; + bottom: 5%; + right: 5%; + width: 50px; + display: flex; + flex-direction: column; + gap: 1rem; + + & .avatar { + border: 2px solid black; + border-radius: 50%; + width: 50px; + height: 50px; + overflow: hidden; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + + & img { + width: 100%; + height: 100%; + object-fit: cover; + } + } +} + +#word-modal { + position: relative; + + & .font-icon { + position: absolute; + top: 0; + left: 0; + width: 32px; + height: 32px; + } + + & .save-icon { + position: absolute; + top: 0; + right: 0; + width: 32px; + height: 32px; + } + + & .original { + font-size: 4rem; + margin-bottom: 1rem; + } + + & .syllable {} + + & .IPA { + font-size: 1.6rem; + line-height: 1.6rem; + & img{ + width: 50px; + margin-left: 1rem; + } + } + + & .meanings { + + & .spinner { + width: 80px; + height: 80px; + } + + & .meaning { + margin: 1rem auto; + } + + & .pos { + font-size: 1.2rem; + margin-bottom: 0.3rem; + text-align: left; + } + + & ol { + word-wrap: normal; + margin: auto; + text-align: left; + } + } +} + +img { + width: 100%; + height: 100%; + object-fit: cover; +} +.flex1{ + width: 100%; + display: flex; + gap: 1rem; + align-items: center; +} +.flex-center{ + justify-content: center; +} + +/* p { */ +/* position: absolute; */ +/* top: 50%; */ +/* left: 50%; */ +/* transform: translate(-50%, -50%); */ +/* color: white; */ +/* background-color: rgba(0, 0, 0, 0.5); */ +/* padding: 10px; */ +/* border-radius: 5px; */ +/* } */ +#modal-bg{ + height: 100vh; + width: 100vw; + background-color: rgb(0, 0, 0, 0.9); + position: fixed; + top: 0; + left: 0; + z-index: 100; +} + +#modal-fg { + position: fixed; + top: 50%; + left: 50%; + width: 80%; + z-index: 101; + transform: translate(-50%, -50%); + /* background-color: var(--background-color); */ + background-color: lightgrey; + font-size: 1.2rem; + padding: 1rem; + max-height: 80%; + overflow-y: scroll; +} + + +.text-ipa{ + font-size: 1.5rem; +} +.text-thai{ + font-size: 1.5rem; +} + + +/* // new */ +.word.cp{ + margin: 0 0.5ch; +} diff --git a/packages/prosody-ui/src/components/word.css b/packages/prosody-ui/src/components/word.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/packages/prosody-ui/src/components/word.css diff --git a/packages/prosody-ui/src/files.d.ts b/packages/prosody-ui/src/files.d.ts new file mode 100644 index 0000000..5e52f80 --- /dev/null +++ b/packages/prosody-ui/src/files.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const content: string; + export default content; +} diff --git a/packages/prosody-ui/src/fonts/FontChanger.tsx b/packages/prosody-ui/src/fonts/FontChanger.tsx new file mode 100644 index 0000000..15c932e --- /dev/null +++ b/packages/prosody-ui/src/fonts/FontChanger.tsx @@ -0,0 +1,64 @@ +import React, { useEffect, useState, type ReactNode } from "react"; +import fontIcon from "../assets/icons/font.svg"; +import { getScriptPredictor } from "glotscript"; +import ThaiFontLoader from "./Thai"; + +function FontChanger({ text }: { text: string }) { + const [script, setScript] = useState<string | null>(null); + useEffect(() => { + const predictor = getScriptPredictor(); + const res = predictor(text); + console.log("script predicted", res); + setScript(res[0]); + }, [text]); + useEffect(() => { + if (script === "Hani") setFontCount(12); + else if (script === "Thai") setFontCount(6); + else if (script === "Jpan") setFontCount(5); + // else if (script === "Latn") setFontCount(6) + }, [script]); + const [fontIdx, setFont] = useState(0); + const [fontCount, setFontCount] = useState(0); + function changeFont() { + if (fontIdx === fontCount) setFont(0); + else setFont((prev) => prev + 1); + } + return ( + <div + className={`font-changer font-${script}-${fontIdx}`} + lang={script || ""} + > + <img + className="font-icon cp" + style={{ width: 25 }} + onClick={changeFont} + src={fontIcon} + /> + {script === "Thai" ? <ThaiFontLoader text={text} /> : null} + </div> + ); +} +// function FontChanger({ +// lang, +// children, +// }: { +// lang: string; +// children: ReactNode; +// }) { +// useEffect(() => {}, []); +// const [script, setScript] = useState("Latn"); +// const [fontIdx, setFont] = useState(0); +// const fontCount = 6; +// function changeFont() { +// if (fontIdx === fontCount) setFont(0); +// else setFont((prev) => prev + 1); +// } +// return ( +// <div className="font-changer" lang={script}> +// <img className="font-icon cp" onClick={changeFont} src={fontIcon} /> +// {children} +// </div> +// ); +// } + +export default FontChanger; diff --git a/packages/prosody-ui/src/fonts/Hani.tsx b/packages/prosody-ui/src/fonts/Hani.tsx new file mode 100644 index 0000000..f9cc602 --- /dev/null +++ b/packages/prosody-ui/src/fonts/Hani.tsx @@ -0,0 +1,14 @@ +import React, { useState, type ReactNode } from "react"; +import "../assets/fonts/Hani/style.css"; + +function ChineseFontLoader({ children }: { children: ReactNode }) { + const [fontIdx, setFont] = useState(0); + const fontCount = 12; + function changeFont() { + if (fontIdx === fontCount) setFont(0); + else setFont((prev) => prev + 1); + } + return <div>{children}</div>; +} + +export default ChineseFontLoader; diff --git a/packages/prosody-ui/src/fonts/Thai.tsx b/packages/prosody-ui/src/fonts/Thai.tsx new file mode 100644 index 0000000..0048316 --- /dev/null +++ b/packages/prosody-ui/src/fonts/Thai.tsx @@ -0,0 +1,8 @@ +import React, { useState, type ReactNode } from "react"; +import "../assets/fonts/Thai/style.css"; + +function ThaiFontLoader({ text }: { text: string }) { + return <div>{text}</div>; +} + +export default ThaiFontLoader; diff --git a/packages/prosody-ui/src/fonts/useLangFont.tsx b/packages/prosody-ui/src/fonts/useLangFont.tsx new file mode 100644 index 0000000..36fa603 --- /dev/null +++ b/packages/prosody-ui/src/fonts/useLangFont.tsx @@ -0,0 +1,44 @@ +import React, { useEffect, useState, type ReactNode } from "react"; +import fontIcon from "../assets/icons/font.svg"; +import { getScriptPredictor } from "glotscript"; + +function useLangFont({ text }: { text: string }) { + useEffect(() => { + const predictor = getScriptPredictor(); + const res = predictor(text); + console.log("script predicted", res); + setScript(res[0]); + }, [text]); + const [script, setScript] = useState<string | null>(null); + const [fontIdx, setFont] = useState(0); + const fontCount = 6; + function changeFont() { + if (fontIdx === fontCount) setFont(0); + else setFont((prev) => prev + 1); + } + // if (script === "Hani") return {} +} +// function FontChanger({ +// lang, +// children, +// }: { +// lang: string; +// children: ReactNode; +// }) { +// useEffect(() => {}, []); +// const [script, setScript] = useState("Latn"); +// const [fontIdx, setFont] = useState(0); +// const fontCount = 6; +// function changeFont() { +// if (fontIdx === fontCount) setFont(0); +// else setFont((prev) => prev + 1); +// } +// return ( +// <div className="font-changer" lang={script}> +// <img className="font-icon cp" onClick={changeFont} src={fontIcon} /> +// {children} +// </div> +// ); +// } + +export default useLangFont; diff --git a/packages/prosody-ui/src/hooks/useLang.tsx b/packages/prosody-ui/src/hooks/useLang.tsx new file mode 100644 index 0000000..687c81d --- /dev/null +++ b/packages/prosody-ui/src/hooks/useLang.tsx @@ -0,0 +1,184 @@ +import { + useState, + useEffect, + createContext, + useContext, + useCallback, + type ElementType, +} from "react"; +type ScriptClass = + | "text-ipa" + | "text-rtl" + | "text-cjk" + | "text-thai" + | "text-cyrillic" + | "text-latin"; +interface ScriptContextType { + getClass: (text: string) => ScriptClass; +} +const ScriptContext = createContext({ + getClass: (text: string) => "text-latin" as ScriptClass, +}); + +const getScriptClass = (text: string): ScriptClass => { + // You can combine these with includes() if text has multiple scripts + if (/[\u0591-\u07FF\u200F\u202B]/.test(text)) return "text-rtl"; + + if (/[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff]/.test(text)) return "text-cjk"; + + if (/[\u0E00-\u0E7F]/.test(text)) return "text-thai"; + + if (/[\u0400-\u04FF]/.test(text)) return "text-cyrillic"; + + if (/[\u0250-\u02AF\u1D00-\u1D7F\u1D80-\u1DBF\u1DC0-\u1DFF]/.test(text)) + return "text-ipa"; + + return "text-latin"; // default +}; + +export const ScripProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const getClass = useCallback((text: string) => { + return getScriptClass(text); + }, []); + + return ( + <ScriptContext.Provider value={{ getClass }}> + {children} + </ScriptContext.Provider> + ); +}; + +export const useScript = () => useContext(ScriptContext); + +type TextElementProps = { + children?: React.ReactNode; + className?: string; +}; +const createTextElement = (Component: ElementType) => { + return function TextElement({ + children, + className, + ...rest + }: TextElementProps & React.ComponentPropsWithoutRef<ElementType>) { + const writingSystemClass = + typeof children === "string" ? getScriptClass(children) : "text-latin"; + + return ( + <Component + className={`${writingSystemClass} ${className || ""}`} + {...rest} + > + {children} + </Component> + ); + }; +}; + +// Create all the text elements you need +export const Span = createTextElement("span"); +export const P = createTextElement("p"); +export const H1 = createTextElement("h1"); +export const H2 = createTextElement("h2"); +export const H3 = createTextElement("h3"); +export const H4 = createTextElement("h4"); +export const H5 = createTextElement("h5"); +export const H6 = createTextElement("h6"); +export const Label = createTextElement("label"); +export const Small = createTextElement("small"); + +interface Voice { + default: boolean; + lang: string; + localService: boolean; + name: string; + voiceURI: string; +} + +export const useSpeechSynthesis = () => { + const [voices, setVoices] = useState<Voice[]>([]); + const [speaking, setSpeaking] = useState(false); + console.log({ voices }, "voices hook"); + + useEffect(() => { + // Function to get voices + const updateVoices = () => { + // Some browsers need a small delay for voices to be available + setTimeout(() => { + const availableVoices = window.speechSynthesis.getVoices(); + if (availableVoices.length > 0) { + setVoices(availableVoices); + } + }, 100); + }; + + // Get initial voices + updateVoices(); + + window.speechSynthesis.addEventListener("voiceschanged", updateVoices); + + // Cleanup + return () => { + window.speechSynthesis.removeEventListener("voiceschanged", updateVoices); + }; + }, []); + + const speak = (text: string, voiceName?: string) => { + const utterance = new SpeechSynthesisUtterance(text); + + if (voiceName) { + const voice = voices.find((v) => v.name === voiceName); + if (voice) utterance.voice = voice; + } + + utterance.onstart = () => setSpeaking(true); + utterance.onend = () => setSpeaking(false); + utterance.onerror = () => setSpeaking(false); + + window.speechSynthesis.speak(utterance); + }; + + const stop = () => { + window.speechSynthesis.cancel(); + setSpeaking(false); + }; + + return { + voices, + speaking, + speak, + stop, + }; +}; + +// Example usage in a component: +const SpeechComponent = () => { + const { voices, speaking, speak, stop } = useSpeechSynthesis(); + const [selectedVoice, setSelectedVoice] = useState<string>(""); + + return ( + <div> + <select + value={selectedVoice} + onChange={(e) => setSelectedVoice(e.target.value)} + > + <option value="">Default Voice</option> + {voices.map((voice) => ( + <option key={voice.name} value={voice.name}> + {voice.name} ({voice.lang}) + </option> + ))} + </select> + + <button + onClick={() => speak("Hello, world!", selectedVoice)} + disabled={speaking} + > + {speaking ? "Speaking..." : "Speak"} + </button> + + {speaking && <button onClick={stop}>Stop</button>} + </div> + ); +}; diff --git a/packages/prosody-ui/src/hooks/useModal.tsx b/packages/prosody-ui/src/hooks/useModal.tsx new file mode 100644 index 0000000..7164bcb --- /dev/null +++ b/packages/prosody-ui/src/hooks/useModal.tsx @@ -0,0 +1,53 @@ +import { franc } from "franc-all"; +import React, { + ReactElement, + ReactNode, + useCallback, + useEffect, + useRef, + useState, +} from "react"; + +function useModal() { + const [achild, setChild] = useState<ReactNode>(null); + return <Modal close={() => setChild(null)}>{achild}</Modal>; +} +export default useModal; + +function Modal({ + children, + height = "fit-content", + width = "80%", + close, +}: { + children: ReactNode; + close: () => void; + width?: any; + height?: any; +}) { + function onKey(event: any) { + if (event.key === "Escape") close(); + + useEffect(() => { + document.addEventListener("keyup", onKey); + return () => { + document.removeEventListener("keyup", onKey); + }; + }, [children]); + } + + function clickAway(e: React.MouseEvent) { + e.stopPropagation(); + if (!modalRef.current || !modalRef.current.contains(e.target as any)) + close(); + } + const modalRef = useRef<HTMLDivElement>(null); + const style = { width, height }; + return ( + <div id="modal-bg" onClick={clickAway}> + <div id="modal-fg" style={style} ref={modalRef}> + {children} + </div> + </div> + ); +} diff --git a/packages/prosody-ui/src/hooks/useTTS.tsx b/packages/prosody-ui/src/hooks/useTTS.tsx new file mode 100644 index 0000000..671d078 --- /dev/null +++ b/packages/prosody-ui/src/hooks/useTTS.tsx @@ -0,0 +1,3 @@ +function useTTS(text: string) {} + +export default useTTS; diff --git a/packages/prosody-ui/src/latin/LatinText.tsx b/packages/prosody-ui/src/latin/LatinText.tsx new file mode 100644 index 0000000..e5b13ff --- /dev/null +++ b/packages/prosody-ui/src/latin/LatinText.tsx @@ -0,0 +1,77 @@ +import React, { useCallback, useEffect, useState } from "react"; +import type { AnalyzeRes } from "../logic/types"; +import { ColoredText } from "../components/Sentence"; +import Word from "../components/Word"; +import { iso6393To1 } from "../logic/iso6393to1"; + +function segmentate( + text: string, + lang: string, + granularity: "sentence" | "word" | "grapheme", +) { + // TODO proper error handling here + console.log("segmenting", lang); + const la = iso6393To1[lang]; + const lng = la || lang; + const segmenter = new Intl.Segmenter(lng, { granularity }); + const segments = Array.from(segmenter.segment(text)); + console.log("seg", segments[0]); + return segments.reduce((acc: string[], s) => { + const trimmed = s.segment.trim(); + if (trimmed) return [...acc, trimmed]; + else return acc; + }, []); +} + +export default function LatinText({ + text, + lang, + openWord, +}: { + text: string; + lang: string; + openWord?: (word: string) => void; +}) { + useEffect(() => { + const sentences = segmentate(text, lang, "sentence"); + if (sentences) setSentences(sentences); + }, [text]); + const [sentences, setSentences] = useState<string[]>([]); + console.log({ sentences }); + return ( + <> + {sentences.map((s, i) => ( + <Sentence key={s + i} text={s} lang={lang} openWord={openWord} /> + ))} + </> + ); +} + +function Sentence({ + text, + lang, + openWord, +}: { + text: string; + lang: string; + + openWord?: (word: string) => void; +}) { + useEffect(() => { + const w = segmentate(text, lang, "word"); + if (w) setWords(w); + console.log({ words }); + }, [text]); + const [words, setWords] = useState<string[]>([]); + console.log({ words }); + + // const [data, setData] = useState<Record<string, AnalyzeRes>>({}); + const [word, setWord] = useState<AnalyzeRes>(); + + return ( + <> + <ColoredText frags={words} fn={openWord} />; + {word && <Word data={word} lang={lang} />} + </> + ); +} diff --git a/packages/prosody-ui/src/logic/iso6393to1.ts b/packages/prosody-ui/src/logic/iso6393to1.ts new file mode 100644 index 0000000..4c4deed --- /dev/null +++ b/packages/prosody-ui/src/logic/iso6393to1.ts @@ -0,0 +1,186 @@ +export const iso6393To1: Record<string, string> = { + aar: "aa", + abk: "ab", + afr: "af", + aka: "ak", + amh: "am", + ara: "ar", + arg: "an", + asm: "as", + ava: "av", + ave: "ae", + aym: "ay", + aze: "az", + bak: "ba", + bam: "bm", + bel: "be", + ben: "bn", + bis: "bi", + bod: "bo", + bos: "bs", + bre: "br", + bul: "bg", + cat: "ca", + ces: "cs", + cha: "ch", + che: "ce", + chu: "cu", + chv: "cv", + cor: "kw", + cos: "co", + cre: "cr", + cym: "cy", + dan: "da", + deu: "de", + div: "dv", + dzo: "dz", + ell: "el", + eng: "en", + epo: "eo", + est: "et", + eus: "eu", + ewe: "ee", + fao: "fo", + fas: "fa", + fij: "fj", + fin: "fi", + fra: "fr", + fry: "fy", + ful: "ff", + gla: "gd", + gle: "ga", + glg: "gl", + glv: "gv", + grn: "gn", + guj: "gu", + hat: "ht", + hau: "ha", + hbs: "sh", + heb: "he", + her: "hz", + hin: "hi", + hmo: "ho", + hrv: "hr", + hun: "hu", + hye: "hy", + ibo: "ig", + ido: "io", + iii: "ii", + iku: "iu", + ile: "ie", + ina: "ia", + ind: "id", + ipk: "ik", + isl: "is", + ita: "it", + jav: "jv", + jpn: "ja", + kal: "kl", + kan: "kn", + kas: "ks", + kat: "ka", + kau: "kr", + kaz: "kk", + khm: "km", + kik: "ki", + kin: "rw", + kir: "ky", + kom: "kv", + kon: "kg", + kor: "ko", + kua: "kj", + kur: "ku", + lao: "lo", + lat: "la", + lav: "lv", + lim: "li", + lin: "ln", + lit: "lt", + ltz: "lb", + lub: "lu", + lug: "lg", + mah: "mh", + mal: "ml", + mar: "mr", + mkd: "mk", + mlg: "mg", + mlt: "mt", + mon: "mn", + mri: "mi", + msa: "ms", + mya: "my", + nau: "na", + nav: "nv", + nbl: "nr", + nde: "nd", + ndo: "ng", + nep: "ne", + nld: "nl", + nno: "nn", + nob: "nb", + nor: "no", + nya: "ny", + oci: "oc", + oji: "oj", + ori: "or", + orm: "om", + oss: "os", + pan: "pa", + pli: "pi", + pol: "pl", + por: "pt", + pus: "ps", + que: "qu", + roh: "rm", + ron: "ro", + run: "rn", + rus: "ru", + sag: "sg", + san: "sa", + sin: "si", + slk: "sk", + slv: "sl", + sme: "se", + smo: "sm", + sna: "sn", + snd: "sd", + som: "so", + sot: "st", + spa: "es", + sqi: "sq", + srd: "sc", + srp: "sr", + ssw: "ss", + sun: "su", + swa: "sw", + swe: "sv", + tah: "ty", + tam: "ta", + tat: "tt", + tel: "te", + tgk: "tg", + tgl: "tl", + tha: "th", + tir: "ti", + ton: "to", + tsn: "tn", + tso: "ts", + tuk: "tk", + tur: "tr", + twi: "tw", + uig: "ug", + ukr: "uk", + urd: "ur", + uzb: "uz", + ven: "ve", + vie: "vi", + vol: "vo", + wln: "wa", + wol: "wo", + xho: "xh", + yid: "yi", + yor: "yo", + zha: "za", + zho: "zh", + zul: "zu", +}; diff --git a/packages/prosody-ui/src/logic/stanza.ts b/packages/prosody-ui/src/logic/stanza.ts new file mode 100644 index 0000000..9e59450 --- /dev/null +++ b/packages/prosody-ui/src/logic/stanza.ts @@ -0,0 +1,86 @@ +import type { AsyncRes, Result } from "sortug"; + +const ENDPOINT = "http://localhost:8102"; +export async function segmenter(text: string, lang: string) { + try { + const body = JSON.stringify({ lang, string: text }); + const opts = { + headers: { "Content-type": "application/json" }, + method: "POST", + body, + }; + const res = await fetch(ENDPOINT + "/segment", opts); + console.log("stanza", res); + const j = await res.json(); + return { ok: j }; + } catch (e) { + return { error: `${e}` }; + } +} +export async function idLang(text: string) { + try { + const body = JSON.stringify({ string: text }); + const opts = { + headers: { "Content-type": "application/json" }, + method: "POST", + body, + }; + const res = await fetch(ENDPOINT + "/detect-lang", opts); + const j = await res.json(); + return { ok: j }; + } catch (e) { + return { error: `${e}` }; + } +} + +export type Sentence = { + text: string; + sentiment: number; + constituency: string; + dependencies: Dependency[]; + entities: Entity[]; + tokens: Token[]; + words: Word[]; +}; +export type Dependency = Array<[Word, string, Word]>; +export type Word = { + id: number; + text: string; + lemma: string; + upos: string; + xpos: string; + feats: string; + head: number; + deprel: string; + start_char: number; + end_char: number; +}; +export type Token = { + id: [number, number]; + text: string; + misc: string; + words: Word[]; + start_char: number; + end_char: number; + ner: string; +}; +export type Entity = { + text: string; + misc: string; + start_char: number; + end_char: number; + type: string; +}; +// "amod", +// { +// "id": 1, +// "text": "Stony", +// "lemma": "Stony", +// "upos": "ADJ", +// "xpos": "NNP", +// "feats": "Degree=Pos", +// "head": 3, +// "deprel": "amod", +// "start_char": 0, +// "end_char": 5 +// } diff --git a/packages/prosody-ui/src/logic/types.ts b/packages/prosody-ui/src/logic/types.ts new file mode 100644 index 0000000..ac308cf --- /dev/null +++ b/packages/prosody-ui/src/logic/types.ts @@ -0,0 +1,48 @@ +export type Cookie = { + domain: string; + path: string; + hostOnly: boolean; + httpOnly: boolean; + secure: boolean; + session: boolean; + sameSite: SameSite; + storeId: null; + name: string; + value: string; +}; +export type CookiesMap = Record<string, CookieMap>; +export type CookieMap = Record<string, Cookie>; +export type KeyMap = Record<string, string>; +type SameSite = null | "no_restriction"; // TODO + +export type APIRes = { API: { app: string; api_key: string } }; +export type CookieRes = { Cookie: { app: string; cookie: CookieMap } }; +export type CookiesRes = { cookies: CookiesMap; apiKeys: KeyMap }; + +// words +export type Meaning = { + pos: string; // part of speech; + meaning: string[]; + etymology: string; + references?: any; +}; + +export type Prompts = { + translate: string; +}; +export type AnalyzeRes = { + word: string; + syllables: string[]; + ipa: string; + pos: POS; +}; +type PosTuple = [string, POS]; +type POS = string; + +export type WordData = { + spelling: string; + lang: string; + ipa: string; + meanings: Meaning[]; + references?: any; +}; diff --git a/packages/prosody-ui/src/logic/utils.ts b/packages/prosody-ui/src/logic/utils.ts new file mode 100644 index 0000000..737a6ec --- /dev/null +++ b/packages/prosody-ui/src/logic/utils.ts @@ -0,0 +1,66 @@ +import type { Result } from "sortug"; + +export function detectScript(text: string): Result<string> { + const scripts = { + Latin: /[\u0000-\u007F\u00A0-\u00FF\u0100-\u017F\u0180-\u024F]/g, + Cyrillic: /[\u0400-\u04FF\u0500-\u052F\u2DE0-\u2DFF\uA640-\uA69F]/g, + Greek: /[\u0370-\u03FF\u1F00-\u1FFF]/g, + Hebrew: /[\u0590-\u05FF]/g, + Arabic: /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]/g, + Devanagari: /[\u0900-\u097F]/g, // Hindi, Sanskrit, etc. + Bengali: /[\u0980-\u09FF]/g, + Thai: /[\u0E00-\u0E7F]/g, + Chinese: + /[\u4E00-\u9FFF\u3400-\u4DBF\u20000-\u2A6DF\u2A700-\u2B73F\u2B740-\u2B81F]/g, + Japanese: /[\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF]/g, // Includes Hiragana, Katakana + Korean: /[\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F]/g, // Includes Hangul + Armenian: /[\u0530-\u058F]/g, + Georgian: /[\u10A0-\u10FF]/g, + Khmer: /[\u1780-\u17FF]/g, // Cambodian + Myanmar: /[\u1000-\u109F]/g, // Burmese + Tamil: /[\u0B80-\u0BFF]/g, + Telugu: /[\u0C00-\u0C7F]/g, + Amharic: /[\u1200-\u137F]/g, // Ethiopian + }; + const counts: Record<string, number> = {}; + + for (const [scriptName, regex] of Object.entries(scripts)) { + // Create an array of matches and count its length + const matches = text.match(regex) || []; + counts[scriptName] = matches.length; + } + + let maxCount = 0; + let dominantScript = "Unknown"; + + for (const [scriptName, count] of Object.entries(counts)) { + if (count > maxCount) { + maxCount = count; + dominantScript = scriptName; + } + } + if (dominantScript === "Unknown") return { error: "Not detected" }; + else return { ok: dominantScript }; +} + +export function langFromScript(script: string): Result<string> { + if (script === "Thai") return { ok: "th" }; + if (script === "Japanese") return { ok: "ja" }; + if (script === "Chinese") return { ok: "zh" }; + if (script === "Korean") return { ok: "ko" }; + else return { error: "too generic" }; +} +export function scriptFromLang(lang: string, text: string): string { + if (lang == "th") return "Thai"; + if (lang == "tha") return "Thai"; + if (lang == "en") return "Engl"; + if (lang == "es") return "Span"; + if (lang == "cn") return "Hant"; + if (lang == "zh") return "Hant"; + if (lang == "ja") return "Japn"; + else { + const res = detectScript(text); + if ("ok" in res) return res.ok; + else return ""; + } +} diff --git a/packages/prosody-ui/src/logic/wiki.ts b/packages/prosody-ui/src/logic/wiki.ts new file mode 100644 index 0000000..1325c0f --- /dev/null +++ b/packages/prosody-ui/src/logic/wiki.ts @@ -0,0 +1,138 @@ +import type { AsyncRes, Result } from "sortug"; +import type { Meaning } from "./types"; + +export function buildWiktionaryURL(word: string) { + const params = new URLSearchParams(); + params.append("action", "parse"); + params.append("page", word); + params.append("format", "json"); + params.append("prop", "templates|text"); + params.append("formatversion", "2"); + + const p = params.toString(); + const url = `https://en.wiktionary.org/w/api.php?${p}`; + return url; +} + +// export async function fetchWordInWiki(url: string) { +// const opts = { method: "GET", body: null, headers: {} }; +// try { +// const res = await proxyCall(url, opts); +// console.log(res.headers.get("content-type")); +// const j = await res.json(); +// return { ok: j }; +// } catch (e) { +// return { error: `${e}` }; +// } +// } + +export type WikiRes = { + url: string; + meanings: Meaning[]; + ipa: string[]; +}; +const poses = [ + "noun", + "verb", + "adjective", + "adverb", + "conjunction", + "determiner", + "preposition", + "definitions", +]; + +export function parseWiktionary(html: string, url: string): Result<WikiRes> { + try { + const dp = new DOMParser(); + const doc = dp.parseFromString(html, "text/html"); + const ipas = doc.querySelectorAll(".IPA"); + const headings = doc.querySelectorAll(".mw-heading"); + const ms: Meaning[] = []; + const doneIdx: number[] = []; + let currentRound: Meaning = { pos: "", meaning: [], etymology: "" }; + for (let [idx, h] of Array.from(headings).entries()) { + const headingType: string = (h.firstChild as any).innerText; + if (!headingType) continue; + const ht = headingType.toLowerCase(); + if (ht.includes("etymology")) currentRound.etymology = fillEtym(h); + else if (poses.includes(ht)) { + currentRound.pos = ht; + currentRound = fillMeaning(h, currentRound); + } + if (currentRound.pos) { + ms.push({ ...currentRound }); + currentRound = { pos: "", meaning: [], etymology: "" }; + } + if (ht === "references") break; // make sure it's one single language lol + } + const ipaStrings = Array.from(ipas).map((el: any) => el.innerText); + return { ok: { meanings: ms, ipa: ipaStrings, url } }; + } catch (e) { + return { error: `${e}` }; + } +} + +function fillMeaning(el: Element, m: Meaning) { + const sibling = el.nextElementSibling; + if (!sibling) return m; + if (sibling?.tagName.toLowerCase() === "ol") { + for (let li of Array.from(sibling.children)) { + if (li.tagName.toLowerCase() !== "li") continue; + if (li.className.includes("empty-elt")) continue; + m.meaning.push(li.innerHTML); + } + } + if (m.meaning.length === 0) return fillMeaning(sibling, m); + else return m; +} + +function fillEtym(el: Element, acc: string = ""): string { + const sibling = el.nextElementSibling; + if (!sibling) return acc; + if (sibling?.tagName.toLowerCase() === "p") acc += `\n${sibling.innerHTML}`; + if (!acc) return fillEtym(sibling, acc); + else return acc; +} + +export function parseWiktionaryo(html: string, url: string): Result<WikiRes> { + try { + const dp = new DOMParser(); + const doc = dp.parseFromString(html, "text/html"); + const ipas = doc.querySelectorAll(".IPA"); + const ols = doc.querySelectorAll("ol"); + const ms = Array.from(ols).map((el) => { + let pos = ""; + let etymology = ""; + let meaning: string[] = []; + let posr = findPos(el); + if ("ok" in posr) pos = posr.ok; + for (let li of Array.from(el.children)) { + if (li.tagName !== "LI") continue; + meaning.push((li as any).innerText); + } + return { pos, meaning, etymology }; + }); + console.log(ipas, "ipa strings"); + console.log(ols, "lists in wiki"); + const ipaStrings = Array.from(ipas).map((el: any) => el.innerText); + return { ok: { meanings: ms, ipa: ipaStrings, url } }; + } catch (e) { + return { error: `${e}` }; + } +} + +function findPos(el: Element): Result<string> { + let pichai = el.previousElementSibling; + console.log(pichai, "previous"); + if (!pichai) return { error: "no pichai" }; + if (pichai.classList.contains("mw-heading")) { + const h4 = pichai.querySelector("h4"); + const h3 = pichai.querySelector("h3"); + if (!h4 && !h3) return findPos(pichai); + else { + const id = (h4?.innerText || h3?.innerText)!; + return { ok: id }; + } + } else return findPos(pichai); +} diff --git a/packages/prosody-ui/src/sortug.css b/packages/prosody-ui/src/sortug.css new file mode 100644 index 0000000..c6280c0 --- /dev/null +++ b/packages/prosody-ui/src/sortug.css @@ -0,0 +1,248 @@ + +/* SORTUG CSS */ +/* variables */ +:root { + --bai: rgba(255, 255, 255, 1); + --baizi: rgba(230, 230, 230); + --hui: rgba(130, 130, 130, 1); + --hei: rgba(0, 0, 0, 1); + --hong: rgb(141, 15, 15, 1); + --huang: rgb(230, 180, 60, 1); + --lan: rgb(30, 60, 80, 1); +} + +[data-theme="dark"] { + --bg: hei; + --fg: baizi; +} + +[data-theme="light"] { + --bg: white; + --fg: black; +} + +* { + box-sizing: border-box; +} + +html, +body, +#root { + height: 100%; + min-height: 100%; + overscroll-behavior: none; + color: var(--fg); + -webkit-font-smoothing: antialiased; + margin: 0; +} + +/* tailwindy classes */ +.card { + padding: 1rem; + max-width: max-content; +} + +button, +.button { + max-width: max-content; + padding: 0.5rem; + border: 1px solid var(--fg); +} + +/* borders */ +.nb { + border: none; +} + +/* widths */ +.hw { + width: 50%; +} + +.qw { + width: 25%; +} + +.tqw { + width: 75%; +} + +/* flex */ +.row { + display: flex; + align-items: center; +} + +.sy { + overflow-y: scroll; +} + +.fsy { + overflow-y: scroll; + height: 100%; +} + +.fxc { + display: flex; + justify-content: center; + align-items: baseline; +} + +/* flex spread */ +.fs { + display: flex; + justify-content: space-between; +} + +.fsc { + display: flex; + justify-content: space-between; + align-items: center; +} + +.g1 { + gap: 0.5rem; +} + +.g2 { + gap: 1rem; +} + +.address { + font-family: "Courier New", Courier, monospace; +} + +.spread { + justify-content: space-between; +} + +.even { + justify-content: space-evenly; +} + +.flexc { + justify-content: center; +} + +.cp { + cursor: pointer; +} + +/* centering */ +.gc { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.agc { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.ac { + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.xc { + position: fixed; + left: 50%; + transform: translateX(-50%); + z-index: 20; +} + +.tc { + text-align: center; +} + +.bc { + display: block; + margin-left: auto; + margin-right: auto; +} + +.blocks { + & * { + display: block; + } +} + +.bold { + font-weight: 700; +} + +.weak { + opacity: 0.7; +} + +.all-c { + & * { + margin-left: auto; + margin-right: auto; + } +} + +.mb-1 { + margin-bottom: 1rem; +} + +.error { + color: red; + text-align: center; +} + +.tabs { + display: flex; + justify-content: space-evenly; + align-items: center; + + & .tab { + cursor: pointer; + opacity: 0.5; + } + + & .tab.active { + opacity: 1; + } +} + +.disabled { + opacity: 0.5; +} + +.smol { + font-size: 0.9rem; +} + +/* The Modal (background) */ +#modal-bg { + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0, 0, 0, 0.4); + z-index: 998; +} + +/* Modal Content */ +#modal-fg { + background-color: var(--bg); + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 20px; + z-index: 999; + max-height: 90vh; + min-height: 20vh; + max-width: 90vw; + overflow: auto; +} diff --git a/packages/prosody-ui/src/styles/styles.css b/packages/prosody-ui/src/styles/styles.css new file mode 100644 index 0000000..69351f1 --- /dev/null +++ b/packages/prosody-ui/src/styles/styles.css @@ -0,0 +1,281 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +#root>.spinner { + width: 100px; + height: 100px; +} + +#entry>.spinner { + width: 80px; + height: 80px; +} + + + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} + +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} + +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +#cookies { + & .active { + background-color: var(--huang); + } + + & input { + margin-left: 1rem; + width: 100%; + } + + & textarea { + width: 100%; + height: 500px; + resize: none; + outline: none; + } +} + +#entry { + width: 100%; + height: 100%; + position: relative; + padding: 1rem; + /* prov */ + border: 2px solid black; + + & div[lang="th"] { + + & .tw-text, + & .tw-hashtag { + font-size: 3rem; + } + } + + & .text-wrapper { + display: block; + margin: 0.5rem 0; + /* overflow: hidden; */ + } + + & .word { + display: inline-block; + transition: transform 0.3s ease; + } + + & .word:hover { + transform: scale(1.4); + background-color: white; + } + + & #tw-media { + max-width: 100%; + + & img, + & video { + max-width: 100%; + } + } +} + +#inner { + height: 100%; + max-height: 100%; + overflow-y: auto; +} + +#entry-icons { + position: absolute; + bottom: 5%; + right: 5%; + width: 50px; + display: flex; + flex-direction: column; + gap: 1rem; + + & .avatar { + border: 2px solid black; + border-radius: 50%; + width: 50px; + height: 50px; + overflow: hidden; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + + & img { + width: 100%; + height: 100%; + object-fit: cover; + } + } +} + +#word-modal { + position: relative; + + & .font-icon { + position: absolute; + top: 0; + left: 0; + width: 32px; + height: 32px; + } + + & .save-icon { + position: absolute; + top: 0; + right: 0; + width: 32px; + height: 32px; + } + + & .original { + font-size: 4rem; + margin-bottom: 1rem; + } + + & .syllable {} + + & .IPA { + font-size: 1.6rem; + line-height: 1.6rem; + + & img { + width: 50px; + margin-left: 1rem; + } + } + + & .meanings { + + & .spinner { + width: 80px; + height: 80px; + } + + & .meaning { + margin: 1rem auto; + } + + & .pos { + font-size: 1.2rem; + margin-bottom: 0.3rem; + text-align: left; + } + + & ol { + word-wrap: normal; + margin: auto; + text-align: left; + } + } +} + +img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.flex1 { + width: 100%; + display: flex; + gap: 1rem; + align-items: center; +} + +.flex-center { + justify-content: center; +} + +/* p { */ +/* position: absolute; */ +/* top: 50%; */ +/* left: 50%; */ +/* transform: translate(-50%, -50%); */ +/* color: white; */ +/* background-color: rgba(0, 0, 0, 0.5); */ +/* padding: 10px; */ +/* border-radius: 5px; */ +/* } */ +#modal-bg { + height: 100vh; + width: 100vw; + background-color: rgb(0, 0, 0, 0.9); + position: fixed; + top: 0; + left: 0; + z-index: 100; +} + +#modal-fg { + position: fixed; + top: 50%; + left: 50%; + width: 80%; + z-index: 101; + transform: translate(-50%, -50%); + /* background-color: var(--background-color); */ + background-color: lightgrey; + font-size: 1.2rem; + padding: 1rem; + max-height: 80%; + overflow-y: scroll; +} + + +.text-ipa { + font-size: 1.5rem; +} + +.text-thai { + font-size: 1.5rem; +} + + +/* // new */ +.word.cp { + margin: 0 0.5ch; +} + +.lang-text-container { + display: flex; + flex-wrap: wrap; +}
\ No newline at end of file diff --git a/packages/prosody-ui/src/thai/ThaiText.tsx b/packages/prosody-ui/src/thai/ThaiText.tsx new file mode 100644 index 0000000..fc1e1e6 --- /dev/null +++ b/packages/prosody-ui/src/thai/ThaiText.tsx @@ -0,0 +1,49 @@ +import React, { useCallback, useEffect, useState } from "react"; +import "../assets/fonts/Thai/style.css"; +import { segmentateThai } from "./logic/thainlp"; +import type { AnalyzeRes } from "../logic/types"; +import { ColoredText } from "../components/Sentence"; +import Word from "../components/Word"; + +export default function ThaiText({ + text, + openWord, +}: { + text: string; + openWord: (s: string) => void; +}) { + useEffect(() => { + pythonseg(); + }, [text]); + + const [data, setData] = useState<Record<string, AnalyzeRes>>({}); + const [modal, setModal] = useState<any>(); + const pythonseg = useCallback(async () => { + const s2 = await segmentateThai(text.trim()); + if ("ok" in s2) { + const ob = s2.ok.reduce((acc, item) => { + acc[item.word] = item; + return acc; + }, {} as any); + setData(ob); + console.log(s2, "s2"); + } else console.error(s2.error); + }, [text]); + + // function openWord(e: React.MouseEvent<any>) { + // const s = e.currentTarget.innerText; + // const d = data[s]; + // setModal(d); + // // setModal(<WordModal data={d} lang={lang} />); + // } + return ( + <div className="thaitext"> + <ColoredText lang="tha" frags={Object.keys(data)} fn={openWord} /> + {modal && <Word data={modal} lang={"tha"} />} + </div> + ); +} + +function ThaiWord() { + return <div />; +} diff --git a/packages/prosody-ui/src/thai/logic/thainlp.ts b/packages/prosody-ui/src/thai/logic/thainlp.ts new file mode 100644 index 0000000..031bf4c --- /dev/null +++ b/packages/prosody-ui/src/thai/logic/thainlp.ts @@ -0,0 +1,90 @@ +import type { AsyncRes } from "sortug"; +import type { AnalyzeRes } from "../../logic/types"; + +const ENDPOINT = "http://192.168.1.110:8001"; +async function call(path: string, body: any) { + try { + const opts = { + method: "POST", + headers: { "Content-type": "application/json" }, + body: JSON.stringify(body), + }; + const r1 = await fetch(ENDPOINT + path, opts); + // const r2 = await fetch(`http://192.168.1.110:8000/analyze`, opts); + const jj = await r1.json(); + return { ok: jj }; + } catch (e) { + return { error: `${e}` }; + } +} +export async function analyzeTHWord(word: string): AsyncRes<AnalyzeRes> { + return await call("/analyze", { word }); +} +export async function segmentateThai(sentence: string): AsyncRes<AnalyzeRes[]> { + return await call("/segmentate", { word: sentence }); +} + +export const POSMAP: Record<string, string> = { + ADJ: "Adjective", + ADP: "Adposition", + ADV: "Adverb", + AUX: "Auxiliary", + CCONJ: "Coordinating conjunction", + DET: "Determiner", + INTJ: "Interjection", + NOUN: "Noun", + NUM: "Numeral", + PART: "Particle", + PRON: "Pronoun", + PROPN: "Proper noun", + PUNCT: "Punctuation", + SCONJ: "Subordinating conjunction", + VERB: "Verb", + NPRP: "Proper noun", + NCNM: "Cardinal number", + NONM: "Ordinal number", + NLBL: "Label noun", + NCMN: "Common noun", + NTTL: "Title noun", + PPRS: "Personal pronoun", + PDMN: "Demonstrative pronoun", + PNTR: "Interrogative pronoun", + PREL: "Relative pronoun", + VACT: "Active verb", + VSTA: "Stative verb", + VATT: "Attributive verb", + XVBM: "Pre-verb auxiliary, before negator “ไม่”", + XVAM: "Pre-verb auxiliary, after negator “ไม่”", + XVMM: "Pre-verb, before or after negator “ไม่”", + XVBB: "Pre-verb auxiliary, in imperative mood", + XVAE: "Post-verb auxiliary", + DDAN: "classifier in between", + DDAC: "in between", + DDBQ: "classifier or preceding quantitative expression", + DDAQ: "following quantitative expression", + DIAC: "classifier in between", + DIBQ: "classifier or preceding quantitative expression", + DIAQ: "following quantitative expression", + DCNM: "Determiner, cardinal number expression", + DONM: "Determiner, ordinal number expression", + ADVN: "Adverb with normal form", + ADVI: "Adverb with iterative form", + ADVP: "Adverb with prefixed form", + ADVS: "Sentential adverb", + CNIT: "Unit classifier", + CLTV: "Collective classifier", + CMTR: "Measurement classifier", + CFQC: "Frequency classifier", + CVBL: "Verbal classifier", + JCRG: "Coordinating conjunction", + JCMP: "Comparative conjunction", + JSBR: "Subordinating conjunction", + RPRE: "Preposition", + INT: "Interjection", + FIXN: "Nominal prefix", + FIXV: "Adverbial prefix", + EAFF: "Ending for affirmative sentence", + EITT: "Ending for interrogative sentence", + NEG: "Negator", + PUNC: "Punctuation", +}; diff --git a/packages/prosody-ui/src/zoom/FullText.tsx b/packages/prosody-ui/src/zoom/FullText.tsx new file mode 100644 index 0000000..ec85f09 --- /dev/null +++ b/packages/prosody-ui/src/zoom/FullText.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { motion, AnimatePresence } from "motion/react"; +import Paragraph from "./Paragraph"; +import { useZoom } from "./hooks/useZoom"; +import { containerVariants, buttonVariants } from "./animations"; +import { NLP } from "sortug-ai"; + +interface TextFocusMorphProps { + text: string; + doc: NLP.Spacy.SpacyRes; +} + +const FullText: React.FC<TextFocusMorphProps> = ({ text, doc }) => { + const { viewState, navigateBack, handleElementClick } = useZoom(); + const { level } = viewState; + + // Split text into paragraphs + const paragraphs = text + .split("\n\n") + .map((p) => p.trim()) + .filter(Boolean); + + return ( + <div className="text-focus-morph"> + {level !== "text" && ( + <AnimatePresence> + <motion.button + className="back-button" + onClick={navigateBack} + variants={buttonVariants} + initial="initial" + animate="animate" + exit="exit" + > + ← Back + </motion.button> + </AnimatePresence> + )} + + <motion.div + className="content-container" + variants={containerVariants} + initial="text" + animate={level} + > + {paragraphs.map((paragraph, idx) => ( + <Paragraph + doc={doc} + key={paragraph + idx} + rawText={paragraph} + context={{ idx, parentText: text, segmented: paragraphs }} + idx={idx} + /> + ))} + </motion.div> + </div> + ); +}; + +export default FullText; diff --git a/packages/prosody-ui/src/zoom/Paragraph.tsx b/packages/prosody-ui/src/zoom/Paragraph.tsx new file mode 100644 index 0000000..c26f806 --- /dev/null +++ b/packages/prosody-ui/src/zoom/Paragraph.tsx @@ -0,0 +1,60 @@ +import React, { memo, useCallback, useEffect, useState } from "react"; +import { motion } from "motion/react"; +import type { ViewProps, LoadingStatus } from "./logic/types"; +import { NLP } from "sortug-ai"; +import Sentence from "./Sentence"; +import { paragraphVariants, createHoverEffect } from "./animations"; +import { useZoom } from "./hooks/useZoom"; + +function Paragraph({ rawText, context, idx, doc }: ViewProps) { + const { viewState, handleElementClick } = useZoom(); + const { level, pIndex } = viewState; + const selected = pIndex === idx; + const isFocused = level === "paragraph" && selected; + + // State for sentences + const [loading, setLoading] = useState<LoadingStatus>("pending"); + + return ( + <> + <motion.div + key={idx + rawText} + className={`paragraph-wrapper ${selected ? "selected" : ""}`} + custom={selected} + variants={paragraphVariants} + initial="text" + animate={level} + onClick={(e) => handleElementClick(e, idx)} + whileHover={ + level === "text" + ? createHoverEffect(level, "text", "255, 255, 200") + : {} + } + > + {loading === "loading" && <div className="spinner" />} + {level === "text" || !selected || doc.segs.length === 0 ? ( + <p className="paragraph">{rawText}</p> + ) : ( + <div className="sentences-container"> + {doc.segs.map((sentence, sentIdx) => ( + <Sentence + key={sentence.text + sentIdx} + idx={sentIdx} + rawText={sentence.text} + spacy={sentence} + context={{ + idx: sentIdx, + parentText: rawText, + segmented: doc.segs.map((s) => s.text), + }} + doc={doc} + /> + ))} + </div> + )} + </motion.div> + </> + ); +} + +export default memo(Paragraph); diff --git a/packages/prosody-ui/src/zoom/Sentence.tsx b/packages/prosody-ui/src/zoom/Sentence.tsx new file mode 100644 index 0000000..1d90346 --- /dev/null +++ b/packages/prosody-ui/src/zoom/Sentence.tsx @@ -0,0 +1,46 @@ +import React, { memo } from "react"; +import { motion } from "motion/react"; +import type { ViewProps, LoadingStatus } from "./logic/types"; +import { NLP } from "sortug-ai"; +import SpacyClause from "./SpacyClause"; +import { sentenceVariants, createHoverEffect } from "./animations"; +import { useZoom } from "./hooks/useZoom"; + +interface Props extends ViewProps { + spacy: NLP.Spacy.Sentence; + stanza?: NLP.Stanza.Sentence; +} + +function Sentence({ spacy, stanza, context, idx }: Props) { + const { viewState, handleElementClick } = useZoom(); + const { level, sIndex } = viewState; + const selected = sIndex === idx; + const isFocused = level === "sentence" && selected; + + return ( + <> + <motion.span + key={idx + spacy.text} + className={`sentence-wrapper ${selected ? "selected" : ""}`} + custom={selected} + variants={sentenceVariants} + initial="paragraph" + animate={level} + onClick={(e) => handleElementClick(e, idx)} + whileHover={ + level === "paragraph" + ? createHoverEffect(level, "paragraph", "200, 220, 255") + : {} + } + > + {level === "paragraph" || !selected ? ( + <span className="sentence">{spacy.text}</span> + ) : ( + <SpacyClause sentence={spacy} /> + )} + </motion.span> + </> + ); +} + +export default memo(Sentence); diff --git a/packages/prosody-ui/src/zoom/SpacyClause.tsx b/packages/prosody-ui/src/zoom/SpacyClause.tsx new file mode 100644 index 0000000..6b6f178 --- /dev/null +++ b/packages/prosody-ui/src/zoom/SpacyClause.tsx @@ -0,0 +1,125 @@ +import React, { memo, useState } from "react"; +import { motion } from "motion/react"; +import "./spacy.css"; +import { NLP } from "sortug-ai"; +// import { clauseVariants, createHoverEffect } from "./animations"; +// import { useZoom } from "./hooks/useZoom"; + +function Grammar({ sentence }: { sentence: NLP.Spacy.Sentence }) { + const [hoveredClause, setHoveredClause] = useState<number | null>(null); + + // Ref to manage the timeout for debouncing mouse leave + return ( + <div className="clause-container"> + {sentence.words.map((w, idx) => { + const isRoot = + w.ancestors.length === 0 || w.dep.toLowerCase() === "root"; + const isSubj = NLP.Spacy.isChild(w, sentence.subj.id); + const isPred = !isSubj && !isRoot; + const predClass = isPred ? "pred" : ""; + const relClass = isRoot ? "root" : `rel-${w.dep}`; + const ownClass = isRoot + ? "" + : isSubj + ? "subj" + : w.children.length === 0 + ? "" + : `clause-${w.id}`; + const clase = w.ancestors.reduce((acc, item) => { + if (item === sentence.subj.id || item === sentence.root.id) + return acc; + else return `${acc} clause-${item}`; + }, ``); + const className = `suword ${relClass} ${ownClass} ${clase} ${predClass}`; + const isHovering = + !isRoot && + !!hoveredClause && + (w.id === hoveredClause || w.ancestors.includes(hoveredClause)); + function handleClick(w: NLP.Spacy.Word) { + console.log("show the whole clause and all that", w); + } + return ( + <ClauseSpan + word={w} + key={w.id} + className={className} + hovering={isHovering} + setHovering={setHoveredClause} + onClick={handleClick} + /> + ); + })} + </div> + ); +} + +const spanVariants: any = { + initial: { + // Base style + backgroundColor: "rgba(0, 0, 0, 0)", // Transparent background initially + fontWeight: "normal", + scale: 1, + zIndex: 0, // Default stacking + position: "relative", // Needed for zIndex to work reliably + // Add other base styles if needed + }, + hovered: { + // Style when this span's group is hovered + backgroundColor: "rgba(255, 255, 0, 0.5)", // Yellow highlight + scale: 1.05, + zIndex: 1, // Bring hovered spans slightly forward + boxShadow: "0px 2px 5px rgba(0,0,0,0.2)", + // Add other hover effects + }, +}; + +// Define the transition +const spanTransition = { + type: "spring", + stiffness: 500, + damping: 30, + // duration: 0.1 // Or use duration for non-spring types +}; + +function ClauseSpan({ + word, + className, + hovering, + setHovering, + onClick, +}: { + word: NLP.Spacy.Word; + className: string; + hovering: boolean; + setHovering: (n: number | null) => void; + onClick: (w: NLP.Spacy.Word) => void; +}) { + function handleMouseOver() { + setHovering(word.id); + // if (word.children.length > 0) setHovering(word.id); + // else setHovering(word.head); + } + function handleMouseLeave() { + setHovering(null); + } + function handleClick(e: React.MouseEvent) { + e.stopPropagation(); + onClick(word); + } + return ( + <motion.span + className={className} + variants={spanVariants} + initial="initial" + animate={hovering ? "hovered" : "initial"} + transition={spanTransition} + onMouseOver={handleMouseOver} + onMouseLeave={handleMouseLeave} + onClick={handleClick} + > + {word.text} + </motion.span> + ); +} + +export default memo(Grammar); diff --git a/packages/prosody-ui/src/zoom/animations.ts b/packages/prosody-ui/src/zoom/animations.ts new file mode 100644 index 0000000..6135e7f --- /dev/null +++ b/packages/prosody-ui/src/zoom/animations.ts @@ -0,0 +1,199 @@ +import type { Variants } from "motion/react"; + +// Base transition configurations for consistent animations +const baseTransition = { + duration: 0.5, + ease: [0.43, 0.13, 0.23, 0.96], // Improved easing for smoother feel +}; + +export const fadeTransition = { + ...baseTransition, + duration: 0.3, +}; + +// Shared variants for different view levels +export const containerVariants: Variants = { + text: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + paragraph: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + sentence: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + clause: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + word: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + syllable: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, + phoneme: { + opacity: 1, + transition: { + staggerChildren: 0.05, + delayChildren: 0.1, + }, + }, +}; + +// Function to create element variants based on selection state +export const createElementVariants = ( + currentLevel: string, + nextLevel: string, + prevLevel: string, + selectedOpacity = 1, + unselectedOpacity = 0.1, + selectedScale = 1.05, + unselectedScale = 0.95, + selectedBlur = "0px", + unselectedBlur = "2px", + bgColor = "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity instead of transparent +): Variants => { + return { + [prevLevel]: { + opacity: 1, + scale: 1, + filter: "blur(0px)", + backgroundColor: "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity + transition: baseTransition, + }, + [currentLevel]: (isSelected: boolean) => ({ + opacity: isSelected ? selectedOpacity : unselectedOpacity, + scale: isSelected ? selectedScale : unselectedScale, + filter: isSelected ? `blur(${selectedBlur})` : `blur(${unselectedBlur})`, + backgroundColor: isSelected ? bgColor : "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity + transition: baseTransition, + }), + [nextLevel]: (isSelected: boolean) => ({ + opacity: isSelected ? selectedOpacity : unselectedOpacity / 2, + scale: isSelected ? selectedScale : unselectedScale * 0.95, + filter: isSelected + ? `blur(${selectedBlur})` + : `blur(${parseInt(unselectedBlur) + 1}px)`, + backgroundColor: isSelected ? bgColor : "rgba(255, 255, 255, 0)", // Use rgba with 0 opacity + transition: baseTransition, + }), + }; +}; + +// Pre-configured variants for each level +export const paragraphVariants = createElementVariants( + "paragraph", + "sentence", + "text", + 1, + 0.1, + 1.05, + 0.95, + "0px", + "2px", + "rgba(200, 220, 255, 0.1)", +); + +export const sentenceVariants = createElementVariants( + "sentence", + "clause", + "paragraph", + 1, + 0.1, + 1.1, + 0.95, + "0px", + "2px", + "rgba(200, 220, 255, 0.2)", +); + +export const clauseVariants = createElementVariants( + "clause", + "word", + "sentence", + 1, + 0.1, + 1.1, + 0.95, + "0px", + "2px", + "rgba(220, 200, 255, 0.2)", +); + +export const wordVariants = createElementVariants( + "word", + "syllable", + "clause", + 1, + 0.1, + 1.15, + 0.9, + "0px", + "2px", + "rgba(255, 200, 200, 0.2)", +); + +export const syllableVariants = createElementVariants( + "syllable", + "phoneme", + "word", + 1, + 0.1, + 1.2, + 0.9, + "0px", + "2px", + "rgba(200, 255, 200, 0.2)", +); + +// Button animations +export const buttonVariants: Variants = { + initial: { opacity: 0, x: -20 }, + animate: { opacity: 1, x: 0, transition: fadeTransition }, + exit: { opacity: 0, x: -20, transition: fadeTransition }, +}; + +// Hover effects +export const createHoverEffect = ( + level: string, + currentLevel: string, + color: string, +) => { + if (level === currentLevel) { + return { + scale: 1.02, + backgroundColor: `rgba(${color}, 0.3)`, + transition: { duration: 0.2 }, + }; + } + return { + // Return empty animation with same properties to avoid errors + scale: 1, + backgroundColor: "rgba(255, 255, 255, 0)", + transition: { duration: 0.2 }, + }; +}; diff --git a/packages/prosody-ui/src/zoom/hooks/useZoom.tsx b/packages/prosody-ui/src/zoom/hooks/useZoom.tsx new file mode 100644 index 0000000..733ca06 --- /dev/null +++ b/packages/prosody-ui/src/zoom/hooks/useZoom.tsx @@ -0,0 +1,135 @@ +import React, { + createContext, + useState, + useContext, + type ReactNode, +} from "react"; +import type { ViewLevel, ViewState } from "../logic/types"; + +// Type definitions for the context +interface ZoomContextType { + viewState: ViewState; + setLevel: (level: ViewLevel) => void; + setParagraphIndex: (idx: number | null) => void; + setSentenceIndex: (idx: number | null) => void; + setClauseIndex: (idx: number | null) => void; + setWordIndex: (idx: number | null) => void; + setSyllableIndex: (idx: number | null) => void; + setPhonemeIndex: (idx: number | null) => void; + navigateBack: () => void; + handleElementClick: (e: React.MouseEvent, idx: number) => void; +} + +// Create the context with default empty values +const ZoomContext = createContext<ZoomContextType>({ + viewState: { + level: "text", + pIndex: null, + sIndex: null, + cIndex: null, + wIndex: null, + yIndex: null, + fIndex: null, + }, + setLevel: () => {}, + setParagraphIndex: () => {}, + setSentenceIndex: () => {}, + setClauseIndex: () => {}, + setWordIndex: () => {}, + setSyllableIndex: () => {}, + setPhonemeIndex: () => {}, + navigateBack: () => {}, + handleElementClick: () => {}, +}); + +// Provider component +export const ZoomProvider: React.FC<{ children: ReactNode }> = ({ + children, +}) => { + const [viewState, setViewState] = useState<ViewState>({ + level: "text", + pIndex: null, + sIndex: null, + cIndex: null, + wIndex: null, + yIndex: null, + fIndex: null, + }); + + // Helper functions to update individual parts of the state + const setLevel = (level: ViewLevel) => + setViewState((prev) => ({ ...prev, level })); + const setParagraphIndex = (pIndex: number | null) => + setViewState((prev) => ({ ...prev, pIndex })); + const setSentenceIndex = (sIndex: number | null) => + setViewState((prev) => ({ ...prev, sIndex })); + const setClauseIndex = (cIndex: number | null) => + setViewState((prev) => ({ ...prev, cIndex })); + const setWordIndex = (wIndex: number | null) => + setViewState((prev) => ({ ...prev, wIndex })); + const setSyllableIndex = (yIndex: number | null) => + setViewState((prev) => ({ ...prev, yIndex })); + const setPhonemeIndex = (fIndex: number | null) => + setViewState((prev) => ({ ...prev, fIndex })); + + // Handle navigation levels + const navigateBack = () => { + const { level } = viewState; + + if (level === "paragraph") { + setViewState((prev) => ({ ...prev, level: "text", pIndex: null })); + } else if (level === "sentence") { + setViewState((prev) => ({ ...prev, level: "paragraph", sIndex: null })); + } else if (level === "clause") { + setViewState((prev) => ({ ...prev, level: "sentence", cIndex: null })); + } else if (level === "word") { + setViewState((prev) => ({ ...prev, level: "clause", wIndex: null })); + } else if (level === "syllable") { + setViewState((prev) => ({ ...prev, level: "word", yIndex: null })); + } else if (level === "phoneme") { + setViewState((prev) => ({ ...prev, level: "syllable", fIndex: null })); + } + }; + + // Handle clicks on elements to navigate forward + const handleElementClick = (e: React.MouseEvent, idx: number) => { + e.stopPropagation(); + const { level } = viewState; + + if (level === "text") { + setViewState((prev) => ({ ...prev, level: "paragraph", pIndex: idx })); + } else if (level === "paragraph") { + setViewState((prev) => ({ ...prev, level: "sentence", sIndex: idx })); + } else if (level === "sentence") { + setViewState((prev) => ({ ...prev, level: "clause", cIndex: idx })); + } else if (level === "clause") { + setViewState((prev) => ({ ...prev, level: "word", wIndex: idx })); + } else if (level === "word") { + setViewState((prev) => ({ ...prev, level: "syllable", yIndex: idx })); + } else if (level === "syllable") { + setViewState((prev) => ({ ...prev, level: "phoneme", fIndex: idx })); + } + }; + + return ( + <ZoomContext.Provider + value={{ + viewState, + setLevel, + setParagraphIndex, + setSentenceIndex, + setClauseIndex, + setWordIndex, + setSyllableIndex, + setPhonemeIndex, + navigateBack, + handleElementClick, + }} + > + {children} + </ZoomContext.Provider> + ); +}; + +// Custom hook to use the zoom context +export const useZoom = () => useContext(ZoomContext); diff --git a/packages/prosody-ui/src/zoom/index.ts b/packages/prosody-ui/src/zoom/index.ts new file mode 100644 index 0000000..baf5db1 --- /dev/null +++ b/packages/prosody-ui/src/zoom/index.ts @@ -0,0 +1,8 @@ +export { ZoomProvider, useZoom } from "./hooks/useZoom"; +import Paragraph from "./Paragraph"; +import FullText from "./FullText"; +import Sentence from "./Paragraph"; +import SpacyClause from "./SpacyClause"; +import type * as Types from "./logic/types"; + +export { Paragraph, FullText, Sentence, SpacyClause, Types }; diff --git a/packages/prosody-ui/src/zoom/logic/types.ts b/packages/prosody-ui/src/zoom/logic/types.ts new file mode 100644 index 0000000..bea68ff --- /dev/null +++ b/packages/prosody-ui/src/zoom/logic/types.ts @@ -0,0 +1,53 @@ +import type { NLP } from "sortug-ai"; + +export type ViewLevel = + | "text" + | "paragraph" + | "sentence" + | "clause" + | "word" + | "syllable" + | "phoneme"; +export interface ViewState { + level: ViewLevel; + pIndex: number | null; + sIndex: number | null; + cIndex: number | null; + wIndex: number | null; + yIndex: number | null; + fIndex: number | null; +} + +export interface ViewProps { + idx: number; + rawText: string; + context: Context; + doc: NLP.Spacy.SpacyRes; +} +export type Context = { + parentText: string; + segmented: string[]; + idx: number; +}; + +export type WordData = { + confidence: number; + frequency: number | null; + id: number; + ipa: Array<{ ipa: string; tags: string[] }>; + spelling: string; + type: ExpressionType; + syllables: number; + lang: string; + prosody: any; + senses: Sense[]; +}; +export type ExpressionType = "word" | "expression" | "syllable"; +export type Sense = { + etymology: string; + pos: string; + forms: Array<{ form: string; tags: string[] }>; + related: any; + senses: Array<{ glosses: string[]; links: Array<[string, string]> }>; +}; +export type LoadingStatus = "pending" | "loading" | "success" | "error"; diff --git a/packages/prosody-ui/src/zoom/spacy.css b/packages/prosody-ui/src/zoom/spacy.css new file mode 100644 index 0000000..0077119 --- /dev/null +++ b/packages/prosody-ui/src/zoom/spacy.css @@ -0,0 +1,39 @@ +.suword { + margin-left: 0.5ch; + margin-right: 0.5ch; +} + +/* .suword.pred { */ +/* color: gold; */ +/* } */ + +/* Clause level */ +.clause-container { + max-width: 600px; + white-space: normal !important; + hyphens: auto; + + padding: 2px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s ease; + will-change: transform, opacity, filter, background-color; + + span { + white-space: normal !important; + } +} + +.clause-container.selected { + background-color: rgba(220, 200, 255, 0.2); + z-index: 3; +} + +.suword.subj { + color: blue; + /* border-bottom: 2px solid blue; */ +} + +.suword.root { + color: darkred; +}
\ No newline at end of file diff --git a/packages/prosody-ui/tsconfig.json b/packages/prosody-ui/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/packages/prosody-ui/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} |
