From cb1b56f5a0eddbf77446f415f2beda57c8305f85 Mon Sep 17 00:00:00 2001 From: polwex Date: Sun, 23 Nov 2025 01:12:53 +0700 Subject: wut --- packages/prosody-ui/.gitignore | 175 ++++++++++++ packages/prosody-ui/README.md | 15 + packages/prosody-ui/bun.lock | 318 +++++++++++++++++++++ packages/prosody-ui/index.ts | 6 + packages/prosody-ui/package.json | 22 ++ packages/prosody-ui/src/LangText.tsx | 78 +++++ packages/prosody-ui/src/Paragraph.tsx | 56 ++++ .../assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf | Bin 0 -> 1984156 bytes .../src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf | Bin 0 -> 4827080 bytes .../src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf | Bin 0 -> 30564660 bytes .../src/assets/fonts/Hani/Iansui-Regular.ttf | Bin 0 -> 9396328 bytes .../assets/fonts/Hani/LiuJianMaoCao-Regular.ttf | Bin 0 -> 4940224 bytes .../src/assets/fonts/Hani/LongCang-Regular.ttf | Bin 0 -> 5151180 bytes .../src/assets/fonts/Hani/Meirenzhuan.ttf | Bin 0 -> 7336648 bytes .../fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf | Bin 0 -> 4890264 bytes .../src/assets/fonts/Hani/NotoSansHK-Black.ttf | Bin 0 -> 7082052 bytes .../src/assets/fonts/Hani/NotoSansHK-Bold.ttf | Bin 0 -> 7088136 bytes .../src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf | Bin 0 -> 7084512 bytes .../assets/fonts/Hani/NotoSansHK-ExtraLight.ttf | Bin 0 -> 7095176 bytes .../src/assets/fonts/Hani/NotoSansHK-Light.ttf | Bin 0 -> 7095576 bytes .../src/assets/fonts/Hani/NotoSansHK-Medium.ttf | Bin 0 -> 7089444 bytes .../src/assets/fonts/Hani/NotoSansHK-Regular.ttf | Bin 0 -> 7093428 bytes .../src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf | Bin 0 -> 7086788 bytes .../src/assets/fonts/Hani/NotoSansHK-Thin.ttf | Bin 0 -> 7092016 bytes .../fonts/Hani/NotoSansHK-VariableFont_wght.ttf | Bin 0 -> 11909304 bytes .../Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf | Bin 0 -> 5486956 bytes .../src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf | Bin 0 -> 2314256 bytes .../src/assets/fonts/Hani/ZhiMangXing-Regular.ttf | Bin 0 -> 4052388 bytes .../dingliezhuhaifont-20240831GengXinBan)-2.ttf | Bin 0 -> 5359608 bytes .../prosody-ui/src/assets/fonts/Hani/style.css | 223 +++++++++++++++ ...44\251\351\276\231\350\241\214\346\245\267.ttf" | Bin 0 -> 3344412 bytes .../src/assets/fonts/IPA/Judson-Bold.ttf | Bin 0 -> 192452 bytes .../src/assets/fonts/IPA/Judson-Italic.ttf | Bin 0 -> 209028 bytes .../src/assets/fonts/IPA/Judson-Regular.ttf | Bin 0 -> 217096 bytes .../IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf | Bin 0 -> 2637272 bytes .../fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf | Bin 0 -> 2490816 bytes .../src/assets/fonts/IPA/Voces-Regular.ttf | Bin 0 -> 119992 bytes packages/prosody-ui/src/assets/fonts/IPA/style.css | 33 +++ .../assets/fonts/Jpan/DelaGothicOne-Regular.ttf | Bin 0 -> 2487960 bytes .../src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf | Bin 0 -> 4256124 bytes .../src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf | Bin 0 -> 4265764 bytes .../src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf | Bin 0 -> 4472380 bytes .../assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf | Bin 0 -> 7095584 bytes .../src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf | Bin 0 -> 4303064 bytes .../prosody-ui/src/assets/fonts/Jpan/style.css | 223 +++++++++++++++ .../src/assets/fonts/Latn/Poppins/OFL.txt | 93 ++++++ .../assets/fonts/Latn/Poppins/Poppins-Black.ttf | Bin 0 -> 151396 bytes .../fonts/Latn/Poppins/Poppins-BlackItalic.ttf | Bin 0 -> 171604 bytes .../src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf | Bin 0 -> 153944 bytes .../fonts/Latn/Poppins/Poppins-BoldItalic.ttf | Bin 0 -> 176588 bytes .../fonts/Latn/Poppins/Poppins-ExtraBold.ttf | Bin 0 -> 152764 bytes .../fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf | Bin 0 -> 173916 bytes .../fonts/Latn/Poppins/Poppins-ExtraLight.ttf | Bin 0 -> 161456 bytes .../Latn/Poppins/Poppins-ExtraLightItalic.ttf | Bin 0 -> 186168 bytes .../assets/fonts/Latn/Poppins/Poppins-Italic.ttf | Bin 0 -> 182012 bytes .../assets/fonts/Latn/Poppins/Poppins-Light.ttf | Bin 0 -> 159892 bytes .../fonts/Latn/Poppins/Poppins-LightItalic.ttf | Bin 0 -> 184460 bytes .../assets/fonts/Latn/Poppins/Poppins-Medium.ttf | Bin 0 -> 156520 bytes .../fonts/Latn/Poppins/Poppins-MediumItalic.ttf | Bin 0 -> 180444 bytes .../assets/fonts/Latn/Poppins/Poppins-Regular.ttf | Bin 0 -> 158240 bytes .../assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf | Bin 0 -> 155232 bytes .../fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf | Bin 0 -> 178584 bytes .../src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf | Bin 0 -> 161652 bytes .../fonts/Latn/Poppins/Poppins-ThinItalic.ttf | Bin 0 -> 187044 bytes .../prosody-ui/src/assets/fonts/Latn/style.css | 11 + .../src/assets/fonts/Thai/Charm-Bold.ttf | Bin 0 -> 135416 bytes .../src/assets/fonts/Thai/Charm-Regular.ttf | Bin 0 -> 134652 bytes .../src/assets/fonts/Thai/Chonburi-Regular.ttf | Bin 0 -> 168404 bytes .../src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf | Bin 0 -> 113924 bytes .../fonts/Thai/IBMPlexSansThai-ExtraLight.ttf | Bin 0 -> 117248 bytes .../assets/fonts/Thai/IBMPlexSansThai-Light.ttf | Bin 0 -> 115728 bytes .../assets/fonts/Thai/IBMPlexSansThai-Medium.ttf | Bin 0 -> 113640 bytes .../assets/fonts/Thai/IBMPlexSansThai-Regular.ttf | Bin 0 -> 113392 bytes .../assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf | Bin 0 -> 113856 bytes .../src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf | Bin 0 -> 118256 bytes .../src/assets/fonts/Thai/Kanit-Black.ttf | Bin 0 -> 173492 bytes .../src/assets/fonts/Thai/Kanit-BlackItalic.ttf | Bin 0 -> 182076 bytes .../src/assets/fonts/Thai/Kanit-Bold.ttf | Bin 0 -> 172876 bytes .../src/assets/fonts/Thai/Kanit-BoldItalic.ttf | Bin 0 -> 180308 bytes .../src/assets/fonts/Thai/Kanit-ExtraBold.ttf | Bin 0 -> 174464 bytes .../assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf | Bin 0 -> 184928 bytes .../src/assets/fonts/Thai/Kanit-ExtraLight.ttf | Bin 0 -> 160796 bytes .../assets/fonts/Thai/Kanit-ExtraLightItalic.ttf | Bin 0 -> 164908 bytes .../src/assets/fonts/Thai/Kanit-Italic.ttf | Bin 0 -> 171876 bytes .../src/assets/fonts/Thai/Kanit-Light.ttf | Bin 0 -> 168036 bytes .../src/assets/fonts/Thai/Kanit-LightItalic.ttf | Bin 0 -> 171596 bytes .../src/assets/fonts/Thai/Kanit-Medium.ttf | Bin 0 -> 171336 bytes .../src/assets/fonts/Thai/Kanit-MediumItalic.ttf | Bin 0 -> 172360 bytes .../src/assets/fonts/Thai/Kanit-Regular.ttf | Bin 0 -> 169744 bytes .../src/assets/fonts/Thai/Kanit-SemiBold.ttf | Bin 0 -> 171548 bytes .../src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf | Bin 0 -> 172244 bytes .../src/assets/fonts/Thai/Kanit-Thin.ttf | Bin 0 -> 155788 bytes .../src/assets/fonts/Thai/Kanit-ThinItalic.ttf | Bin 0 -> 161688 bytes .../src/assets/fonts/Thai/Kodchasan-Bold.ttf | Bin 0 -> 98600 bytes .../src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf | Bin 0 -> 104048 bytes .../src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf | Bin 0 -> 96992 bytes .../fonts/Thai/Kodchasan-ExtraLightItalic.ttf | Bin 0 -> 101308 bytes .../src/assets/fonts/Thai/Kodchasan-Italic.ttf | Bin 0 -> 103088 bytes .../src/assets/fonts/Thai/Kodchasan-Light.ttf | Bin 0 -> 98168 bytes .../assets/fonts/Thai/Kodchasan-LightItalic.ttf | Bin 0 -> 102364 bytes .../src/assets/fonts/Thai/Kodchasan-Medium.ttf | Bin 0 -> 98740 bytes .../assets/fonts/Thai/Kodchasan-MediumItalic.ttf | Bin 0 -> 103552 bytes .../src/assets/fonts/Thai/Kodchasan-Regular.ttf | Bin 0 -> 98392 bytes .../src/assets/fonts/Thai/Kodchasan-SemiBold.ttf | Bin 0 -> 98824 bytes .../assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf | Bin 0 -> 104024 bytes .../prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf | Bin 0 -> 105372 bytes .../src/assets/fonts/Thai/Mali-BoldItalic.ttf | Bin 0 -> 108796 bytes .../src/assets/fonts/Thai/Mali-ExtraLight.ttf | Bin 0 -> 105668 bytes .../assets/fonts/Thai/Mali-ExtraLightItalic.ttf | Bin 0 -> 108572 bytes .../src/assets/fonts/Thai/Mali-Italic.ttf | Bin 0 -> 108960 bytes .../src/assets/fonts/Thai/Mali-Light.ttf | Bin 0 -> 105864 bytes .../src/assets/fonts/Thai/Mali-LightItalic.ttf | Bin 0 -> 108732 bytes .../src/assets/fonts/Thai/Mali-Medium.ttf | Bin 0 -> 105988 bytes .../src/assets/fonts/Thai/Mali-MediumItalic.ttf | Bin 0 -> 109008 bytes .../src/assets/fonts/Thai/Mali-Regular.ttf | Bin 0 -> 105896 bytes .../src/assets/fonts/Thai/Mali-SemiBold.ttf | Bin 0 -> 106032 bytes .../src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf | Bin 0 -> 109000 bytes .../src/assets/fonts/Thai/Sarabun-Bold.ttf | Bin 0 -> 82592 bytes .../src/assets/fonts/Thai/Sarabun-BoldItalic.ttf | Bin 0 -> 85636 bytes .../src/assets/fonts/Thai/Sarabun-ExtraBold.ttf | Bin 0 -> 82632 bytes .../assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf | Bin 0 -> 85448 bytes .../src/assets/fonts/Thai/Sarabun-ExtraLight.ttf | Bin 0 -> 83276 bytes .../assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf | Bin 0 -> 86368 bytes .../src/assets/fonts/Thai/Sarabun-Italic.ttf | Bin 0 -> 86024 bytes .../src/assets/fonts/Thai/Sarabun-Light.ttf | Bin 0 -> 83224 bytes .../src/assets/fonts/Thai/Sarabun-LightItalic.ttf | Bin 0 -> 86072 bytes .../src/assets/fonts/Thai/Sarabun-Medium.ttf | Bin 0 -> 83080 bytes .../src/assets/fonts/Thai/Sarabun-MediumItalic.ttf | Bin 0 -> 86136 bytes .../src/assets/fonts/Thai/Sarabun-Regular.ttf | Bin 0 -> 83080 bytes .../src/assets/fonts/Thai/Sarabun-SemiBold.ttf | Bin 0 -> 82952 bytes .../assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf | Bin 0 -> 86020 bytes .../src/assets/fonts/Thai/Sarabun-Thin.ttf | Bin 0 -> 83408 bytes .../src/assets/fonts/Thai/Sarabun-ThinItalic.ttf | Bin 0 -> 86344 bytes .../prosody-ui/src/assets/fonts/Thai/style.css | 76 +++++ packages/prosody-ui/src/assets/icons/bookmark.svg | 4 + packages/prosody-ui/src/assets/icons/font.svg | 2 + packages/prosody-ui/src/assets/icons/heart.svg | 4 + packages/prosody-ui/src/assets/icons/play.svg | 4 + packages/prosody-ui/src/assets/icons/quote.svg | 28 ++ packages/prosody-ui/src/assets/icons/react.svg | 1 + packages/prosody-ui/src/assets/icons/share.svg | 28 ++ packages/prosody-ui/src/assets/icons/speaker.svg | 32 +++ packages/prosody-ui/src/assets/icons/spinner.svg | 1 + packages/prosody-ui/src/components/Sentence.tsx | 57 ++++ packages/prosody-ui/src/components/Word.tsx | 119 ++++++++ packages/prosody-ui/src/components/sentence.css | 272 ++++++++++++++++++ packages/prosody-ui/src/components/word.css | 0 packages/prosody-ui/src/files.d.ts | 4 + packages/prosody-ui/src/fonts/FontChanger.tsx | 64 +++++ packages/prosody-ui/src/fonts/Hani.tsx | 14 + packages/prosody-ui/src/fonts/Thai.tsx | 8 + packages/prosody-ui/src/fonts/useLangFont.tsx | 44 +++ packages/prosody-ui/src/hooks/useLang.tsx | 184 ++++++++++++ packages/prosody-ui/src/hooks/useModal.tsx | 53 ++++ packages/prosody-ui/src/hooks/useTTS.tsx | 3 + packages/prosody-ui/src/latin/LatinText.tsx | 77 +++++ packages/prosody-ui/src/logic/iso6393to1.ts | 186 ++++++++++++ packages/prosody-ui/src/logic/stanza.ts | 86 ++++++ packages/prosody-ui/src/logic/types.ts | 48 ++++ packages/prosody-ui/src/logic/utils.ts | 66 +++++ packages/prosody-ui/src/logic/wiki.ts | 138 +++++++++ packages/prosody-ui/src/sortug.css | 248 ++++++++++++++++ packages/prosody-ui/src/styles/styles.css | 281 ++++++++++++++++++ packages/prosody-ui/src/thai/ThaiText.tsx | 49 ++++ packages/prosody-ui/src/thai/logic/thainlp.ts | 90 ++++++ packages/prosody-ui/src/zoom/FullText.tsx | 60 ++++ packages/prosody-ui/src/zoom/Paragraph.tsx | 60 ++++ packages/prosody-ui/src/zoom/Sentence.tsx | 46 +++ packages/prosody-ui/src/zoom/SpacyClause.tsx | 125 ++++++++ packages/prosody-ui/src/zoom/animations.ts | 199 +++++++++++++ packages/prosody-ui/src/zoom/hooks/useZoom.tsx | 135 +++++++++ packages/prosody-ui/src/zoom/index.ts | 8 + packages/prosody-ui/src/zoom/logic/types.ts | 53 ++++ packages/prosody-ui/src/zoom/spacy.css | 39 +++ packages/prosody-ui/tsconfig.json | 27 ++ 175 files changed, 4276 insertions(+) create mode 100644 packages/prosody-ui/.gitignore create mode 100644 packages/prosody-ui/README.md create mode 100644 packages/prosody-ui/bun.lock create mode 100644 packages/prosody-ui/index.ts create mode 100644 packages/prosody-ui/package.json create mode 100644 packages/prosody-ui/src/LangText.tsx create mode 100644 packages/prosody-ui/src/Paragraph.tsx create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-VariableFont_wght.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/dingliezhuhaifont-20240831GengXinBan)-2.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Hani/style.css create mode 100644 "packages/prosody-ui/src/assets/fonts/Hani/\345\255\227\351\255\202\345\244\251\351\276\231\350\241\214\346\245\267.ttf" create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/IPA/style.css create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/DelaGothicOne-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Jpan/style.css create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/OFL.txt create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Black.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BlackItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BoldItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLight.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLightItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Italic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Light.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-LightItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Medium.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-MediumItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Regular.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ThinItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Latn/style.css create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Charm-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf create mode 100755 packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf create mode 100644 packages/prosody-ui/src/assets/fonts/Thai/style.css create mode 100755 packages/prosody-ui/src/assets/icons/bookmark.svg create mode 100755 packages/prosody-ui/src/assets/icons/font.svg create mode 100755 packages/prosody-ui/src/assets/icons/heart.svg create mode 100755 packages/prosody-ui/src/assets/icons/play.svg create mode 100755 packages/prosody-ui/src/assets/icons/quote.svg create mode 100755 packages/prosody-ui/src/assets/icons/react.svg create mode 100755 packages/prosody-ui/src/assets/icons/share.svg create mode 100644 packages/prosody-ui/src/assets/icons/speaker.svg create mode 100755 packages/prosody-ui/src/assets/icons/spinner.svg create mode 100644 packages/prosody-ui/src/components/Sentence.tsx create mode 100644 packages/prosody-ui/src/components/Word.tsx create mode 100644 packages/prosody-ui/src/components/sentence.css create mode 100644 packages/prosody-ui/src/components/word.css create mode 100644 packages/prosody-ui/src/files.d.ts create mode 100644 packages/prosody-ui/src/fonts/FontChanger.tsx create mode 100644 packages/prosody-ui/src/fonts/Hani.tsx create mode 100644 packages/prosody-ui/src/fonts/Thai.tsx create mode 100644 packages/prosody-ui/src/fonts/useLangFont.tsx create mode 100644 packages/prosody-ui/src/hooks/useLang.tsx create mode 100644 packages/prosody-ui/src/hooks/useModal.tsx create mode 100644 packages/prosody-ui/src/hooks/useTTS.tsx create mode 100644 packages/prosody-ui/src/latin/LatinText.tsx create mode 100644 packages/prosody-ui/src/logic/iso6393to1.ts create mode 100644 packages/prosody-ui/src/logic/stanza.ts create mode 100644 packages/prosody-ui/src/logic/types.ts create mode 100644 packages/prosody-ui/src/logic/utils.ts create mode 100644 packages/prosody-ui/src/logic/wiki.ts create mode 100644 packages/prosody-ui/src/sortug.css create mode 100644 packages/prosody-ui/src/styles/styles.css create mode 100644 packages/prosody-ui/src/thai/ThaiText.tsx create mode 100644 packages/prosody-ui/src/thai/logic/thainlp.ts create mode 100644 packages/prosody-ui/src/zoom/FullText.tsx create mode 100644 packages/prosody-ui/src/zoom/Paragraph.tsx create mode 100644 packages/prosody-ui/src/zoom/Sentence.tsx create mode 100644 packages/prosody-ui/src/zoom/SpacyClause.tsx create mode 100644 packages/prosody-ui/src/zoom/animations.ts create mode 100644 packages/prosody-ui/src/zoom/hooks/useZoom.tsx create mode 100644 packages/prosody-ui/src/zoom/index.ts create mode 100644 packages/prosody-ui/src/zoom/logic/types.ts create mode 100644 packages/prosody-ui/src/zoom/spacy.css create mode 100644 packages/prosody-ui/tsconfig.json (limited to 'packages/prosody-ui') 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; + handleWord?: (wd: Result) => 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(); + } + + return ( +
+ {script === "Thai" ? ( + + ) : script === "Latin" ? ( + + ) : ( + + )} +
+ ); +} +function Generic({ text, lang }: { text: string; lang: string }) { + const [data, setData] = useState(); + useEffect(() => { + // segmentate(text, lang) + }, [text, lang]); + console.log({ lang }, "generic"); + //

{lang}

+ //

{text}

+ // {data && } + return
; +} 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) => any; +}) { + useEffect(() => { + segmentString(); + }, [text]); + const [lang, setLang] = useState(""); + const [script, setScript] = useState(""); + const [segs, setSegs] = useState([]); + 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
{text}
; +} diff --git a/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf b/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf new file mode 100644 index 0000000..5ada19c Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/BeiShiDaJiaGuWenZiTi-1.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf new file mode 100644 index 0000000..2606d1c Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/GaiLiangShouJinTi-2.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf new file mode 100644 index 0000000..49f5405 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/GuDianMingChaoKai-2.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf new file mode 100644 index 0000000..5da538b Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/Iansui-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf new file mode 100644 index 0000000..4b7e9bc Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/LiuJianMaoCao-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf new file mode 100644 index 0000000..44f6a9f Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/LongCang-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf b/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf new file mode 100644 index 0000000..8eb1209 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/Meirenzhuan.ttf differ 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 new file mode 100644 index 0000000..1f16ba8 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/No.300-ShangShouGuHuangTi-2.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf new file mode 100644 index 0000000..e86fb96 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Black.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf new file mode 100644 index 0000000..76812d7 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf new file mode 100644 index 0000000..db381ed Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf new file mode 100644 index 0000000..e30cdd8 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf new file mode 100644 index 0000000..8be49fc Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf new file mode 100644 index 0000000..f45d4ec Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf new file mode 100644 index 0000000..2a62b97 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf new file mode 100644 index 0000000..bc3e266 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf new file mode 100644 index 0000000..832c29f Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-Thin.ttf differ 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 new file mode 100644 index 0000000..47f2c84 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/NotoSansHK-VariableFont_wght.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf b/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf new file mode 100644 index 0000000..b59a399 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/YeZiGongChangZuiHanJiangXingCao-2.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf b/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf new file mode 100644 index 0000000..9364f2d Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/YiShanBeiZhuanTi.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf new file mode 100644 index 0000000..e2d4fad Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/ZhiMangXing-Regular.ttf differ 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 new file mode 100644 index 0000000..b387fc5 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Hani/dingliezhuhaifont-20240831GengXinBan)-2.ttf differ 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/\345\255\227\351\255\202\345\244\251\351\276\231\350\241\214\346\245\267.ttf" "b/packages/prosody-ui/src/assets/fonts/Hani/\345\255\227\351\255\202\345\244\251\351\276\231\350\241\214\346\245\267.ttf" new file mode 100644 index 0000000..b565e37 Binary files /dev/null and "b/packages/prosody-ui/src/assets/fonts/Hani/\345\255\227\351\255\202\345\244\251\351\276\231\350\241\214\346\245\267.ttf" differ diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf new file mode 100755 index 0000000..4b977b0 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf new file mode 100755 index 0000000..b2ea190 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Italic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf new file mode 100755 index 0000000..a1cbb58 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/Judson-Regular.ttf differ 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 new file mode 100755 index 0000000..4e962ee Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-Italic-VariableFont_wdth,wght.ttf differ 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 new file mode 100755 index 0000000..f7d0d78 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/NotoSans-VariableFont_wdth,wght.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf b/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf new file mode 100755 index 0000000..36aa975 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/IPA/Voces-Regular.ttf differ 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 new file mode 100644 index 0000000..475c4dd Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/DelaGothicOne-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf new file mode 100644 index 0000000..7d13d05 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf new file mode 100644 index 0000000..1e35712 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf new file mode 100644 index 0000000..7d68508 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/KaiseiDecol-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf new file mode 100644 index 0000000..c78f7d6 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/ZenAntiqueSoft-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf new file mode 100644 index 0000000..cb3044e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Jpan/ZenKurenaido-Regular.ttf differ 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 new file mode 100644 index 0000000..71c0f99 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Black.ttf differ 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 new file mode 100644 index 0000000..7aeb58b Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BlackItalic.ttf differ 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 new file mode 100644 index 0000000..00559ee Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Bold.ttf differ 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 new file mode 100644 index 0000000..e61e8e8 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-BoldItalic.ttf differ 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 new file mode 100644 index 0000000..df70936 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBold.ttf differ 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 new file mode 100644 index 0000000..14d2b37 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraBoldItalic.ttf differ 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 new file mode 100644 index 0000000..e76ec69 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLight.ttf differ 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 new file mode 100644 index 0000000..89513d9 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ExtraLightItalic.ttf differ 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 new file mode 100644 index 0000000..12b7b3c Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Italic.ttf differ 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 new file mode 100644 index 0000000..bc36bcc Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Light.ttf differ 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 new file mode 100644 index 0000000..9e70be6 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-LightItalic.ttf differ 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 new file mode 100644 index 0000000..6bcdcc2 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Medium.ttf differ 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 new file mode 100644 index 0000000..be67410 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-MediumItalic.ttf differ 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 new file mode 100644 index 0000000..9f0c71b Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Regular.ttf differ 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 new file mode 100644 index 0000000..74c726e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBold.ttf differ 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 new file mode 100644 index 0000000..3e6c942 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-SemiBoldItalic.ttf differ 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 new file mode 100644 index 0000000..03e7366 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-Thin.ttf differ 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 new file mode 100644 index 0000000..e26db5d Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Latn/Poppins/Poppins-ThinItalic.ttf differ 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 new file mode 100755 index 0000000..d32f072 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf new file mode 100755 index 0000000..02013a4 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Charm-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf new file mode 100755 index 0000000..52fedc7 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Chonburi-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf new file mode 100755 index 0000000..3a8583f Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf new file mode 100755 index 0000000..c4161bd Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf new file mode 100755 index 0000000..a676550 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf new file mode 100755 index 0000000..75e62df Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf new file mode 100755 index 0000000..c31b8c2 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf new file mode 100755 index 0000000..9812b5a Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf new file mode 100755 index 0000000..2cc968f Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/IBMPlexSansThai-Thin.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf new file mode 100755 index 0000000..2e37a00 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Black.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf new file mode 100755 index 0000000..dc81853 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BlackItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf new file mode 100755 index 0000000..4686906 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf new file mode 100755 index 0000000..17eda2a Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-BoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf new file mode 100755 index 0000000..5240d38 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf new file mode 100755 index 0000000..037187a Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf new file mode 100755 index 0000000..404c1e0 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf new file mode 100755 index 0000000..5d575cc Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ExtraLightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf new file mode 100755 index 0000000..e6d868b Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Italic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf new file mode 100755 index 0000000..3c9d4b5 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf new file mode 100755 index 0000000..59a3f2e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-LightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf new file mode 100755 index 0000000..50413d0 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf new file mode 100755 index 0000000..2c6aa14 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-MediumItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf new file mode 100755 index 0000000..ef204c1 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf new file mode 100755 index 0000000..7501a2e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf new file mode 100755 index 0000000..2284650 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-SemiBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf new file mode 100755 index 0000000..5c835ad Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-Thin.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf new file mode 100755 index 0000000..25fd1f9 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kanit-ThinItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf new file mode 100755 index 0000000..cd36ffc Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf new file mode 100755 index 0000000..f86a715 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-BoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf new file mode 100755 index 0000000..af416d2 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf new file mode 100755 index 0000000..3478406 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-ExtraLightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf new file mode 100755 index 0000000..3032d77 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Italic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf new file mode 100755 index 0000000..b3db128 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf new file mode 100755 index 0000000..5acfdd5 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-LightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf new file mode 100755 index 0000000..de8f843 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf new file mode 100755 index 0000000..2c0cb1e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-MediumItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf new file mode 100755 index 0000000..b6cb5d5 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf new file mode 100755 index 0000000..917a988 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf new file mode 100755 index 0000000..36d3579 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Kodchasan-SemiBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf new file mode 100755 index 0000000..db8c190 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf new file mode 100755 index 0000000..a67a0ae Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-BoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf new file mode 100755 index 0000000..0e3f955 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf new file mode 100755 index 0000000..6f4d3d3 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-ExtraLightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf new file mode 100755 index 0000000..479a8e8 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Italic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf new file mode 100755 index 0000000..aaad3b6 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf new file mode 100755 index 0000000..cdfa5c6 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-LightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf new file mode 100755 index 0000000..658a6a1 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf new file mode 100755 index 0000000..4b88574 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-MediumItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf new file mode 100755 index 0000000..70cd35b Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf new file mode 100755 index 0000000..acdce49 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf new file mode 100755 index 0000000..fc76e74 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Mali-SemiBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf new file mode 100755 index 0000000..4d6bf36 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Bold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf new file mode 100755 index 0000000..42857a5 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-BoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf new file mode 100755 index 0000000..27ba997 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf new file mode 100755 index 0000000..bc36f97 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf new file mode 100755 index 0000000..060c6c1 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLight.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf new file mode 100755 index 0000000..beaa024 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ExtraLightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf new file mode 100755 index 0000000..51d6dbe Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Italic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf new file mode 100755 index 0000000..d2f2291 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Light.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf new file mode 100755 index 0000000..75eb8d8 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-LightItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf new file mode 100755 index 0000000..e03148e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Medium.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf new file mode 100755 index 0000000..b172a09 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-MediumItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf new file mode 100755 index 0000000..50fa707 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Regular.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf new file mode 100755 index 0000000..7b760ce Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBold.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf new file mode 100755 index 0000000..ecc5fb6 Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-SemiBoldItalic.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf new file mode 100755 index 0000000..cdaabcb Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-Thin.ttf differ diff --git a/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf new file mode 100755 index 0000000..e96d17e Binary files /dev/null and b/packages/prosody-ui/src/assets/fonts/Thai/Sarabun-ThinItalic.ttf differ 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 @@ + + + + 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 @@ + + \ 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 @@ + + + + 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 @@ + + + + \ 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 @@ + + + + + + + + \ 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 @@ + \ 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 @@ + + + + + + + + + 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 @@ + + + + + + + + + + + + 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 @@ + 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 ; + })} + + ); +} + +export function CTInner({ + s, + style, + fn, + lang, +}: { + s: string; + style: any; + fn?: (s: string) => void; + lang?: string; +}) { + function handleClick(e: React.MouseEvent) { + console.log(!!fn, "fn"); + if (fn) fn(e.currentTarget.innerText.trim()); + } + return ( + + {s} + + ); +} +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([]); + 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 ( +
+ + +
+ +
+
+

{`/${data.ipa.replace(/\s/g, "")}/`}

+ +
+
+ {loading ? ( + + ) : ( + meanings.map((m) => ( +
+
+ {m.pos} +
+
    + {m.meaning.map((t, i) => ( +
  1. +

    {t}

    +
  2. + ))} +
+
+ )) + )} + {error &&
{error}
} +
+
+ ); +} + +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() +// } +// async function doBookmark() {} +// return ( +//
+//
+// +//
+// +// +// +// +// +//
+// ); +// } 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 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(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 ( +
+ + {script === "Thai" ? : null} +
+ ); +} +// 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 ( +//
+// +// {children} +//
+// ); +// } + +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
{children}
; +} + +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
{text}
; +} + +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(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 ( +//
+// +// {children} +//
+// ); +// } + +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 ( + + {children} + + ); +}; + +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) { + const writingSystemClass = + typeof children === "string" ? getScriptClass(children) : "text-latin"; + + return ( + + {children} + + ); + }; +}; + +// 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([]); + 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(""); + + return ( +
+ + + + + {speaking && } +
+ ); +}; 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(null); + return setChild(null)}>{achild}; +} +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(null); + const style = { width, height }; + return ( + + ); +} 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([]); + console.log({ sentences }); + return ( + <> + {sentences.map((s, i) => ( + + ))} + + ); +} + +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([]); + console.log({ words }); + + // const [data, setData] = useState>({}); + const [word, setWord] = useState(); + + return ( + <> + ; + {word && } + + ); +} 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 = { + 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; +export type CookieMap = Record; +export type KeyMap = Record; +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 { + 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 = {}; + + 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 { + 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 { + 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 { + 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 { + 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>({}); + const [modal, setModal] = useState(); + 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) { + // const s = e.currentTarget.innerText; + // const d = data[s]; + // setModal(d); + // // setModal(); + // } + return ( +
+ + {modal && } +
+ ); +} + +function ThaiWord() { + return
; +} 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 { + return await call("/analyze", { word }); +} +export async function segmentateThai(sentence: string): AsyncRes { + return await call("/segmentate", { word: sentence }); +} + +export const POSMAP: Record = { + 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 = ({ 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 ( +
+ {level !== "text" && ( + + + ← Back + + + )} + + + {paragraphs.map((paragraph, idx) => ( + + ))} + +
+ ); +}; + +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("pending"); + + return ( + <> + handleElementClick(e, idx)} + whileHover={ + level === "text" + ? createHoverEffect(level, "text", "255, 255, 200") + : {} + } + > + {loading === "loading" &&
} + {level === "text" || !selected || doc.segs.length === 0 ? ( +

{rawText}

+ ) : ( +
+ {doc.segs.map((sentence, sentIdx) => ( + s.text), + }} + doc={doc} + /> + ))} +
+ )} + + + ); +} + +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 ( + <> + handleElementClick(e, idx)} + whileHover={ + level === "paragraph" + ? createHoverEffect(level, "paragraph", "200, 220, 255") + : {} + } + > + {level === "paragraph" || !selected ? ( + {spacy.text} + ) : ( + + )} + + + ); +} + +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(null); + + // Ref to manage the timeout for debouncing mouse leave + return ( +
+ {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 ( + + ); + })} +
+ ); +} + +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 ( + + {word.text} + + ); +} + +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({ + 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({ + 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 ( + + {children} + + ); +}; + +// 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 + } +} -- cgit v1.2.3