Merge remote-tracking branch 'weblate/develop' into develop
This commit is contained in:
commit
7373fc625a
|
@ -675,3 +675,48 @@ useGlobalSetting: Fes servir els ajustos globals
|
|||
useGlobalSettingDesc: Si s'activa, es faran servir els ajustos de notificacions del
|
||||
teu compte. Si es desactiva , es poden fer configuracions individuals.
|
||||
other: Altres
|
||||
menu: Menú
|
||||
addItem: Afegeix un element
|
||||
divider: Divisor
|
||||
relays: Relés
|
||||
addRelay: Afegeix un Relé
|
||||
inboxUrl: Adreça de la safata d'entrada
|
||||
addedRelays: Relés afegits
|
||||
serviceworkerInfo: Ha de estar activat per les notificacions push.
|
||||
poll: Enquesta
|
||||
deletedNote: Article eliminat
|
||||
disablePlayer: Tancar el reproductor de vídeo
|
||||
fileIdOrUrl: ID o adreça URL del fitxer
|
||||
behavior: Comportament
|
||||
regenerateLoginTokenDescription: Regenera el token que es fa servir de manera interna
|
||||
durant l'inici de sessió. Normalment això no és necessari. Si es torna a genera
|
||||
el token, es tancarà la sessió a tots els dispositius.
|
||||
setMultipleBySeparatingWithSpace: Separa diferents entrades amb espais.
|
||||
reportAbuseOf: Informa sobre {name}
|
||||
sample: Exemple
|
||||
abuseReports: Informes
|
||||
reportAbuse: Informe
|
||||
reporter: Informador
|
||||
reporterOrigin: Origen d'el informador
|
||||
forwardReport: Envia l'informe a una instancia remota
|
||||
abuseReported: El teu informe ha sigut enviat. Moltes gràcies.
|
||||
reporteeOrigin: Origen de l'informe
|
||||
send: Enviar
|
||||
abuseMarkAsResolved: Marcar l'informe com a resolt
|
||||
visibility: Visibilitat
|
||||
useCw: Amaga el contingut
|
||||
enablePlayer: Obre el reproductor de vídeo
|
||||
yourAccountSuspendedDescription: Aquest compte ha sigut suspesa per no seguir els
|
||||
termes de servei del servidor o quelcom similar. Contacte amb l'administrador si
|
||||
vols conèixer la raó amb més detall. Si us plau no facis un compte nou.
|
||||
invisibleNote: Article ocult
|
||||
enableInfiniteScroll: Carregar més de forma automàtica
|
||||
fillAbuseReportDescription: Si us plau omple els detalls sobre aquest informe. Si
|
||||
es sobre un article en concret, si us plau inclou l'adreça URL.
|
||||
forwardReportIsAnonymous: Com a informador a l'instància remota no es mostrarà el
|
||||
teu compte, si no un compte anònim.
|
||||
openInNewTab: Obrir en una pestanya nova
|
||||
openInSideView: Obrir a la vista lateral
|
||||
defaultNavigationBehaviour: Navegació per defecte
|
||||
editTheseSettingsMayBreakAccount: Si edites aquestes configuracions pots fer mal bé
|
||||
el teu compte.
|
||||
|
|
|
@ -1042,7 +1042,7 @@ moveFromLabel: "Account you're moving from:"
|
|||
moveFromDescription: "This will set an alias of your old account so that you can move\
|
||||
\ from that account to this current one. Do this BEFORE moving from your older account.\
|
||||
\ Please enter the tag of the account formatted like @person@instance.com"
|
||||
migrationConfirm: "Are you absolutely sure you want to migrate your acccount to {account}?\
|
||||
migrationConfirm: "Are you absolutely sure you want to migrate your account to {account}?\
|
||||
\ Once you do this, you won't be able to reverse it, and you won't be able to use\
|
||||
\ your account normally again.\nAlso, please ensure that you've set this current\
|
||||
\ account as the account you're moving from."
|
||||
|
|
182
locales/fi.yml
182
locales/fi.yml
|
@ -3,7 +3,7 @@ fetchingAsApObject: Hae Fedeversestä
|
|||
gotIt: Selvä!
|
||||
cancel: Peruuta
|
||||
enterUsername: Anna käyttäjänimi
|
||||
renotedBy: Buustannut {käyttäjä}
|
||||
renotedBy: Buustannut {user}
|
||||
noNotes: Ei lähetyksiä
|
||||
noNotifications: Ei ilmoituksia
|
||||
instance: Instanssi
|
||||
|
@ -41,3 +41,183 @@ favorite: Lisää kirjanmerkkeihin
|
|||
copyContent: Kopioi sisältö
|
||||
deleteAndEdit: Poista ja muokkaa
|
||||
copyLink: Kopioi linkki
|
||||
makeFollowManuallyApprove: Seuraajapyyntö vaatii hyväksymistä
|
||||
follow: Seuraa
|
||||
pinned: Kiinnitä profiiliin
|
||||
followRequestPending: Seuraajapyyntö odottaa
|
||||
you: Sinä
|
||||
unrenote: Peruuta buustaus
|
||||
reaction: Reaktiot
|
||||
reactionSettingDescription2: Vedä uudelleenjärjestelläksesi, napsauta poistaaksesi,
|
||||
paina "+" lisätäksesi.
|
||||
attachCancel: Poista liite
|
||||
enterFileName: Anna tiedostonimi
|
||||
mute: Hiljennä
|
||||
unmute: Poista hiljennys
|
||||
headlineMisskey: Avoimen lähdekoodin, hajautettu sosiaalisen median alusta, joka on
|
||||
ikuisesti ilmainen! 🚀
|
||||
monthAndDay: '{day}/{month}'
|
||||
deleteAndEditConfirm: Oletko varma, että haluat poistaa tämän lähetyksen ja muokata
|
||||
sitä? Menetät kaikki reaktiot, buustaukset ja vastaukset lähetyksestäsi.
|
||||
addToList: Lisää listaan
|
||||
sendMessage: Lähetä viesti
|
||||
reply: Vastaa
|
||||
loadMore: Lataa enemmän
|
||||
showMore: Näytä enemmän
|
||||
receiveFollowRequest: Seuraajapyyntö vastaanotettu
|
||||
followRequestAccepted: Seuraajapyyntö hyväksytty
|
||||
mentions: Maininnat
|
||||
importAndExport: Tuo/Vie Tietosisältö
|
||||
import: Tuo
|
||||
export: Vie
|
||||
files: Tiedostot
|
||||
download: Lataa
|
||||
unfollowConfirm: Oletko varma, ettet halua seurata enää käyttäjää {name}?
|
||||
noLists: Sinulla ei ole listoja
|
||||
note: Lähetys
|
||||
notes: Lähetykset
|
||||
following: Seuraa
|
||||
createList: Luo lista
|
||||
manageLists: Hallitse listoja
|
||||
error: Virhe
|
||||
somethingHappened: On tapahtunut virhe
|
||||
retry: Yritä uudelleen
|
||||
pageLoadError: Virhe ladattaessa sivua.
|
||||
serverIsDead: Tämä palvelin ei vastaa. Yritä hetken kuluttua uudelleen.
|
||||
youShouldUpgradeClient: Nähdäksesi tämän sivun, virkistä päivittääksesi asiakasohjelmasi.
|
||||
privacy: Tietosuoja
|
||||
defaultNoteVisibility: Oletusnäkyvyys
|
||||
followRequest: Seuraajapyyntö
|
||||
followRequests: Seuraajapyynnöt
|
||||
unfollow: Poista seuraaminen
|
||||
enterEmoji: Syötä emoji
|
||||
renote: Buustaa
|
||||
renoted: Buustattu.
|
||||
cantRenote: Tätä lähetystä ei voi buustata.
|
||||
cantReRenote: Buustausta ei voi buustata.
|
||||
quote: Lainaus
|
||||
pinnedNote: Lukittu lähetys
|
||||
clickToShow: Napsauta nähdäksesi
|
||||
sensitive: Herkkää sisältöä (NSFW)
|
||||
add: Lisää
|
||||
enableEmojiReactions: Ota käyttöön emoji-reaktiot
|
||||
showEmojisInReactionNotifications: Näytä emojit reaktioilmoituksissa
|
||||
reactionSetting: Reaktiot näytettäväksi reaktiovalitsimessa
|
||||
rememberNoteVisibility: Muista lähetyksen näkyvyysasetukset
|
||||
markAsSensitive: Merkitse herkäksi sisällöksi (NSFW)
|
||||
unmarkAsSensitive: Poista merkintä herkkää sisältöä (NSFW)
|
||||
renoteMute: Hiljennä buustit
|
||||
renoteUnmute: Poista buustien hiljennys
|
||||
block: Estä
|
||||
unblock: Poista esto
|
||||
unsuspend: Poista keskeytys
|
||||
suspend: Keskeytys
|
||||
blockConfirm: Oletko varma, että haluat estää tämän tilin?
|
||||
unblockConfirm: Oletko varma, että haluat poistaa tämän tilin eston?
|
||||
selectAntenna: Valitse antenni
|
||||
selectWidget: Valitse vimpain
|
||||
editWidgets: Muokkaa vimpaimia
|
||||
editWidgetsExit: Valmis
|
||||
emoji: Emoji
|
||||
emojis: Emojit
|
||||
emojiName: Emojin nimi
|
||||
emojiUrl: Emojin URL-linkki
|
||||
cacheRemoteFiles: Taltioi etätiedostot välimuistiin
|
||||
flagAsBot: Merkitse tili botiksi
|
||||
flagAsBotDescription: Ota tämä vaihtoehto käyttöön, jos tätä tiliä ohjaa ohjelma.
|
||||
Jos se on käytössä, se toimii lippuna muille kehittäjille, jotta estetään loputtomat
|
||||
vuorovaikutusketjut muiden bottien kanssa ja säädetään Calckeyn sisäiset järjestelmät
|
||||
käsittelemään tätä tiliä botina.
|
||||
flagAsCat: Oletko kissa? 🐱
|
||||
flagAsCatDescription: Saat kissan korvat ja puhut kuin kissa!
|
||||
flagSpeakAsCat: Puhu kuin kissa
|
||||
flagShowTimelineReplies: Näytä vastaukset aikajanalla
|
||||
addAccount: Lisää tili
|
||||
loginFailed: Kirjautuminen epäonnistui
|
||||
showOnRemote: Katsele etäinstanssilla
|
||||
general: Yleistä
|
||||
accountMoved: 'Käyttäjä on muuttanut uuteen tiliin:'
|
||||
wallpaper: Taustakuva
|
||||
setWallpaper: Aseta taustakuva
|
||||
searchWith: 'Etsi: {q}'
|
||||
youHaveNoLists: Sinulla ei ole listoja
|
||||
followConfirm: Oletko varma, että haluat seurata käyttäjää {name}?
|
||||
host: Isäntä
|
||||
selectUser: Valitse käyttäjä
|
||||
annotation: Kommentit
|
||||
registeredAt: Rekisteröity
|
||||
latestRequestReceivedAt: Viimeisin pyyntö vastaanotettu
|
||||
latestRequestSentAt: Viimeisin pyyntö lähetetty
|
||||
storageUsage: Tallennustilan käyttö
|
||||
charts: Kaaviot
|
||||
stopActivityDelivery: Lopeta toimintojen lähettäminen
|
||||
blockThisInstance: Estä tämä instanssi
|
||||
operations: Toiminnot
|
||||
metadata: Metatieto
|
||||
monitor: Seuranta
|
||||
jobQueue: Työjono
|
||||
cpuAndMemory: Prosessori ja muisti
|
||||
network: Verkko
|
||||
disk: Levy
|
||||
clearCachedFiles: Tyhjennä välimuisti
|
||||
clearCachedFilesConfirm: Oletko varma, että haluat tyhjentää kaikki välimuistiin tallennetut
|
||||
etätiedostot?
|
||||
blockedInstances: Estetyt instanssit
|
||||
hiddenTags: Piilotetut asiatunnisteet
|
||||
mention: Maininta
|
||||
copyUsername: Kopioi käyttäjänimi
|
||||
searchUser: Etsi käyttäjää
|
||||
showLess: Sulje
|
||||
youGotNewFollower: seurasi sinua
|
||||
directNotes: Yksityisviestit
|
||||
driveFileDeleteConfirm: Oletko varma, että haluat poistaa tiedoston " {name}"? Lähetykset,
|
||||
jotka sisältyvät tiedostoon, poistuvat myös.
|
||||
importRequested: Olet pyytänyt viemistä. Tämä voi viedä hetken.
|
||||
exportRequested: Olet pyytänyt tuomista. Tämä voi viedä hetken. Se lisätään asemaan
|
||||
kun tuonti valmistuu.
|
||||
lists: Listat
|
||||
followers: Seuraajat
|
||||
followsYou: Seuraa sinua
|
||||
pageLoadErrorDescription: Tämä yleensä johtuu verkkovirheistä tai selaimen välimuistista.
|
||||
Kokeile tyhjentämällä välimuisti ja yritä sitten hetken kuluttua uudelleen.
|
||||
enterListName: Anna listalle nimi
|
||||
withNFiles: '{n} tiedosto(t)'
|
||||
instanceInfo: Instanssin tiedot
|
||||
clearQueue: Tyhjennä jono
|
||||
suspendConfirm: Oletko varma, että haluat keskeyttää tämän tilin?
|
||||
unsuspendConfirm: Oletko varma, että haluat poistaa tämän tilin keskeytyksen?
|
||||
selectList: Valitse lista
|
||||
customEmojis: Kustomoitu Emoji
|
||||
addEmoji: Lisää
|
||||
settingGuide: Suositellut asetukset
|
||||
cacheRemoteFilesDescription: Kun tämä asetus ei ole käytössä, etätiedostot on ladattu
|
||||
suoraan etäinstanssilta. Asetuksen poistaminen käytöstä vähentää tallennustilan
|
||||
käyttöä, mutta lisää verkkoliikennettä kun pienoiskuvat eivät muodostu.
|
||||
flagSpeakAsCatDescription: Lähetyksesi nyanifioidaan, kun olet kissatilassa
|
||||
flagShowTimelineRepliesDescription: Näyttää käyttäjien vastaukset muiden käyttäjien
|
||||
lähetyksiin aikajanalla, jos se on päällä.
|
||||
autoAcceptFollowed: Automaattisesti hyväksy seuraamispyynnöt käyttäjiltä, joita seuraat
|
||||
perHour: Tunnissa
|
||||
removeWallpaper: Poista taustakuva
|
||||
recipient: Vastaanottaja(t)
|
||||
federation: Federaatio
|
||||
software: Ohjelmisto
|
||||
proxyAccount: Proxy-tili
|
||||
proxyAccountDescription: Välitystili (Proxy-tili) on tili, joka toimii käyttäjien
|
||||
etäseuraajana tietyin edellytyksin. Kun käyttäjä esimerkiksi lisää etäkäyttäjän
|
||||
luetteloon, etäkäyttäjän toimintaa ei toimiteta instanssiin, jos yksikään paikallinen
|
||||
käyttäjä ei seuraa kyseistä käyttäjää, joten välitystili seuraa sen sijaan.
|
||||
latestStatus: Viimeisin tila
|
||||
selectInstance: Valitse instanssi
|
||||
instances: Instanssit
|
||||
perDay: Päivässä
|
||||
version: Versio
|
||||
statistics: Tilastot
|
||||
clearQueueConfirmTitle: Oletko varma, että haluat tyhjentää jonon?
|
||||
introMisskey: Tervetuloa! Calckey on avoimen lähdekoodin, hajautettu sosiaalisen median
|
||||
alusta, joka on ikuisesti ilmainen! 🚀
|
||||
clearQueueConfirmText: Mitkään välittämättömät lähetykset, jotka ovat jonossa, eivät
|
||||
federoidu. Yleensä tätä toimintoa ei tarvita.
|
||||
blockedInstancesDescription: Lista instanssien isäntänimistä, jotka haluat estää.
|
||||
Listatut instanssit eivät kykene kommunikoimaan enää tämän instanssin kanssa.
|
||||
_lang_: Suomi
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "calckey",
|
||||
"version": "13.2.0-dev40",
|
||||
"version": "13.2.0-dev41",
|
||||
"codename": "aqua",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -40,8 +40,6 @@
|
|||
"@bull-board/ui": "^4.10.2",
|
||||
"@napi-rs/cli": "^2.15.0",
|
||||
"@tensorflow/tfjs": "^3.21.0",
|
||||
"focus-trap": "^7.2.0",
|
||||
"focus-trap-vue": "^4.0.1",
|
||||
"js-yaml": "4.1.0",
|
||||
"seedrandom": "^3.0.5"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
export class LibreTranslate1682777547198 {
|
||||
name = "LibreTranslate1682777547198";
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiUrl" character varying(512)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiKey" character varying(128)
|
||||
`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiKey"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiUrl"
|
||||
`);
|
||||
}
|
||||
}
|
|
@ -89,6 +89,11 @@ export type Source = {
|
|||
authKey?: string;
|
||||
isPro?: boolean;
|
||||
};
|
||||
libreTranslate: {
|
||||
managed?: boolean;
|
||||
apiUrl?: string;
|
||||
apiKey?: string;
|
||||
};
|
||||
email: {
|
||||
managed?: boolean;
|
||||
address?: string;
|
||||
|
|
|
@ -386,6 +386,18 @@ export class Meta {
|
|||
})
|
||||
public deeplIsPro: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 128,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiKey: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
|
|
|
@ -30,6 +30,17 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
set.deeplIsPro = config.deepl.isPro;
|
||||
}
|
||||
}
|
||||
if (
|
||||
config.libreTranslate.managed != null &&
|
||||
config.libreTranslate.managed === true
|
||||
) {
|
||||
if (typeof config.libreTranslate.apiUrl === "string") {
|
||||
set.libreTranslateApiUrl = config.libreTranslate.apiUrl;
|
||||
}
|
||||
if (typeof config.libreTranslate.apiKey === "string") {
|
||||
set.libreTranslateApiKey = config.libreTranslate.apiKey;
|
||||
}
|
||||
}
|
||||
if (config.email.managed != null && config.email.managed === true) {
|
||||
set.enableEmail = true;
|
||||
if (typeof config.email.address === "string") {
|
||||
|
|
|
@ -512,7 +512,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
enableGithubIntegration: instance.enableGithubIntegration,
|
||||
enableDiscordIntegration: instance.enableDiscordIntegration,
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
pinnedPages: instance.pinnedPages,
|
||||
pinnedClipId: instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
|
@ -564,6 +565,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle,
|
||||
deeplAuthKey: instance.deeplAuthKey,
|
||||
deeplIsPro: instance.deeplIsPro,
|
||||
libreTranslateApiUrl: instance.libreTranslateApiUrl,
|
||||
libreTranslateApiKey: instance.libreTranslateApiKey,
|
||||
enableIpLogging: instance.enableIpLogging,
|
||||
enableActiveEmailValidation: instance.enableActiveEmailValidation,
|
||||
};
|
||||
|
|
|
@ -124,6 +124,8 @@ export const paramDef = {
|
|||
summalyProxy: { type: "string", nullable: true },
|
||||
deeplAuthKey: { type: "string", nullable: true },
|
||||
deeplIsPro: { type: "boolean" },
|
||||
libreTranslateApiUrl: { type: "string", nullable: true },
|
||||
libreTranslateApiKey: { type: "string", nullable: true },
|
||||
enableTwitterIntegration: { type: "boolean" },
|
||||
twitterConsumerKey: { type: "string", nullable: true },
|
||||
twitterConsumerSecret: { type: "string", nullable: true },
|
||||
|
@ -515,6 +517,22 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
set.deeplIsPro = ps.deeplIsPro;
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiUrl !== undefined) {
|
||||
if (ps.libreTranslateApiUrl === "") {
|
||||
set.libreTranslateApiUrl = null;
|
||||
} else {
|
||||
set.libreTranslateApiUrl = ps.libreTranslateApiUrl;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiKey !== undefined) {
|
||||
if (ps.libreTranslateApiKey === "") {
|
||||
set.libreTranslateApiKey = null;
|
||||
} else {
|
||||
set.libreTranslateApiKey = ps.libreTranslateApiKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableIpLogging !== undefined) {
|
||||
set.enableIpLogging = ps.enableIpLogging;
|
||||
}
|
||||
|
|
|
@ -482,7 +482,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
defaultReaction: instance.defaultReaction,
|
||||
|
||||
...(ps.detail
|
||||
|
|
|
@ -51,15 +51,54 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
|
||||
const instance = await fetchMeta();
|
||||
|
||||
if (instance.deeplAuthKey == null) {
|
||||
if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) {
|
||||
return 204; // TODO: 良い感じのエラー返す
|
||||
}
|
||||
|
||||
let targetLang = ps.targetLang;
|
||||
if (targetLang.includes("-")) targetLang = targetLang.split("-")[0];
|
||||
|
||||
if (instance.libreTranslateApiUrl != null) {
|
||||
const jsonBody = {
|
||||
q: note.text,
|
||||
source: "auto",
|
||||
target: targetLang,
|
||||
format: "text",
|
||||
api_key: instance.libreTranslateApiKey ?? "",
|
||||
};
|
||||
|
||||
const url = new URL(instance.libreTranslateApiUrl);
|
||||
if (url.pathname.endsWith("/")) {
|
||||
url.pathname = url.pathname.slice(0, -1);
|
||||
}
|
||||
if (!url.pathname.endsWith("/translate")) {
|
||||
url.pathname += "/translate";
|
||||
}
|
||||
const res = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(jsonBody),
|
||||
agent: getAgentByUrl,
|
||||
});
|
||||
|
||||
const json = (await res.json()) as {
|
||||
detectedLanguage?: {
|
||||
confidence: number;
|
||||
language: string;
|
||||
};
|
||||
translatedText: string;
|
||||
};
|
||||
|
||||
return {
|
||||
sourceLang: json.detectedLanguage?.language,
|
||||
text: json.translatedText,
|
||||
};
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append("auth_key", instance.deeplAuthKey);
|
||||
params.append("auth_key", instance.deeplAuthKey ?? "");
|
||||
params.append("text", note.text);
|
||||
params.append("target_lang", targetLang);
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
node_modules
|
||||
/built
|
||||
/coverage
|
||||
/.eslintrc.js
|
||||
/jest.config.ts
|
||||
/test
|
||||
/test-d
|
|
@ -1,65 +0,0 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ["./tsconfig.json"],
|
||||
},
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
rules: {
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
SwitchCase: 1,
|
||||
MemberExpression: "off",
|
||||
flatTernaryExpressions: true,
|
||||
ArrayExpression: "first",
|
||||
ObjectExpression: "first",
|
||||
},
|
||||
],
|
||||
"eol-last": ["error", "always"],
|
||||
semi: ["error", "always"],
|
||||
quotes: ["error", "single"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"keyword-spacing": [
|
||||
"error",
|
||||
{
|
||||
before: true,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
"key-spacing": [
|
||||
"error",
|
||||
{
|
||||
beforeColon: false,
|
||||
afterColon: true,
|
||||
},
|
||||
],
|
||||
"space-infix-ops": ["error"],
|
||||
"space-before-blocks": ["error", "always"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"nonblock-statement-body-position": ["error", "beside"],
|
||||
eqeqeq: ["error", "always", { null: "ignore" }],
|
||||
"no-multiple-empty-lines": ["error", { max: 1 }],
|
||||
"no-multi-spaces": ["error"],
|
||||
"no-var": ["error"],
|
||||
"prefer-arrow-callback": ["error"],
|
||||
"no-throw-literal": ["error"],
|
||||
"no-param-reassign": ["warn"],
|
||||
"no-constant-condition": ["warn"],
|
||||
"no-empty-pattern": ["warn"],
|
||||
"@typescript-eslint/no-unnecessary-condition": ["error"],
|
||||
"@typescript-eslint/no-inferrable-types": ["warn"],
|
||||
"@typescript-eslint/no-non-null-assertion": ["warn"],
|
||||
"@typescript-eslint/explicit-function-return-type": ["warn"],
|
||||
"@typescript-eslint/no-misused-promises": [
|
||||
"error",
|
||||
{
|
||||
checksVoidReturn: false,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
},
|
||||
};
|
|
@ -9,9 +9,8 @@
|
|||
"tsd": "tsd",
|
||||
"api": "pnpm api-extractor run --local --verbose",
|
||||
"api-prod": "pnpm api-extractor run --verbose",
|
||||
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
"lint": "pnpm typecheck && pnpm rome check \"src/*.ts\"",
|
||||
"jest": "jest --coverage --detectOpenHandles",
|
||||
"test": "pnpm jest && pnpm tsd"
|
||||
},
|
||||
|
|
|
@ -195,7 +195,8 @@ function onMousedown(evt: MouseEvent): void {
|
|||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: auto;
|
||||
outline: solid 2px var(--focus);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&.inline {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
<button
|
||||
ref="el"
|
||||
class="_button"
|
||||
:class="{ showLess: modelValue, fade: !modelValue }"
|
||||
@click.stop="toggle"
|
||||
|
@ -13,7 +12,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { computed } from "vue";
|
||||
import { length } from "stringz";
|
||||
import * as misskey from "calckey-js";
|
||||
import { concat } from "@/scripts/array";
|
||||
|
@ -28,8 +27,6 @@ const emit = defineEmits<{
|
|||
(ev: "update:modelValue", v: boolean): void;
|
||||
}>();
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
|
||||
const label = computed(() => {
|
||||
return concat([
|
||||
props.note.text
|
||||
|
@ -46,14 +43,6 @@ const label = computed(() => {
|
|||
const toggle = () => {
|
||||
emit("update:modelValue", !props.modelValue);
|
||||
};
|
||||
|
||||
function focus() {
|
||||
el.value.focus();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
focus
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -73,7 +62,7 @@ defineExpose({
|
|||
}
|
||||
}
|
||||
}
|
||||
&:hover > span, &:focus > span {
|
||||
&:hover > span {
|
||||
background: var(--cwFg) !important;
|
||||
color: var(--cwBg) !important;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<button ref="thumbnail" class="zdjebgpv">
|
||||
<div ref="thumbnail" class="zdjebgpv">
|
||||
<ImgWithBlurhash
|
||||
v-if="isThumbnailAvailable"
|
||||
:hash="file.blurhash"
|
||||
|
@ -36,7 +36,7 @@
|
|||
v-if="isThumbnailAvailable && is === 'video'"
|
||||
class="ph-file-video ph-bold ph-lg icon-sub"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -88,9 +88,6 @@ const isThumbnailAvailable = computed(() => {
|
|||
background: var(--panel);
|
||||
border-radius: 8px;
|
||||
overflow: clip;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
> .icon-sub {
|
||||
position: absolute;
|
||||
|
|
|
@ -1,160 +1,157 @@
|
|||
<template>
|
||||
<FocusTrap v-bind:active="isActive">
|
||||
<div
|
||||
class="omfetrab"
|
||||
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
||||
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
||||
tabindex="-1"
|
||||
>
|
||||
<input
|
||||
ref="search"
|
||||
v-model.trim="q"
|
||||
class="search"
|
||||
data-prevent-emoji-insert
|
||||
:class="{ filled: q != null && q != '' }"
|
||||
:placeholder="i18n.ts.search"
|
||||
type="search"
|
||||
@paste.stop="paste"
|
||||
@keyup.enter="done()"
|
||||
/>
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0" class="body">
|
||||
<div
|
||||
class="omfetrab"
|
||||
:class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]"
|
||||
:style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
|
||||
>
|
||||
<input
|
||||
ref="search"
|
||||
v-model.trim="q"
|
||||
class="search"
|
||||
data-prevent-emoji-insert
|
||||
:class="{ filled: q != null && q != '' }"
|
||||
:placeholder="i18n.ts.search"
|
||||
type="search"
|
||||
@paste.stop="paste"
|
||||
@keyup.enter="done()"
|
||||
/>
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultCustom"
|
||||
:key="emoji.id"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||
<img
|
||||
class="emoji"
|
||||
:src="
|
||||
disableShowingAnimatedImages
|
||||
? getStaticImageUrl(emoji.url)
|
||||
: emoji.url
|
||||
"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultUnicode"
|
||||
:key="emoji.name"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji class="emoji" :emoji="emoji.char" />
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div v-if="tab === 'index'" class="group index">
|
||||
<section v-if="showPinned">
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultCustom"
|
||||
:key="emoji.id"
|
||||
v-for="emoji in pinned"
|
||||
:key="emoji"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||
<img
|
||||
<MkEmoji
|
||||
class="emoji"
|
||||
:src="
|
||||
disableShowingAnimatedImages
|
||||
? getStaticImageUrl(emoji.url)
|
||||
: emoji.url
|
||||
"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultUnicode"
|
||||
:key="emoji.name"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji class="emoji" :emoji="emoji.char" />
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div v-if="tab === 'index'" class="group index">
|
||||
<section v-if="showPinned">
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in pinned"
|
||||
:key="emoji"
|
||||
class="_button item"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji
|
||||
class="emoji"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<header class="_acrylic">
|
||||
<i class="ph-alarm ph-bold ph-fw ph-lg"></i>
|
||||
{{ i18n.ts.recentUsed }}
|
||||
</header>
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in recentlyUsedEmojis"
|
||||
:key="emoji"
|
||||
class="_button item"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji
|
||||
class="emoji"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div v-once class="group">
|
||||
<header>{{ i18n.ts.customEmojis }}</header>
|
||||
<XSection
|
||||
v-for="category in customEmojiCategories"
|
||||
:key="'custom:' + category"
|
||||
:initial-shown="false"
|
||||
:emojis="
|
||||
customEmojis
|
||||
.filter((e) => e.category === category)
|
||||
.map((e) => ':' + e.name + ':')
|
||||
"
|
||||
@chosen="chosen"
|
||||
>{{ category || i18n.ts.other }}</XSection
|
||||
>
|
||||
</div>
|
||||
<div v-once class="group">
|
||||
<header>{{ i18n.ts.emoji }}</header>
|
||||
<XSection
|
||||
v-for="category in categories"
|
||||
:key="category"
|
||||
:emojis="
|
||||
emojilist
|
||||
.filter((e) => e.category === category)
|
||||
.map((e) => e.char)
|
||||
"
|
||||
@chosen="chosen"
|
||||
>{{ category }}</XSection
|
||||
>
|
||||
</div>
|
||||
<section>
|
||||
<header class="_acrylic">
|
||||
<i class="ph-alarm ph-bold ph-fw ph-lg"></i>
|
||||
{{ i18n.ts.recentUsed }}
|
||||
</header>
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in recentlyUsedEmojis"
|
||||
:key="emoji"
|
||||
class="_button item"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji
|
||||
class="emoji"
|
||||
:emoji="emoji"
|
||||
:normal="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'index' }"
|
||||
@click="tab = 'index'"
|
||||
<div v-once class="group">
|
||||
<header>{{ i18n.ts.customEmojis }}</header>
|
||||
<XSection
|
||||
v-for="category in customEmojiCategories"
|
||||
:key="'custom:' + category"
|
||||
:initial-shown="false"
|
||||
:emojis="
|
||||
customEmojis
|
||||
.filter((e) => e.category === category)
|
||||
.map((e) => ':' + e.name + ':')
|
||||
"
|
||||
@chosen="chosen"
|
||||
>{{ category || i18n.ts.other }}</XSection
|
||||
>
|
||||
<i class="ph-asterisk ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'custom' }"
|
||||
@click="tab = 'custom'"
|
||||
</div>
|
||||
<div v-once class="group">
|
||||
<header>{{ i18n.ts.emoji }}</header>
|
||||
<XSection
|
||||
v-for="category in categories"
|
||||
:key="category"
|
||||
:emojis="
|
||||
emojilist
|
||||
.filter((e) => e.category === category)
|
||||
.map((e) => e.char)
|
||||
"
|
||||
@chosen="chosen"
|
||||
>{{ category }}</XSection
|
||||
>
|
||||
<i class="ph-smiley ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'unicode' }"
|
||||
@click="tab = 'unicode'"
|
||||
>
|
||||
<i class="ph-leaf ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'tags' }"
|
||||
@click="tab = 'tags'"
|
||||
>
|
||||
<i class="ph-hash ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
<div class="tabs">
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'index' }"
|
||||
@click="tab = 'index'"
|
||||
>
|
||||
<i class="ph-asterisk ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'custom' }"
|
||||
@click="tab = 'custom'"
|
||||
>
|
||||
<i class="ph-smiley ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'unicode' }"
|
||||
@click="tab = 'unicode'"
|
||||
>
|
||||
<i class="ph-leaf ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="_button tab"
|
||||
:class="{ active: tab === 'tags' }"
|
||||
@click="tab = 'tags'"
|
||||
>
|
||||
<i class="ph-hash ph-bold ph-lg ph-fw ph-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -174,7 +171,6 @@ import { deviceKind } from "@/scripts/device-kind";
|
|||
import { emojiCategories, instance } from "@/instance";
|
||||
import { i18n } from "@/i18n";
|
||||
import { defaultStore } from "@/store";
|
||||
import { FocusTrap } from 'focus-trap-vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
|
|
@ -139,7 +139,7 @@ function close() {
|
|||
height: 100px;
|
||||
border-radius: 10px;
|
||||
|
||||
&:hover, &:focus-visible {
|
||||
&:hover {
|
||||
color: var(--accent);
|
||||
background: var(--accentedBg);
|
||||
text-decoration: none;
|
||||
|
|
|
@ -138,10 +138,6 @@ watch(
|
|||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
box-sizing: border-box;
|
||||
&:focus-visible {
|
||||
border: 2px solid var(--accent);
|
||||
}
|
||||
|
||||
> .gif {
|
||||
background-color: var(--fg);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div ref="el" class="sfhdhdhr" tabindex="-1">
|
||||
<MkMenu
|
||||
ref="menu"
|
||||
:items="items"
|
||||
:align="align"
|
||||
:width="width"
|
||||
:as-drawer="false"
|
||||
@close="onChildClosed"
|
||||
/>
|
||||
</div>
|
||||
<div ref="el" class="sfhdhdhr">
|
||||
<MkMenu
|
||||
ref="menu"
|
||||
:items="items"
|
||||
:align="align"
|
||||
:width="width"
|
||||
:as-drawer="false"
|
||||
@close="onChildClosed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -23,6 +23,7 @@ import {
|
|||
} from "vue";
|
||||
import MkMenu from "./MkMenu.vue";
|
||||
import { MenuItem } from "@/types/menu";
|
||||
import * as os from "@/os";
|
||||
|
||||
const props = defineProps<{
|
||||
items: MenuItem[];
|
||||
|
|
|
@ -1,188 +1,191 @@
|
|||
<template>
|
||||
<FocusTrap v-bind:active="isActive">
|
||||
<div tabindex="-1" v-focus>
|
||||
<div
|
||||
ref="itemsEl"
|
||||
class="rrevdjwt _popup _shadow"
|
||||
:class="{ center: align === 'center', asDrawer }"
|
||||
:style="{
|
||||
width: width && !asDrawer ? width + 'px' : '',
|
||||
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
||||
}"
|
||||
@contextmenu.self="(e) => e.preventDefault()"
|
||||
>
|
||||
<template v-for="(item, i) in items2">
|
||||
<div v-if="item === null" class="divider"></div>
|
||||
<span v-else-if="item.type === 'label'" class="label item">
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
</span>
|
||||
<span
|
||||
v-else-if="item.type === 'pending'"
|
||||
class="pending item"
|
||||
>
|
||||
<span><MkEllipsis /></span>
|
||||
</span>
|
||||
<MkA
|
||||
v-else-if="item.type === 'link'"
|
||||
:to="item.to"
|
||||
class="_button item"
|
||||
@click.passive="close(true)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<MkAvatar
|
||||
v-if="item.avatar"
|
||||
:user="item.avatar"
|
||||
class="avatar"
|
||||
disableLink
|
||||
/>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</MkA>
|
||||
<a
|
||||
v-else-if="item.type === 'a'"
|
||||
:href="item.href"
|
||||
:target="item.target"
|
||||
:download="item.download"
|
||||
class="_button item"
|
||||
@click="close(true)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</a>
|
||||
<button
|
||||
v-else-if="item.type === 'user' && !items.hidden"
|
||||
class="_button item"
|
||||
:class="{ active: item.active }"
|
||||
:disabled="item.active"
|
||||
@click="clicked(item.action, $event)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<MkAvatar :user="item.user" class="avatar" disableLink /><MkUserName
|
||||
:user="item.user"
|
||||
/>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</button>
|
||||
<span
|
||||
v-else-if="item.type === 'switch'"
|
||||
class="item"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<FormSwitch
|
||||
v-model="item.ref"
|
||||
:disabled="item.disabled"
|
||||
class="form-switch"
|
||||
:style="item.textStyle || ''"
|
||||
>{{ item.text }}</FormSwitch
|
||||
>
|
||||
</span>
|
||||
<button
|
||||
v-else-if="item.type === 'parent'"
|
||||
class="_button item parent"
|
||||
:class="{ childShowing: childShowingItem === item }"
|
||||
@mouseenter="showChildren(item, $event)"
|
||||
@click="showChildren(item, $event)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span class="caret"
|
||||
><i class="ph-caret-right ph-bold ph-lg ph-fw ph-lg"></i
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
v-else-if="!item.hidden"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
:disabled="item.active"
|
||||
@click="clicked(item.action, $event)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<MkAvatar
|
||||
v-if="item.avatar"
|
||||
:user="item.avatar"
|
||||
class="avatar"
|
||||
disableLink
|
||||
/>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</button>
|
||||
</template>
|
||||
<span v-if="items2.length === 0" class="none item">
|
||||
<span>{{ i18n.ts.none }}</span>
|
||||
<div>
|
||||
<div
|
||||
ref="itemsEl"
|
||||
v-hotkey="keymap"
|
||||
class="rrevdjwt _popup _shadow"
|
||||
:class="{ center: align === 'center', asDrawer }"
|
||||
:style="{
|
||||
width: width && !asDrawer ? width + 'px' : '',
|
||||
maxHeight: maxHeight ? maxHeight + 'px' : '',
|
||||
}"
|
||||
@contextmenu.self="(e) => e.preventDefault()"
|
||||
>
|
||||
<template v-for="(item, i) in items2">
|
||||
<div v-if="item === null" class="divider"></div>
|
||||
<span v-else-if="item.type === 'label'" class="label item">
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="childMenu" class="child">
|
||||
<XChild
|
||||
ref="child"
|
||||
:items="childMenu"
|
||||
:target-element="childTarget"
|
||||
:root-element="itemsEl"
|
||||
showing
|
||||
@actioned="childActioned"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
v-else-if="item.type === 'pending'"
|
||||
:tabindex="i"
|
||||
class="pending item"
|
||||
>
|
||||
<span><MkEllipsis /></span>
|
||||
</span>
|
||||
<MkA
|
||||
v-else-if="item.type === 'link'"
|
||||
:to="item.to"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
@click.passive="close(true)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<MkAvatar
|
||||
v-if="item.avatar"
|
||||
:user="item.avatar"
|
||||
class="avatar"
|
||||
/>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</MkA>
|
||||
<a
|
||||
v-else-if="item.type === 'a'"
|
||||
:href="item.href"
|
||||
:target="item.target"
|
||||
:download="item.download"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
@click="close(true)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</a>
|
||||
<button
|
||||
v-else-if="item.type === 'user' && !items.hidden"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
:class="{ active: item.active }"
|
||||
:disabled="item.active"
|
||||
@click="clicked(item.action, $event)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<MkAvatar :user="item.user" class="avatar" /><MkUserName
|
||||
:user="item.user"
|
||||
/>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</button>
|
||||
<span
|
||||
v-else-if="item.type === 'switch'"
|
||||
:tabindex="i"
|
||||
class="item"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<FormSwitch
|
||||
v-model="item.ref"
|
||||
:disabled="item.disabled"
|
||||
class="form-switch"
|
||||
:style="item.textStyle || ''"
|
||||
>{{ item.text }}</FormSwitch
|
||||
>
|
||||
</span>
|
||||
<button
|
||||
v-else-if="item.type === 'parent'"
|
||||
:tabindex="i"
|
||||
class="_button item parent"
|
||||
:class="{ childShowing: childShowingItem === item }"
|
||||
@mouseenter="showChildren(item, $event)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span class="caret"
|
||||
><i class="ph-caret-right ph-bold ph-lg ph-fw ph-lg"></i
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
v-else-if="!item.hidden"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
:disabled="item.active"
|
||||
@click="clicked(item.action, $event)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
@mouseleave.passive="onItemMouseLeave(item)"
|
||||
>
|
||||
<i
|
||||
v-if="item.icon"
|
||||
class="ph-fw ph-lg"
|
||||
:class="item.icon"
|
||||
></i>
|
||||
<span v-else-if="item.icons">
|
||||
<i
|
||||
v-for="icon in item.icons"
|
||||
class="ph-fw ph-lg"
|
||||
:class="icon"
|
||||
></i>
|
||||
</span>
|
||||
<MkAvatar
|
||||
v-if="item.avatar"
|
||||
:user="item.avatar"
|
||||
class="avatar"
|
||||
/>
|
||||
<span :style="item.textStyle || ''">{{ item.text }}</span>
|
||||
<span v-if="item.indicate" class="indicator"
|
||||
><i class="ph-circle ph-fill"></i
|
||||
></span>
|
||||
</button>
|
||||
</template>
|
||||
<span v-if="items2.length === 0" class="none item">
|
||||
<span>{{ i18n.ts.none }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
<div v-if="childMenu" class="child">
|
||||
<XChild
|
||||
ref="child"
|
||||
:items="childMenu"
|
||||
:target-element="childTarget"
|
||||
:root-element="itemsEl"
|
||||
showing
|
||||
@actioned="childActioned"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -203,7 +206,6 @@ import FormSwitch from "@/components/form/switch.vue";
|
|||
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from "@/types/menu";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { FocusTrap } from 'focus-trap-vue';
|
||||
|
||||
const XChild = defineAsyncComponent(() => import("./MkMenu.child.vue"));
|
||||
|
||||
|
@ -226,6 +228,12 @@ let items2: InnerMenuItem[] = $ref([]);
|
|||
|
||||
let child = $ref<InstanceType<typeof XChild>>();
|
||||
|
||||
let keymap = computed(() => ({
|
||||
"up|k|shift+tab": focusUp,
|
||||
"down|j|tab": focusDown,
|
||||
esc: close,
|
||||
}));
|
||||
|
||||
let childShowingItem = $ref<MenuItem | null>();
|
||||
|
||||
watch(
|
||||
|
@ -356,7 +364,8 @@ onBeforeUnmount(() => {
|
|||
font-size: 0.9em;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
|
@ -380,7 +389,7 @@ onBeforeUnmount(() => {
|
|||
transform: translateY(0em);
|
||||
}
|
||||
|
||||
&:not(:disabled):hover, &:focus-visible {
|
||||
&:not(:disabled):hover {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
|
||||
|
@ -388,9 +397,6 @@ onBeforeUnmount(() => {
|
|||
background: var(--accentedBg);
|
||||
}
|
||||
}
|
||||
&:focus-visible:before {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
&.danger {
|
||||
color: #eb6f92;
|
||||
|
|
|
@ -14,59 +14,54 @@
|
|||
:duration="transitionDuration"
|
||||
appear
|
||||
@after-leave="emit('closed')"
|
||||
@keyup.esc="emit('click')"
|
||||
@enter="emit('opening')"
|
||||
@after-enter="onOpened"
|
||||
>
|
||||
<FocusTrap v-model:active="isActive">
|
||||
<div
|
||||
v-show="manualShowing != null ? manualShowing : showing"
|
||||
v-hotkey.global="keymap"
|
||||
:class="[
|
||||
$style.root,
|
||||
{
|
||||
[$style.drawer]: type === 'drawer',
|
||||
[$style.dialog]: type === 'dialog' || type === 'dialog:top',
|
||||
[$style.popup]: type === 'popup',
|
||||
},
|
||||
]"
|
||||
:style="{
|
||||
zIndex,
|
||||
pointerEvents: (manualShowing != null ? manualShowing : showing)
|
||||
? 'auto'
|
||||
: 'none',
|
||||
'--transformOrigin': transformOrigin,
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-show="manualShowing != null ? manualShowing : showing"
|
||||
v-hotkey.global="keymap"
|
||||
class="_modalBg data-cy-bg"
|
||||
:class="[
|
||||
$style.root,
|
||||
$style.bg,
|
||||
{
|
||||
[$style.drawer]: type === 'drawer',
|
||||
[$style.dialog]: type === 'dialog' || type === 'dialog:top',
|
||||
[$style.popup]: type === 'popup',
|
||||
[$style.bgTransparent]: isEnableBgTransparent,
|
||||
'data-cy-transparent': isEnableBgTransparent,
|
||||
},
|
||||
]"
|
||||
:style="{
|
||||
zIndex,
|
||||
pointerEvents: (manualShowing != null ? manualShowing : showing)
|
||||
? 'auto'
|
||||
: 'none',
|
||||
'--transformOrigin': transformOrigin,
|
||||
}"
|
||||
tabindex="-1"
|
||||
v-focus
|
||||
:style="{ zIndex }"
|
||||
@click="onBgClick"
|
||||
@mousedown="onBgClick"
|
||||
@contextmenu.prevent.stop="() => {}"
|
||||
></div>
|
||||
<div
|
||||
ref="content"
|
||||
:class="[
|
||||
$style.content,
|
||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
||||
]"
|
||||
:style="{ zIndex }"
|
||||
@click.self="onBgClick"
|
||||
>
|
||||
<div
|
||||
class="_modalBg data-cy-bg"
|
||||
:class="[
|
||||
$style.bg,
|
||||
{
|
||||
[$style.bgTransparent]: isEnableBgTransparent,
|
||||
'data-cy-transparent': isEnableBgTransparent,
|
||||
},
|
||||
]"
|
||||
:style="{ zIndex }"
|
||||
@click="onBgClick"
|
||||
@mousedown="onBgClick"
|
||||
@contextmenu.prevent.stop="() => {}"
|
||||
></div>
|
||||
<div
|
||||
ref="content"
|
||||
:class="[
|
||||
$style.content,
|
||||
{ [$style.fixed]: fixed, top: type === 'dialog:top' },
|
||||
]"
|
||||
:style="{ zIndex }"
|
||||
@click.self="onBgClick"
|
||||
>
|
||||
<slot :max-height="maxHeight" :type="type"></slot>
|
||||
</div>
|
||||
<slot :max-height="maxHeight" :type="type"></slot>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
|
@ -76,7 +71,6 @@ import * as os from "@/os";
|
|||
import { isTouchUsing } from "@/scripts/touch";
|
||||
import { defaultStore } from "@/store";
|
||||
import { deviceKind } from "@/scripts/device-kind";
|
||||
import { FocusTrap } from 'focus-trap-vue';
|
||||
|
||||
function getFixedContainer(el: Element | null): Element | null {
|
||||
if (el == null || el.tagName === "BODY") return null;
|
||||
|
@ -172,7 +166,6 @@ let transitionDuration = $computed(() =>
|
|||
|
||||
let contentClicking = false;
|
||||
|
||||
const focusedElement = document.activeElement;
|
||||
function close(opts: { useSendAnimation?: boolean } = {}) {
|
||||
if (opts.useSendAnimation) {
|
||||
useSendAnime = true;
|
||||
|
@ -182,12 +175,10 @@ function close(opts: { useSendAnimation?: boolean } = {}) {
|
|||
if (props.src) props.src.style.pointerEvents = "auto";
|
||||
showing = false;
|
||||
emit("close");
|
||||
focusedElement.focus();
|
||||
}
|
||||
|
||||
function onBgClick() {
|
||||
if (contentClicking) return;
|
||||
focusedElement.focus();
|
||||
emit("click");
|
||||
}
|
||||
|
||||
|
@ -490,7 +481,6 @@ defineExpose({
|
|||
}
|
||||
|
||||
.root {
|
||||
outline: none;
|
||||
&.dialog {
|
||||
> .content {
|
||||
position: fixed;
|
||||
|
|
|
@ -158,7 +158,6 @@ function onContextmenu(ev: MouseEvent) {
|
|||
flex-direction: column;
|
||||
contain: content;
|
||||
border-radius: var(--radius);
|
||||
margin: auto;
|
||||
|
||||
--root-margin: 24px;
|
||||
|
||||
|
|
|
@ -3,64 +3,59 @@
|
|||
ref="modal"
|
||||
:prefer-type="'dialog'"
|
||||
@click="onBgClick"
|
||||
@keyup.esc="$emit('close')"
|
||||
@closed="$emit('closed')"
|
||||
>
|
||||
<FocusTrap v-model:active="isActive">
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="ebkgoccj"
|
||||
:style="{
|
||||
width: `${width}px`,
|
||||
height: scroll
|
||||
? height
|
||||
? `${height}px`
|
||||
: null
|
||||
: height
|
||||
? `min(${height}px, 100%)`
|
||||
: '100%',
|
||||
}"
|
||||
@keydown="onKeydown"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div ref="headerEl" class="header">
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<span class="title">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<button
|
||||
v-if="!withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
:disabled="okButtonDisabled"
|
||||
@click="$emit('ok')"
|
||||
>
|
||||
<i class="ph-check ph-bold ph-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="body">
|
||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||
</div>
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="ebkgoccj"
|
||||
:style="{
|
||||
width: `${width}px`,
|
||||
height: scroll
|
||||
? height
|
||||
? `${height}px`
|
||||
: null
|
||||
: height
|
||||
? `min(${height}px, 100%)`
|
||||
: '100%',
|
||||
}"
|
||||
@keydown="onKeydown"
|
||||
>
|
||||
<div ref="headerEl" class="header">
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<span class="title">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<button
|
||||
v-if="!withOkButton"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="ph-x ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
class="_button"
|
||||
:disabled="okButtonDisabled"
|
||||
@click="$emit('ok')"
|
||||
>
|
||||
<i class="ph-check ph-bold ph-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
<div class="body">
|
||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted } from "vue";
|
||||
import { FocusTrap } from 'focus-trap-vue';
|
||||
import MkModal from "./MkModal.vue";
|
||||
|
||||
const props = withDefaults(
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
:detailedView="detailedView"
|
||||
:parentId="appearNote.parentId"
|
||||
@push="(e) => router.push(notePage(e))"
|
||||
@focusfooter="footerEl.focus()"
|
||||
></MkSubNoteContent>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
<MkLoading v-if="translating" mini />
|
||||
|
@ -118,7 +117,7 @@
|
|||
<MkTime :time="appearNote.createdAt" mode="absolute" />
|
||||
</MkA>
|
||||
</div>
|
||||
<footer ref="footerEl" class="footer" @click.stop tabindex="-1">
|
||||
<footer ref="el" class="footer" @click.stop>
|
||||
<XReactionsViewer
|
||||
v-if="enableEmojiReactions"
|
||||
ref="reactionsViewer"
|
||||
|
@ -279,7 +278,6 @@ const isRenote =
|
|||
note.poll == null;
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const footerEl = ref<HTMLElement>();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||
|
@ -300,8 +298,8 @@ const keymap = {
|
|||
r: () => reply(true),
|
||||
"e|a|plus": () => react(true),
|
||||
q: () => renoteButton.value.renote(true),
|
||||
"up|k": focusBefore,
|
||||
"down|j": focusAfter,
|
||||
"up|k|shift+tab": focusBefore,
|
||||
"down|j|tab": focusAfter,
|
||||
esc: blur,
|
||||
"m|o": () => menu(true),
|
||||
s: () => showContent.value !== showContent.value,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div v-size="{ min: [350, 500] }" class="fefdfafb">
|
||||
<MkAvatar class="avatar" :user="$i" disableLink />
|
||||
<MkAvatar class="avatar" :user="$i" />
|
||||
<div class="main">
|
||||
<div class="header">
|
||||
<MkUserName :user="$i" />
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
:note="note"
|
||||
:parentId="appearNote.parentId"
|
||||
:conversation="conversation"
|
||||
@focusfooter="footerEl.focus()"
|
||||
/>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
<MkLoading v-if="translating" mini />
|
||||
|
@ -47,7 +46,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer ref="footerEl" class="footer" @click.stop tabindex="-1">
|
||||
<footer class="footer" @click.stop>
|
||||
<XReactionsViewer
|
||||
v-if="enableEmojiReactions"
|
||||
ref="reactionsViewer"
|
||||
|
@ -213,7 +212,6 @@ const isRenote =
|
|||
note.poll == null;
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const footerEl = ref<HTMLElement>();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
:transparent-bg="true"
|
||||
@click="modal.close()"
|
||||
@closed="emit('closed')"
|
||||
tabindex="-1"
|
||||
v-focus
|
||||
>
|
||||
<MkMenu
|
||||
:items="items"
|
||||
|
|
|
@ -198,6 +198,7 @@ export default defineComponent({
|
|||
height: 64px;
|
||||
margin-right: 4px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
|
||||
&:hover > .remove {
|
||||
|
|
|
@ -35,11 +35,7 @@
|
|||
class="content"
|
||||
:class="{ collapsed, isLong, showContent: note.cw && !showContent }"
|
||||
>
|
||||
<XCwButton ref="cwButton" v-if="note.cw && !showContent" v-model="showContent" :note="note" v-on:keydown="focusFooter" />
|
||||
<div
|
||||
class="body"
|
||||
v-bind="{ 'aria-label': !showContent ? '' : null, 'tabindex': !showContent ? '-1' : null }"
|
||||
>
|
||||
<div class="body">
|
||||
<span v-if="note.deletedAt" style="opacity: 0.5"
|
||||
>({{ i18n.ts.deleted }})</span
|
||||
>
|
||||
|
@ -100,11 +96,6 @@
|
|||
<XNoteSimple :note="note.renote" />
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="note.cw && !showContent"
|
||||
tabindex="0"
|
||||
v-on:focus="cwButton?.focus()"
|
||||
></div>
|
||||
</div>
|
||||
<button
|
||||
v-if="isLong && collapsed"
|
||||
|
@ -126,7 +117,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import {} from "vue";
|
||||
import * as misskey from "calckey-js";
|
||||
import * as mfm from "mfm-js";
|
||||
import XNoteSimple from "@/components/MkNoteSimple.vue";
|
||||
|
@ -147,10 +138,8 @@ const props = defineProps<{
|
|||
|
||||
const emit = defineEmits<{
|
||||
(ev: "push", v): void;
|
||||
(ev: "focusfooter"): void;
|
||||
}>();
|
||||
|
||||
const cwButton = ref<HTMLElement>();
|
||||
const isLong =
|
||||
!props.detailedView &&
|
||||
props.note.cw == null &&
|
||||
|
@ -162,13 +151,6 @@ const urls = props.note.text
|
|||
: null;
|
||||
|
||||
let showContent = $ref(false);
|
||||
|
||||
|
||||
function focusFooter(ev) {
|
||||
if (ev.key == "Tab" && !ev.getModifierState("Shift")) {
|
||||
emit("focusfooter");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -260,9 +242,6 @@ function focusFooter(ev) {
|
|||
margin-top: -50px;
|
||||
padding-top: 50px;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
&.collapsed > .body {
|
||||
box-sizing: border-box;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
v-if="item.type === 'a'"
|
||||
:href="item.href"
|
||||
:target="item.target"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
>
|
||||
|
@ -21,6 +22,7 @@
|
|||
</a>
|
||||
<button
|
||||
v-else-if="item.type === 'button'"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
:disabled="item.active"
|
||||
|
@ -36,6 +38,7 @@
|
|||
<MkA
|
||||
v-else
|
||||
:to="item.to"
|
||||
:tabindex="i"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
>
|
||||
|
@ -96,7 +99,7 @@ export default defineComponent({
|
|||
font-size: 0.9em;
|
||||
margin-bottom: 0.3rem;
|
||||
|
||||
&:hover, &:focus-visible {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
background: var(--panelHighlight);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
:user="user"
|
||||
class="avatar"
|
||||
:show-indicator="true"
|
||||
disableLink
|
||||
/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name" />
|
||||
|
@ -74,7 +73,6 @@
|
|||
:user="user"
|
||||
class="avatar"
|
||||
:show-indicator="true"
|
||||
disableLink
|
||||
/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name" />
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
>
|
||||
<div class="beaffaef">
|
||||
<div v-for="u in users" :key="u.id" class="user">
|
||||
<MkAvatar class="avatar" :user="u" disableLink />
|
||||
<MkAvatar class="avatar" :user="u" />
|
||||
<MkUserName class="name" :user="u" :nowrap="true" />
|
||||
</div>
|
||||
<div v-if="users.length < count" class="omitted">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="vjoppmmu">
|
||||
<template v-if="edit">
|
||||
<header tabindex="-1" v-focus>
|
||||
<header>
|
||||
<MkSelect
|
||||
v-model="widgetAdderSelected"
|
||||
style="margin-bottom: var(--margin)"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="dwzlatin" :class="{ opened }">
|
||||
<button class="header _button" @click="toggle">
|
||||
<div class="header _button" @click="toggle">
|
||||
<span class="icon"><slot name="icon"></slot></span>
|
||||
<span class="text"><slot name="label"></slot></span>
|
||||
<span class="right">
|
||||
|
@ -8,7 +8,7 @@
|
|||
<i v-if="opened" class="ph-caret-up ph-bold ph-lg icon"></i>
|
||||
<i v-else class="ph-caret-down ph-bold ph-lg icon"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<KeepAlive>
|
||||
<div v-if="openedAtLeastOnce" v-show="opened" class="body">
|
||||
<MkSpacer :margin-min="14" :margin-max="22">
|
||||
|
|
|
@ -66,9 +66,6 @@ function toggle(): void {
|
|||
&:hover {
|
||||
border-color: var(--inputBorderHover) !important;
|
||||
}
|
||||
&:focus-within {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
&.checked {
|
||||
background-color: var(--accentedBg) !important;
|
||||
|
|
|
@ -99,9 +99,6 @@ const toggle = () => {
|
|||
border-color: var(--inputBorderHover) !important;
|
||||
}
|
||||
}
|
||||
&:focus-within > .button {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
> .label {
|
||||
margin-left: 12px;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
class="avatar"
|
||||
:user="$i"
|
||||
:disable-preview="true"
|
||||
disableLink
|
||||
/>
|
||||
</div>
|
||||
<template v-if="metadata">
|
||||
|
@ -34,7 +33,6 @@
|
|||
:user="metadata.avatar"
|
||||
:disable-preview="true"
|
||||
:show-indicator="true"
|
||||
disableLink
|
||||
/>
|
||||
<i
|
||||
v-else-if="metadata.icon && !narrow"
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
:is="currentPageComponent"
|
||||
:key="key"
|
||||
v-bind="Object.fromEntries(currentPageProps)"
|
||||
tabindex="-1"
|
||||
v-focus
|
||||
style="outline: none;"
|
||||
/>
|
||||
|
||||
<template #fallback>
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export default {
|
||||
mounted: (el) => el.focus()
|
||||
}
|
|
@ -11,7 +11,6 @@ import anim from "./anim";
|
|||
import clickAnime from "./click-anime";
|
||||
import panel from "./panel";
|
||||
import adaptiveBorder from "./adaptive-border";
|
||||
import focus from "./focus";
|
||||
|
||||
export default function (app: App) {
|
||||
app.directive("userPreview", userPreview);
|
||||
|
@ -26,5 +25,4 @@ export default function (app: App) {
|
|||
app.directive("click-anime", clickAnime);
|
||||
app.directive("panel", panel);
|
||||
app.directive("adaptive-border", adaptiveBorder);
|
||||
app.directive("focus", focus);
|
||||
}
|
||||
|
|
|
@ -76,32 +76,23 @@ export default {
|
|||
ev.preventDefault();
|
||||
});
|
||||
|
||||
function showTooltip() {
|
||||
window.clearTimeout(self.showTimer);
|
||||
window.clearTimeout(self.hideTimer);
|
||||
self.showTimer = window.setTimeout(self.show, delay);
|
||||
}
|
||||
function hideTooltip() {
|
||||
window.clearTimeout(self.showTimer);
|
||||
window.clearTimeout(self.hideTimer);
|
||||
self.hideTimer = window.setTimeout(self.close, delay);
|
||||
}
|
||||
|
||||
el.addEventListener(
|
||||
start, showTooltip,
|
||||
{ passive: true },
|
||||
);
|
||||
el.addEventListener(
|
||||
"focusin", showTooltip,
|
||||
start,
|
||||
() => {
|
||||
window.clearTimeout(self.showTimer);
|
||||
window.clearTimeout(self.hideTimer);
|
||||
self.showTimer = window.setTimeout(self.show, delay);
|
||||
},
|
||||
{ passive: true },
|
||||
);
|
||||
|
||||
el.addEventListener(
|
||||
end, hideTooltip,
|
||||
{ passive: true },
|
||||
);
|
||||
el.addEventListener(
|
||||
"focusout", hideTooltip,
|
||||
end,
|
||||
() => {
|
||||
window.clearTimeout(self.showTimer);
|
||||
window.clearTimeout(self.hideTimer);
|
||||
self.hideTimer = window.setTimeout(self.close, delay);
|
||||
},
|
||||
{ passive: true },
|
||||
);
|
||||
|
||||
|
|
|
@ -313,7 +313,11 @@ onUnmounted(() => {
|
|||
font-weight: normal;
|
||||
opacity: 0.7;
|
||||
|
||||
&:hover, &:focus-visible, &.active {
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
class="user"
|
||||
:to="`/user-info/${user.id}`"
|
||||
>
|
||||
<MkAvatar :user="user" class="avatar" indicator disableLink />
|
||||
<MkAvatar :user="user" class="avatar" indicator />
|
||||
</MkA>
|
||||
</div>
|
||||
</Transition>
|
||||
|
|
|
@ -371,6 +371,34 @@
|
|||
<template #label>Pro account</template>
|
||||
</FormSwitch>
|
||||
</FormSection>
|
||||
|
||||
<FormSection>
|
||||
<template #label>Libre Translate</template>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiUrl"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-link ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API URL</template
|
||||
>
|
||||
</FormInput>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiKey"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-key ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API Key</template
|
||||
>
|
||||
</FormInput>
|
||||
</FormSection>
|
||||
</div>
|
||||
</FormSuspense>
|
||||
</MkSpacer>
|
||||
|
@ -422,6 +450,8 @@ let swPublicKey: any = $ref(null);
|
|||
let swPrivateKey: any = $ref(null);
|
||||
let deeplAuthKey: string = $ref("");
|
||||
let deeplIsPro: boolean = $ref(false);
|
||||
let libreTranslateApiUrl: string = $ref("");
|
||||
let libreTranslateApiKey: string = $ref("");
|
||||
let defaultReaction: string = $ref("");
|
||||
let defaultReactionCustom: string = $ref("");
|
||||
|
||||
|
@ -456,6 +486,8 @@ async function init() {
|
|||
swPrivateKey = meta.swPrivateKey;
|
||||
deeplAuthKey = meta.deeplAuthKey;
|
||||
deeplIsPro = meta.deeplIsPro;
|
||||
libreTranslateApiUrl = meta.libreTranslateApiUrl;
|
||||
libreTranslateApiKey = meta.libreTranslateApiKey;
|
||||
defaultReaction = ["⭐", "👍", "❤️"].includes(meta.defaultReaction)
|
||||
? meta.defaultReaction
|
||||
: "custom";
|
||||
|
@ -498,6 +530,8 @@ function save() {
|
|||
swPrivateKey,
|
||||
deeplAuthKey,
|
||||
deeplIsPro,
|
||||
libreTranslateApiUrl,
|
||||
libreTranslateApiKey,
|
||||
defaultReaction,
|
||||
}).then(() => {
|
||||
fetchInstance();
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
class="avatar"
|
||||
:user="req.follower"
|
||||
:show-indicator="true"
|
||||
disableLink
|
||||
/>
|
||||
<div class="body">
|
||||
<div class="name">
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
{{ i18n.ts.addAccount }}</FormButton
|
||||
>
|
||||
|
||||
<button
|
||||
<div
|
||||
v-for="account in accounts"
|
||||
:key="account.id"
|
||||
class="_panel _button lcjjdxlm"
|
||||
@click="menu(account, $event)"
|
||||
>
|
||||
<div class="avatar">
|
||||
<MkAvatar :user="account" class="avatar" disableLink />
|
||||
<MkAvatar :user="account" class="avatar" />
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="name">
|
||||
|
@ -23,7 +23,7 @@
|
|||
<MkAcct :user="account" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</FormSuspense>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -158,8 +158,6 @@ definePageMetadata({
|
|||
.lcjjdxlm {
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
text-align: unset;
|
||||
|
||||
> .avatar {
|
||||
display: block;
|
||||
|
|
|
@ -204,6 +204,10 @@ hr {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<MkAvatar
|
||||
:user="$i"
|
||||
class="icon"
|
||||
disableLink
|
||||
/><!-- <MkAcct class="text" :user="$i"/> -->
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<MkAvatar
|
||||
:user="$i"
|
||||
class="icon"
|
||||
disableLink
|
||||
/><!-- <MkAcct class="text" :user="$i"/> -->
|
||||
</button>
|
||||
</div>
|
||||
|
@ -335,7 +334,6 @@ function more(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&.active {
|
||||
&:before {
|
||||
background: var(--accentLighten);
|
||||
|
@ -400,6 +398,8 @@ function more(ev: MouseEvent) {
|
|||
padding-left: 30px;
|
||||
line-height: 2.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
@ -425,12 +425,9 @@ function more(ev: MouseEvent) {
|
|||
> .text {
|
||||
position: relative;
|
||||
font-size: 0.9em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: var(--navHoverFg);
|
||||
transition: all 0.4s ease;
|
||||
|
@ -440,8 +437,7 @@ function more(ev: MouseEvent) {
|
|||
color: var(--navActive);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&:hover,
|
||||
&.active {
|
||||
color: var(--accent);
|
||||
transition: all 0.4s ease;
|
||||
|
@ -532,7 +528,6 @@ function more(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&.active {
|
||||
&:before {
|
||||
background: var(--accentLighten);
|
||||
|
@ -618,7 +613,6 @@ function more(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&.active {
|
||||
text-decoration: none;
|
||||
color: var(--accent);
|
||||
|
@ -648,12 +642,5 @@ function more(ev: MouseEvent) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
outline: none;
|
||||
&:focus-visible:before {
|
||||
outline: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
<MkAvatar :user="$i" class="avatar" /><MkAcct
|
||||
class="acct"
|
||||
:user="$i"
|
||||
disableLink
|
||||
/>
|
||||
</button>
|
||||
<div class="post" @click="post">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
class="item _button account"
|
||||
@click="openAccountMenu"
|
||||
>
|
||||
<MkAvatar :user="$i" class="avatar" disableLink /><MkAcct
|
||||
<MkAvatar :user="$i" class="avatar" /><MkAcct
|
||||
class="text"
|
||||
:user="$i"
|
||||
/>
|
||||
|
@ -299,7 +299,6 @@ function openInstanceMenu(ev: MouseEvent) {
|
|||
width: 46px;
|
||||
height: 46px;
|
||||
padding: 0;
|
||||
margin-inline: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,7 +372,6 @@ function openInstanceMenu(ev: MouseEvent) {
|
|||
|
||||
> i {
|
||||
width: 32px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
> i,
|
||||
|
|
|
@ -227,8 +227,6 @@ onMounted(() => {
|
|||
}
|
||||
|
||||
.gbhvwtnk {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
$ui-font-size: 1em;
|
||||
$widgets-hide-threshold: 1200px;
|
||||
|
||||
|
|
|
@ -19,12 +19,6 @@ importers:
|
|||
'@tensorflow/tfjs':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0(seedrandom@3.0.5)
|
||||
focus-trap:
|
||||
specifier: ^7.2.0
|
||||
version: 7.2.0
|
||||
focus-trap-vue:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1(focus-trap@7.2.0)(vue@3.2.45)
|
||||
js-yaml:
|
||||
specifier: 4.1.0
|
||||
version: 4.1.0
|
||||
|
@ -3809,12 +3803,14 @@ packages:
|
|||
'@vue/shared': 3.2.45
|
||||
estree-walker: 2.0.2
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/@vue/compiler-dom@3.2.45:
|
||||
resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==}
|
||||
dependencies:
|
||||
'@vue/compiler-core': 3.2.45
|
||||
'@vue/shared': 3.2.45
|
||||
dev: true
|
||||
|
||||
/@vue/compiler-sfc@2.7.14:
|
||||
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
|
||||
|
@ -3837,12 +3833,14 @@ packages:
|
|||
magic-string: 0.25.9
|
||||
postcss: 8.4.21
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/@vue/compiler-ssr@3.2.45:
|
||||
resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==}
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.2.45
|
||||
'@vue/shared': 3.2.45
|
||||
dev: true
|
||||
|
||||
/@vue/reactivity-transform@3.2.45:
|
||||
resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==}
|
||||
|
@ -3852,17 +3850,20 @@ packages:
|
|||
'@vue/shared': 3.2.45
|
||||
estree-walker: 2.0.2
|
||||
magic-string: 0.25.9
|
||||
dev: true
|
||||
|
||||
/@vue/reactivity@3.2.45:
|
||||
resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==}
|
||||
dependencies:
|
||||
'@vue/shared': 3.2.45
|
||||
dev: true
|
||||
|
||||
/@vue/runtime-core@3.2.45:
|
||||
resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==}
|
||||
dependencies:
|
||||
'@vue/reactivity': 3.2.45
|
||||
'@vue/shared': 3.2.45
|
||||
dev: true
|
||||
|
||||
/@vue/runtime-dom@3.2.45:
|
||||
resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==}
|
||||
|
@ -3870,6 +3871,7 @@ packages:
|
|||
'@vue/runtime-core': 3.2.45
|
||||
'@vue/shared': 3.2.45
|
||||
csstype: 2.6.21
|
||||
dev: true
|
||||
|
||||
/@vue/server-renderer@3.2.45(vue@3.2.45):
|
||||
resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==}
|
||||
|
@ -3879,9 +3881,11 @@ packages:
|
|||
'@vue/compiler-ssr': 3.2.45
|
||||
'@vue/shared': 3.2.45
|
||||
vue: 3.2.45
|
||||
dev: true
|
||||
|
||||
/@vue/shared@3.2.45:
|
||||
resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==}
|
||||
dev: true
|
||||
|
||||
/@webassemblyjs/ast@1.11.1:
|
||||
resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==}
|
||||
|
@ -6070,6 +6074,7 @@ packages:
|
|||
|
||||
/csstype@2.6.21:
|
||||
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
||||
dev: true
|
||||
|
||||
/csstype@3.1.1:
|
||||
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
||||
|
@ -6974,6 +6979,7 @@ packages:
|
|||
|
||||
/estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
|
||||
/esutils@2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
|
@ -7439,22 +7445,6 @@ packages:
|
|||
readable-stream: 2.3.7
|
||||
dev: true
|
||||
|
||||
/focus-trap-vue@4.0.1(focus-trap@7.2.0)(vue@3.2.45):
|
||||
resolution: {integrity: sha512-2iqOeoSvgq7Um6aL+255a/wXPskj6waLq2oKCa4gOnMORPo15JX7wN6J5bl1SMhMlTlkHXGSrQ9uJPJLPZDl5w==}
|
||||
peerDependencies:
|
||||
focus-trap: ^7.0.0
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
focus-trap: 7.2.0
|
||||
vue: 3.2.45
|
||||
dev: false
|
||||
|
||||
/focus-trap@7.2.0:
|
||||
resolution: {integrity: sha512-v4wY6HDDYvzkBy4735kW5BUEuw6Yz9ABqMYLuTNbzAFPcBOGiGHwwcNVMvUz4G0kgSYh13wa/7TG3XwTeT4O/A==}
|
||||
dependencies:
|
||||
tabbable: 6.1.1
|
||||
dev: false
|
||||
|
||||
/follow-redirects@1.15.2(debug@4.3.4):
|
||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
@ -10360,6 +10350,7 @@ packages:
|
|||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||
dependencies:
|
||||
sourcemap-codec: 1.4.8
|
||||
dev: true
|
||||
|
||||
/mailcheck@1.1.1:
|
||||
resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==}
|
||||
|
@ -13276,6 +13267,7 @@ packages:
|
|||
/sourcemap-codec@1.4.8:
|
||||
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
||||
deprecated: Please use @jridgewell/sourcemap-codec instead
|
||||
dev: true
|
||||
|
||||
/sparkles@1.0.1:
|
||||
resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==}
|
||||
|
@ -13694,10 +13686,6 @@ packages:
|
|||
resolution: {integrity: sha512-g9rPT3V1Q4WjWFZ/t5BdGC1mT/FpYnsLdBl+M5e6MlRkuE1RSR+R43wcY/3mKI59B9KEr+vxdWCuWNMD3oNHKA==}
|
||||
dev: true
|
||||
|
||||
/tabbable@6.1.1:
|
||||
resolution: {integrity: sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg==}
|
||||
dev: false
|
||||
|
||||
/tapable@2.2.1:
|
||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -14788,6 +14776,7 @@ packages:
|
|||
'@vue/runtime-dom': 3.2.45
|
||||
'@vue/server-renderer': 3.2.45(vue@3.2.45)
|
||||
'@vue/shared': 3.2.45
|
||||
dev: true
|
||||
|
||||
/vuedraggable@4.1.0(vue@3.2.45):
|
||||
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
|
||||
|
|
Loading…
Reference in New Issue