diff --git a/docs/pages/components/clipboard.md b/docs/pages/components/clipboard.md deleted file mode 100644 index 08e007db..00000000 --- a/docs/pages/components/clipboard.md +++ /dev/null @@ -1,241 +0,0 @@ ---- -meta: - title: Clipboard - description: Enables you to save content into the clipboard providing visual feedback. -layout: component ---- - -```html:preview -

Clicking the clipboard button will put "shoelace rocks" into your clipboard

- -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> -

Clicking the clipboard button will put "shoelace rocks" into your clipboard

- - -); -``` - -## Examples - -### Use your own button - -```html:preview - - - - - -
- - Copy - Copied - Error - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> - - -
copied
- -
- - Copy - Copied - Error - - -); -``` - -### Get the textValue from a different element - -```html:preview -
-
-
Phone Number
-
+1 234 456789
-
- -
- - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const css = ` - dl, .row { - display: flex; - margin: 0; - } -`; - -const App = () => ( - <> -
-
-
Phone Number
-
+1 234 456789
-
- -
- - - -); -``` - -### Copy an input/textarea or link - -```html:preview - - -
- - - -
- -Shoelace - -
- - - -
- - - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> - - -
- - -
- Shoelace - - -); -``` - -### Error if copy fails - -For example if a `for` target element is not found or if not using `https`. -An empty string value like `value=""` will also result in an error. - -```html:preview - -
- - Copy - Copied - Error - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> - - - Copy - Copied - Error - - -); -``` - -### Change duration of reset to copy button - -```html:preview - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> - - -); -``` - -### Supports Shadow Dom - -```html:preview - - - -``` - -```jsx:react -import { SlClipboard } from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - <> - - -); - -customElements.define('sl-copy-demo-el', class extends HTMLElement { - constructor() { - super(); - this.attachShadow({ mode: 'open' }); - } - - connectedCallback() { - this.shadowRoot.innerHTML = ` -

copy me (inside shadow root)

- - `; - } -}); -``` - -## Disclaimer - -The public API is partially inspired by https://github.com/github/clipboard-copy-element diff --git a/docs/pages/components/copy.md b/docs/pages/components/copy.md new file mode 100644 index 00000000..fc4cc67e --- /dev/null +++ b/docs/pages/components/copy.md @@ -0,0 +1,156 @@ +--- +meta: + title: Copy + description: Copies data to the clipboard when the user clicks or taps the trigger. +layout: component +--- + +```html:preview + +``` + +```jsx:react +import { SlCopy } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + +); +``` + +## Examples + +### Custom Buttons + +Use the default slot to customize the copy trigger. You can also customize the success and error messages using the respective slots. + +```html:preview + + Copy + Copied! + Error + +``` + +```jsx:react +import { SlButton, SlCopy } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + <> + + Copy + Copied! + Error + + +); +``` + +### Copying the Value From Other Elements + +By default, the data to copy will come from the `value` attribute. You + +```html:preview ++1 (234) 456-7890 + + +

+ + + + +

+ +Shoelace Website + +``` + +```jsx:react +import { SlCopy, SlInput } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + <> + +1 (234) 456-7890 + + +

+ + + + +

+ + Shoelace Website + + +); +``` + +### Displaying Copy Errors + +Copy errors can occur if the value is an empty string, if the `for` attribute points to an id that doesn't exist, or if the browser rejects the operation. You can customize the error that's shown by populating the `error` slot with your own content. + +```html:preview + + +

+ + + Copy + Copied + Error + +``` + +```jsx:react +import { SlCopy } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + <> + + +

+ + + Copy + Copied + Error + + +); +``` + +### Showing Tooltips + +You can wrap a tooltip around `` to provide a hint to users. + +```html:preview + + + +``` + +```jsx:react +import { SlCopy, SlTooltip } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + + + +); +``` + +### Changing Feedback Duration + +A success indicator is briefly shown after copying. You can customize the length of time the indicator is shown using the `feedback-duration` attribute. + +```html:preview + +``` + +```jsx:react +import { SlCopy } from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + +); +``` diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 3698347b..d2b610e5 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -12,6 +12,10 @@ Components with the Experimental bad New versions of Shoelace are released as-needed and generally occur when a critical mass of changes have accumulated. At any time, you can see what's coming in the next release by visiting [next.shoelace.style](https://next.shoelace.style). +## Next + +- Added the `` component [[#1473]] + ## 2.6.0 - Added JSDoc comments to React Wrappers for better documentation when hovering a component. [#1450] diff --git a/src/components/clipboard/clipboard.component.ts b/src/components/clipboard/clipboard.component.ts deleted file mode 100644 index 05710202..00000000 --- a/src/components/clipboard/clipboard.component.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { classMap } from 'lit/directives/class-map.js'; -import { html } from 'lit'; -import { property } from 'lit/decorators.js'; -import ShoelaceElement from '../../internal/shoelace-element.js'; -import SlIconButton from '../icon-button/icon-button.component.js'; -import SlTooltip from '../tooltip/tooltip.component.js'; -import styles from './clipboard.styles.js'; -import type { CSSResultGroup } from 'lit'; - -/** - * @summary Enables you to save content into the clipboard providing visual feedback. - * @documentation https://shoelace.style/components/clipboard - * @status experimental - * @since 2.0 - * - * @dependency sl-icon-button - * @dependency sl-tooltip - * - * @event sl-copying - Event when copying starts. - * @event sl-copied - Event when copying finished. - * - * @slot - The content that gets clicked to copy. - * @slot copied - The content shown after a successful copy. - * @slot error - The content shown if an error occurs. - */ -export default class SlClipboard extends ShoelaceElement { - static styles: CSSResultGroup = styles; - static dependencies = { 'sl-tooltip': SlTooltip, 'sl-icon-button': SlIconButton }; - - /** - * Indicates the current status the copy action is in. - */ - @property({ type: String }) copyStatus: 'trigger' | 'copied' | 'error' = 'trigger'; - - /** Value to copy. */ - @property({ type: String }) value = ''; - - /** Id of the element to copy the text value from. */ - @property({ type: String }) for = ''; - - /** Duration in milliseconds to reset to the trigger state. */ - @property({ type: Number, attribute: 'reset-timeout' }) resetTimeout = 2000; - - private handleClick() { - if (this.copyStatus === 'copied') return; - this.copy(); - } - - /** Copies the clipboard */ - async copy() { - if (this.for) { - const root = this.getRootNode() as ShadowRoot | Document; - const target = 'getElementById' in root ? root.getElementById(this.for) : false; - if (target) { - if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { - this.value = target.value; - } else if (target instanceof HTMLAnchorElement && target.hasAttribute('href')) { - this.value = target.href; - } else if ('value' in target) { - this.value = String(target.value); - } else { - this.value = target.textContent || ''; - } - } - } - if (this.value) { - try { - this.emit('sl-copying'); - await navigator.clipboard.writeText(this.value); - this.emit('sl-copied'); - this.copyStatus = 'copied'; - } catch (error) { - this.copyStatus = 'error'; - } - } else { - this.copyStatus = 'error'; - } - - setTimeout(() => (this.copyStatus = 'trigger'), this.resetTimeout); - } - - render() { - return html` -
- - - - - - - - - - - - - - - -
- `; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'sl-clipboard': SlClipboard; - } -} diff --git a/src/components/clipboard/clipboard.styles.ts b/src/components/clipboard/clipboard.styles.ts deleted file mode 100644 index e99391b5..00000000 --- a/src/components/clipboard/clipboard.styles.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { css } from 'lit'; -import componentStyles from '../../styles/component.styles.js'; - -export default css` - ${componentStyles} - - :host { - display: inline-block; - } - - /* successful copy */ - slot[name='copied'] { - display: none; - } - .clipboard--copied #default { - display: none; - } - .clipboard--copied slot[name='copied'] { - display: block; - } - - .green::part(base) { - color: var(--sl-color-success-600); - } - .green::part(base):hover, - .green::part(base):focus { - color: var(--sl-color-success-600); - } - .green::part(base):active { - color: var(--sl-color-success-600); - } - - /* failed to copy */ - slot[name='error'] { - display: none; - } - .clipboard--error #default { - display: none; - } - .clipboard--error slot[name='error'] { - display: block; - } - - .red::part(base) { - color: var(--sl-color-danger-600); - } - .red::part(base):hover, - .red::part(base):focus { - color: var(--sl-color-danger-600); - } - .red::part(base):active { - color: var(--sl-color-danger-600); - } -`; diff --git a/src/components/clipboard/clipboard.ts b/src/components/clipboard/clipboard.ts deleted file mode 100644 index 390f5940..00000000 --- a/src/components/clipboard/clipboard.ts +++ /dev/null @@ -1,4 +0,0 @@ -import SlClipboard from './clipboard.component.js'; -export * from './clipboard.component.js'; -export default SlClipboard; -SlClipboard.define('sl-clipboard'); diff --git a/src/components/copy/copy.component.ts b/src/components/copy/copy.component.ts new file mode 100644 index 00000000..61b99da1 --- /dev/null +++ b/src/components/copy/copy.component.ts @@ -0,0 +1,165 @@ +import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js'; +import { html } from 'lit'; +import { LocalizeController } from '../../utilities/localize.js'; +import { property, query } from 'lit/decorators.js'; +import ShoelaceElement from '../../internal/shoelace-element.js'; +import SlIconButton from '../icon-button/icon-button.component.js'; +import styles from './copy.styles.js'; +import type { CSSResultGroup } from 'lit'; + +/** + * @summary Copies data to the clipboard when the user clicks or taps the trigger. + * @documentation https://shoelace.style/components/copy + * @status experimental + * @since 2.7 + * + * @dependency sl-icon-button + * + * @event sl-copied - Emitted when the data has been copied. + * @event sl-error - Emitted when the data could not be copied. + * + * @slot - A button that triggers copying. + * @slot success - A button to briefly show when copying is successful. + * @slot error - A button to briefly show when a copy error occurs. + * + * @animation copy.in - The animation to use when copy buttons animate in. + * @animation copy.out - The animation to use when copy buttons animate out. + */ +export default class SlCopy extends ShoelaceElement { + static styles: CSSResultGroup = styles; + static dependencies = { + 'sl-icon-button': SlIconButton + }; + + private readonly localize = new LocalizeController(this); + + @query('slot:not([name])') defaultSlot: HTMLSlotElement; + @query('slot[name="success"]') successSlot: HTMLSlotElement; + @query('slot[name="error"]') errorSlot: HTMLSlotElement; + + /** The text value to copy. */ + @property({ type: String }) value = ''; + + /** The length of time to show feedback before restoring the default trigger. */ + @property({ attribute: 'feedback-duration', type: Number }) feedbackDuration = 1000; + + /** + * An id that references an element in the same document from which data will be copied. If the element is a link, the + * `href` will be copied. If the element is a form control or has a `value` property, its `value` will be copied. + * Otherwise, the element's text content will be copied. + */ + @property({ type: String }) from = ''; + + connectedCallback() { + super.connectedCallback(); + this.setAttribute('aria-live', 'polite'); + } + + private async handleCopy() { + // Copy the value by default + let valueToCopy = this.value; + + // If an element is specified, copy from that instead + if (this.from) { + const root = this.getRootNode() as ShadowRoot | Document; + const target = 'getElementById' in root ? root.getElementById(this.from) : false; + + if (target) { + if (target instanceof HTMLAnchorElement && target.hasAttribute('href')) { + valueToCopy = target.href; + } else if ('value' in target) { + valueToCopy = String(target.value); + } else { + valueToCopy = target.textContent || ''; + } + } else { + this.showStatus('error'); + this.emit('sl-error'); + } + } + + // Copy from the value property otherwise + if (valueToCopy) { + try { + await navigator.clipboard.writeText(valueToCopy); + this.showStatus('success'); + this.emit('sl-copied'); + } catch (error) { + this.showStatus('error'); + this.emit('sl-error'); + } + } + } + + private async showStatus(status: 'success' | 'error') { + const target = status === 'success' ? this.successSlot : this.errorSlot; + const showAnimation = getAnimation(this, 'copy.in', { dir: 'ltr' }); + const hideAnimation = getAnimation(this, 'copy.out', { dir: 'ltr' }); + + await this.defaultSlot.animate(hideAnimation.keyframes, hideAnimation.options).finished; + this.defaultSlot.hidden = true; + + target.hidden = false; + await target.animate(showAnimation.keyframes, showAnimation.options).finished; + + setTimeout(async () => { + await target.animate(hideAnimation.keyframes, hideAnimation.options).finished; + target.hidden = true; + this.defaultSlot.hidden = false; + this.defaultSlot.animate(showAnimation.keyframes, showAnimation.options); + }, this.feedbackDuration); + } + + render() { + return html` + + + + + + + + `; + } +} + +setDefaultAnimation('copy.in', { + keyframes: [ + { scale: '.25', opacity: '.25' }, + { scale: '1', opacity: '1' } + ], + options: { duration: 125 } +}); + +setDefaultAnimation('copy.out', { + keyframes: [ + { scale: '1', opacity: '1' }, + { scale: '.25', opacity: '0' } + ], + options: { duration: 125 } +}); + +declare global { + interface HTMLElementTagNameMap { + 'sl-copy': SlCopy; + } +} diff --git a/src/components/copy/copy.styles.ts b/src/components/copy/copy.styles.ts new file mode 100644 index 00000000..77cbf72c --- /dev/null +++ b/src/components/copy/copy.styles.ts @@ -0,0 +1,24 @@ +import { css } from 'lit'; +import componentStyles from '../../styles/component.styles.js'; + +export default css` + ${componentStyles} + + :host { + display: inline-block; + cursor: pointer; + } + + slot { + display: inline-flex; + } + + .copy { + background: none; + border: none; + font: inherit; + color: inherit; + padding: 0; + margin: 0; + } +`; diff --git a/src/components/clipboard/clipboard.test.ts b/src/components/copy/copy.test.ts similarity index 79% rename from src/components/clipboard/clipboard.test.ts rename to src/components/copy/copy.test.ts index 86093ff4..47a915e5 100644 --- a/src/components/clipboard/clipboard.test.ts +++ b/src/components/copy/copy.test.ts @@ -1,13 +1,13 @@ import '../../../dist/shoelace.js'; import { aTimeout, expect, fixture, html } from '@open-wc/testing'; -import type SlClipboard from './clipboard.js'; +import type SlCopy from './copy.js'; -describe('', () => { - let el: SlClipboard; +describe('', () => { + let el: SlCopy; describe('when provided no parameters', () => { before(async () => { - el = await fixture(html` `); + el = await fixture(html` `); }); it('should pass accessibility tests', async () => { diff --git a/src/components/copy/copy.ts b/src/components/copy/copy.ts new file mode 100644 index 00000000..ce56b309 --- /dev/null +++ b/src/components/copy/copy.ts @@ -0,0 +1,4 @@ +import SlCopy from './copy.component.js'; +export * from './copy.component.js'; +export default SlCopy; +SlCopy.define('sl-copy'); diff --git a/src/components/icon/library.system.ts b/src/components/icon/library.system.ts index a0b6ab3e..0dedf7e6 100644 --- a/src/components/icon/library.system.ts +++ b/src/components/icon/library.system.ts @@ -16,7 +16,7 @@ const icons = { check: ` - + @@ -40,6 +40,11 @@ const icons = { `, + copy: ` + + + + `, eye: ` diff --git a/src/events/events.ts b/src/events/events.ts index 322b9c8d..8786b25d 100644 --- a/src/events/events.ts +++ b/src/events/events.ts @@ -8,8 +8,7 @@ export type { default as SlChangeEvent } from './sl-change'; export type { default as SlClearEvent } from './sl-clear'; export type { default as SlCloseEvent } from './sl-close'; export type { default as SlCollapseEvent } from './sl-collapse'; -export type { SlCopyingEvent } from './sl-copying'; -export type { SlCopiedEvent } from './sl-copied'; +export type { default as SlCopiedEvent } from './sl-copied'; export type { default as SlErrorEvent } from './sl-error'; export type { default as SlExpandEvent } from './sl-expand'; export type { default as SlFinishEvent } from './sl-finish'; diff --git a/src/events/sl-copied.ts b/src/events/sl-copied.ts index 6293ba8e..b170d5cb 100644 --- a/src/events/sl-copied.ts +++ b/src/events/sl-copied.ts @@ -1,7 +1,9 @@ -export type SlCopiedEvent = CustomEvent>; +type SlCopiedEvent = CustomEvent>; declare global { interface GlobalEventHandlersEventMap { 'sl-copied': SlCopiedEvent; } } + +export default SlCopiedEvent; diff --git a/src/events/sl-copying.ts b/src/events/sl-copying.ts deleted file mode 100644 index 33ad22ad..00000000 --- a/src/events/sl-copying.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type SlCopyingEvent = CustomEvent>; - -declare global { - interface GlobalEventHandlersEventMap { - 'sl-copying': SlCopyingEvent; - } -} diff --git a/src/shoelace.ts b/src/shoelace.ts index 69c2e647..5c02bdfd 100644 --- a/src/shoelace.ts +++ b/src/shoelace.ts @@ -12,8 +12,8 @@ export { default as SlCard } from './components/card/card.js'; export { default as SlCarousel } from './components/carousel/carousel.js'; export { default as SlCarouselItem } from './components/carousel-item/carousel-item.js'; export { default as SlCheckbox } from './components/checkbox/checkbox.js'; -export { default as SlClipboard } from './components/clipboard/clipboard.js'; export { default as SlColorPicker } from './components/color-picker/color-picker.js'; +export { default as SlCopy } from './components/copy/copy.js'; export { default as SlDetails } from './components/details/details.js'; export { default as SlDialog } from './components/dialog/dialog.js'; export { default as SlDivider } from './components/divider/divider.js'; diff --git a/src/translations/da.ts b/src/translations/da.ts index e0d459c8..3925e68d 100644 --- a/src/translations/da.ts +++ b/src/translations/da.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Karrusel', clearEntry: 'Ryd indtastning', close: 'Luk', + copied: 'Kopieret', copy: 'Kopier', currentValue: 'Nuværende værdi', + error: 'Fejl', goToSlide: (slide, count) => `Gå til dias ${slide} af ${count}`, hidePassword: 'Skjul adgangskode', loading: 'Indlæser', diff --git a/src/translations/de.ts b/src/translations/de.ts index 4c1df4fb..1894e600 100644 --- a/src/translations/de.ts +++ b/src/translations/de.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Karussell', clearEntry: 'Eingabe löschen', close: 'Schließen', + copied: 'Kopiert', copy: 'Kopieren', currentValue: 'Aktueller Wert', + error: 'Fehler', goToSlide: (slide, count) => `Gehen Sie zu Folie ${slide} von ${count}`, hidePassword: 'Passwort verbergen', loading: 'Wird geladen', diff --git a/src/translations/en.ts b/src/translations/en.ts index 86a5e015..155cfcfd 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Carousel', clearEntry: 'Clear entry', close: 'Close', + copied: 'Copied', copy: 'Copy', currentValue: 'Current value', + error: 'Error', goToSlide: (slide, count) => `Go to slide ${slide} of ${count}`, hidePassword: 'Hide password', loading: 'Loading', diff --git a/src/translations/es.ts b/src/translations/es.ts index d15fdff7..4e948967 100644 --- a/src/translations/es.ts +++ b/src/translations/es.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Carrusel', clearEntry: 'Borrar entrada', close: 'Cerrar', + copied: 'Copiado', copy: 'Copiar', currentValue: 'Valor actual', + error: 'Error', goToSlide: (slide, count) => `Ir a la diapositiva ${slide} de ${count}`, hidePassword: 'Ocultar contraseña', loading: 'Cargando', diff --git a/src/translations/fa.ts b/src/translations/fa.ts index 2f39bde1..6b70bddb 100644 --- a/src/translations/fa.ts +++ b/src/translations/fa.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'چرخ فلک', clearEntry: 'پاک کردن ورودی', close: 'بستن', + copied: 'کپی شد', copy: 'رونوشت', currentValue: 'مقدار فعلی', + error: 'خطا', goToSlide: (slide, count) => `رفتن به اسلاید ${slide} از ${count}`, hidePassword: 'پنهان کردن رمز', loading: 'بارگذاری', diff --git a/src/translations/fr.ts b/src/translations/fr.ts index a760fe84..e1386c97 100644 --- a/src/translations/fr.ts +++ b/src/translations/fr.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Carrousel', clearEntry: `Effacer l'entrée`, close: 'Fermer', + copied: 'Copié', copy: 'Copier', currentValue: 'Valeur actuelle', + error: 'Erreur', goToSlide: (slide, count) => `Aller à la diapositive ${slide} de ${count}`, hidePassword: 'Masquer le mot de passe', loading: 'Chargement', diff --git a/src/translations/he.ts b/src/translations/he.ts index 59187804..91d0f2c9 100644 --- a/src/translations/he.ts +++ b/src/translations/he.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'קרוסלה', clearEntry: 'נקה קלט', close: 'סגור', + copied: 'מוּעֲתָק', copy: 'העתק', currentValue: 'ערך נוכחי', + error: 'שְׁגִיאָה', goToSlide: (slide, count) => `עבור לשקופית ${slide} של ${count}`, hidePassword: 'הסתר סיסמא', loading: 'טוען', diff --git a/src/translations/hu.ts b/src/translations/hu.ts index 7ff13be2..8272af85 100644 --- a/src/translations/hu.ts +++ b/src/translations/hu.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Körhinta', clearEntry: 'Bejegyzés törlése', close: 'Bezárás', + copied: 'Másolva', copy: 'Másolás', currentValue: 'Aktuális érték', + error: 'Hiba', goToSlide: (slide, count) => `Ugrás a ${count}/${slide}. diára`, hidePassword: 'Jelszó elrejtése', loading: 'Betöltés', diff --git a/src/translations/ja.ts b/src/translations/ja.ts index 47217e80..62ba4ed6 100644 --- a/src/translations/ja.ts +++ b/src/translations/ja.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'カルーセル', clearEntry: 'クリアエントリ', close: '閉じる', + copied: 'コピーされました', copy: 'コピー', currentValue: '現在の価値', + error: 'エラー', goToSlide: (slide, count) => `${count} 枚中 ${slide} 枚のスライドに移動`, hidePassword: 'パスワードを隠す', loading: '読み込み中', diff --git a/src/translations/nl.ts b/src/translations/nl.ts index a4c859b8..6357fa7b 100644 --- a/src/translations/nl.ts +++ b/src/translations/nl.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Carrousel', clearEntry: 'Invoer wissen', close: 'Sluiten', + copied: 'Gekopieerd', copy: 'Kopiëren', currentValue: 'Huidige waarde', + error: 'Fout', goToSlide: (slide, count) => `Ga naar slide ${slide} van ${count}`, hidePassword: 'Verberg wachtwoord', loading: 'Bezig met laden', diff --git a/src/translations/pl.ts b/src/translations/pl.ts index 5630a4e0..b22913c6 100644 --- a/src/translations/pl.ts +++ b/src/translations/pl.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Karuzela', clearEntry: 'Wyczyść wpis', close: 'Zamknij', + copied: 'Skopiowane', copy: 'Kopiuj', currentValue: 'Aktualna wartość', + error: 'Błąd', goToSlide: (slide, count) => `Przejdź do slajdu ${slide} z ${count}`, hidePassword: 'Ukryj hasło', loading: 'Ładowanie', diff --git a/src/translations/pt.ts b/src/translations/pt.ts index b433c6a3..c093efac 100644 --- a/src/translations/pt.ts +++ b/src/translations/pt.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Carrossel', clearEntry: 'Limpar entrada', close: 'Fechar', + copied: 'Copiado', copy: 'Copiar', currentValue: 'Valor atual', + error: 'Erro', goToSlide: (slide, count) => `Vá para o slide ${slide} de ${count}`, hidePassword: 'Esconder a senha', loading: 'Carregando', diff --git a/src/translations/ru.ts b/src/translations/ru.ts index ee9f1472..87eae99f 100644 --- a/src/translations/ru.ts +++ b/src/translations/ru.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Карусель', clearEntry: 'Очистить запись', close: 'Закрыть', + copied: 'Скопировано', copy: 'Скопировать', currentValue: 'Текущее значение', + error: 'Ошибка', goToSlide: (slide, count) => `Перейти к слайду ${slide} из ${count}`, hidePassword: 'Скрыть пароль', loading: 'Загрузка', diff --git a/src/translations/sv.ts b/src/translations/sv.ts index 9c1015c8..e9c9f546 100644 --- a/src/translations/sv.ts +++ b/src/translations/sv.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Karusell', clearEntry: 'Återställ val', close: 'Stäng', + copied: 'Kopierade', copy: 'Kopiera', currentValue: 'Nuvarande värde', + error: 'Fel', goToSlide: (slide, count) => `Gå till bild ${slide} av ${count}`, hidePassword: 'Dölj lösenord', loading: 'Läser in', diff --git a/src/translations/tr.ts b/src/translations/tr.ts index 1d983a92..5635963a 100644 --- a/src/translations/tr.ts +++ b/src/translations/tr.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: 'Atlıkarınca', clearEntry: 'Girişi sil', close: 'Kapat', + copied: 'Kopyalandı', copy: 'Kopya', currentValue: 'Mevcut değer', + error: 'Hata', goToSlide: (slide, count) => `${count} slayttan ${slide} slayta gidin`, hidePassword: 'Şifreyi sakla', loading: 'Yükleme', diff --git a/src/translations/zh-tw.ts b/src/translations/zh-tw.ts index 425c182a..6cb7a173 100644 --- a/src/translations/zh-tw.ts +++ b/src/translations/zh-tw.ts @@ -9,8 +9,10 @@ const translation: Translation = { carousel: '旋轉木馬', clearEntry: '清空', close: '關閉', + copied: '已復制', copy: '複製', currentValue: '當前值', + error: '錯誤', goToSlide: (slide, count) => `轉到第 ${slide} 張幻燈片,共 ${count} 張`, hidePassword: '隱藏密碼', loading: '載入中', diff --git a/src/utilities/localize.ts b/src/utilities/localize.ts index 0b52443a..9f22282e 100644 --- a/src/utilities/localize.ts +++ b/src/utilities/localize.ts @@ -16,8 +16,10 @@ export interface Translation extends DefaultTranslation { carousel: string; clearEntry: string; close: string; + copied: string; copy: string; currentValue: string; + error: string; goToSlide: (slide: number, count: number) => string; hidePassword: string; loading: string;