msc-ai-translator
Advanced tools
Comparing version 1.0.1 to 1.0.2
@@ -32,3 +32,73 @@ export const _wccss = ` | ||
.pretty-paragraph{word-break:break-word;hyphens:auto;text-wrap:pretty;white-space:pre-wrap;} | ||
.button-two-face { | ||
--button-size: 40; | ||
--button-size-with-unit: calc(var(--button-size) * 1px); | ||
--button-background-color: rgba(202 230 252); | ||
--button-icon-color: rgba(8 28 53); | ||
--button-box-shadow: none; | ||
--button-active-scale: .8; | ||
--button-icon-scale-basis: calc((var(--button-size) * .75) / 24); | ||
--before-icon: none; | ||
--before-scale: var(--button-icon-scale-basis); | ||
--after-icon: none; | ||
--after-scale: 0; | ||
flex-shrink: 0; | ||
font-size: 0; | ||
appearance: none; | ||
box-shadow: unset; | ||
border: unset; | ||
background: transparent; | ||
-webkit-user-select: none; | ||
user-select: none; | ||
pointer-events: auto; | ||
margin: 0; | ||
padding: 0; | ||
outline: 0 none; | ||
position: relative; | ||
inline-size: var(--button-size-with-unit); | ||
aspect-ratio: 1/1; | ||
border-radius: var(--button-size-with-unit); | ||
background-color: var(--button-background-color); | ||
box-shadow: var(--button-box-shadow); | ||
&:active { | ||
scale: var(--button-active-scale); | ||
} | ||
&::before, | ||
&::after { | ||
position: absolute; | ||
inset-inline-start: 50%; | ||
inset-block-start: 50%; | ||
content: ''; | ||
inline-size: 24px; | ||
aspect-ratio: 1/1; | ||
background-color: var(--button-icon-color); | ||
margin-inline-start: -12px; | ||
margin-block-start: -12px; | ||
transition: scale 250ms ease; | ||
will-change: scale; | ||
pointer-events: none; | ||
} | ||
&::before { | ||
scale: var(--before-scale); | ||
clip-path: var(--before-icon); | ||
} | ||
&::after { | ||
scale: var(--after-scale); | ||
clip-path: var(--after-icon); | ||
} | ||
&[data-reverse] { | ||
--before-scale: 0; | ||
--after-scale: var(--button-icon-scale-basis); | ||
} | ||
} | ||
:host{all:initial;font-family:system-ui,sans-serif;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size:16px;-webkit-tap-highlight-color:transparent;-webkit-print-color-adjust:exact;print-color-adjust:exact;} | ||
@@ -35,0 +105,0 @@ :host { |
@@ -17,2 +17,4 @@ import { _wcl } from './common-lib.js'; | ||
- chrome://on-device-translation-internals/ | ||
- https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis | ||
- https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance | ||
- https://gnn.gamer.com.tw/detail.php?sn=229164 | ||
@@ -534,2 +536,6 @@ */ | ||
--btn-voice-background-color: var(--msc-ai-translator-button-voice-background-color, rgba(202 230 252)); | ||
--btn-voice-icon-color: var(--msc-ai-translator-button-voice-icon-color, rgba(8 28 53)); | ||
--btn-voice-box-shadow: var(--msc-ai-translator-button-voice-box-shadow, 0px 4px 10px rgba(0 0 0/.15)); | ||
position:relative; | ||
@@ -544,5 +550,22 @@ | ||
.prompt-result__titles { | ||
display: flex; | ||
align-items: center; | ||
gap: .5em; | ||
.button--voice { | ||
--button-size: 32; | ||
--before-icon: path('M3 9v6h4l5 5V4L7 9H3zm7-.17v6.34L7.83 13H5v-2h2.83L10 8.83zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77 0-4.28-2.99-7.86-7-8.77z'); | ||
--after-icon: path('M6 19h4V5H6v14zm8-14v14h4V5h-4z'); | ||
--button-background-color: var(--btn-voice-background-color); | ||
--button-icon-color: var(--btn-voice-icon-color); | ||
--button-box-shadow: var(--btn-voice-box-shadow); | ||
} | ||
} | ||
.prompt-result__title { | ||
--sparkle-size: 28px; | ||
flex-grow: 1; | ||
min-block-size: var(--sparkle-size); | ||
@@ -651,3 +674,13 @@ color: var(--introduction-color); | ||
<div class="prompt-result"> | ||
<p class="prompt-result__title pretty-paragraph">${defaults.l10n.introduction}</p> | ||
<div class="prompt-result__titles"> | ||
<p class="prompt-result__title pretty-paragraph">${defaults.l10n.introduction}</p> | ||
<button | ||
type="button" | ||
class="button--voice button-two-face" | ||
data-action="voice" | ||
> | ||
voice | ||
</button> | ||
</div> | ||
<div class="prompt-result__content pretty-paragraph"></div> | ||
@@ -813,2 +846,16 @@ </div> | ||
}); | ||
CSS.registerProperty({ | ||
name: '--msc-ai-translator-button-voice-background-color', | ||
syntax: '<color>', | ||
inherits: true, | ||
initialValue: 'rgba(202 230 252)' | ||
}); | ||
CSS.registerProperty({ | ||
name: '--msc-ai-translator-button-voice-icon-color', | ||
syntax: '<color>', | ||
inherits: true, | ||
initialValue: 'rgba(8 28 53)' | ||
}); | ||
} catch(err) { | ||
@@ -819,2 +866,8 @@ console.warn(`msc-ai-translator: ${err.message}`); | ||
// Web Speech | ||
const synth = window.speechSynthesis; | ||
if (synth) { | ||
window.addEventListener('beforeunload', () => synth.cancel()); | ||
} | ||
// progressSet | ||
@@ -909,2 +962,3 @@ let progressSet = ''; | ||
btnClose: this.shadowRoot.querySelector('.fuji-alerts__close'), | ||
btnVoice: this.shadowRoot.querySelector('.button--voice'), | ||
dialogSubject: this.shadowRoot.querySelector('.fuji-alerts__form__head__p'), | ||
@@ -927,2 +981,3 @@ dialogResultIntroduction: this.shadowRoot.querySelector('.prompt-result__title'), | ||
this._onDialogButtonsClick = this._onDialogButtonsClick.bind(this); | ||
this._onUtteranceActions = this._onUtteranceActions.bind(this); | ||
} | ||
@@ -955,2 +1010,14 @@ | ||
dialog.addEventListener('click', this._onDialogButtonsClick, { signal }); | ||
if (synth && window.SpeechSynthesisUtterance) { | ||
const utterance = new window.SpeechSynthesisUtterance(); | ||
this.#data.utterance = utterance; | ||
['start', 'end', 'resume', 'pause', 'error'].forEach( | ||
(event) => { | ||
utterance.addEventListener(event, this._onUtteranceActions, { signal }); | ||
} | ||
); | ||
} else { | ||
this.#nodes.btnVoice.remove(); | ||
} | ||
} | ||
@@ -1184,2 +1251,7 @@ | ||
dialog.toggleAttribute('close', true); | ||
// force cancel synth | ||
if (synth) { | ||
synth.cancel(); | ||
} | ||
} | ||
@@ -1206,2 +1278,16 @@ | ||
break; | ||
case 'voice': { | ||
if (!synth) { | ||
return; | ||
} | ||
if (synth.speaking) { | ||
synth[synth.paused ? 'resume' : 'pause'](); | ||
} else { | ||
synth.cancel(); | ||
synth.speak(this.#data.utterance); | ||
} | ||
break; | ||
} | ||
} | ||
@@ -1227,2 +1313,22 @@ } | ||
_onUtteranceActions(evt) { | ||
const { btnVoice } = this.#nodes; | ||
const { type } = evt; | ||
switch(type) { | ||
case 'resume': | ||
case 'start': { | ||
btnVoice.toggleAttribute('data-reverse', true); | ||
break; | ||
} | ||
case 'error': | ||
case 'pause': | ||
case 'end': { | ||
btnVoice.toggleAttribute('data-reverse', false); | ||
break; | ||
} | ||
} | ||
} | ||
async #goTranslating({ sourceLanguage, targetLanguage, content }) { | ||
@@ -1300,2 +1406,11 @@ let result = ''; | ||
dialog.showModal(); | ||
if (synth) { | ||
synth.cancel(); | ||
this.#nodes.btnVoice.toggleAttribute('data-reverse', false); | ||
this.#data.utterance.text = result; | ||
this.#data.utterance.lang = targetLanguage; | ||
synth.speak(this.#data.utterance); | ||
} | ||
} | ||
@@ -1302,0 +1417,0 @@ |
{ | ||
"name": "msc-ai-translator", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "<msc-ai-translator /> is a web component based on Chrome Built-in AI > Language Detector API and Translator API. Web developers could use <msc-ai-translator /> wrap article which want to adopt translate language feature.", | ||
@@ -5,0 +5,0 @@ "main": "index.html", |
@@ -126,2 +126,5 @@ # msc-ai-translator | ||
--msc-ai-translator-content-group-background-color: rgba(241 244 248); | ||
--msc-ai-translator-button-voice-background-color: rgba(202 230 252); | ||
--msc-ai-translator-button-voice-icon-color: rgba(8 28 53); | ||
--msc-ai-translator-button-voice-box-shadow: 0px 4px 10px rgba(0 0 0/.15); | ||
} | ||
@@ -128,0 +131,0 @@ </style> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
123492
2918
227