* copy updates

* Update docs/pages/components/copy.md

Co-authored-by: Thomas Allmer <d4kmor@gmail.com>

* unwrap and fix case

* copy button updates

* use bs icon

* add parts, hoist, and improve parsing a bit

* update docs

* remove comment

---------

Co-authored-by: Thomas Allmer <d4kmor@gmail.com>
pull/1504/head
Cory LaViska 2023-08-11 07:27:34 -07:00 zatwierdzone przez GitHub
rodzic 458def7830
commit c36df5ecc1
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
30 zmienionych plików z 643 dodań i 6 usunięć

Wyświetl plik

@ -0,0 +1,258 @@
---
meta:
title: Copy Button
description: Copies data to the clipboard when the user clicks the button.
layout: component
---
```html:preview
<sl-copy-button value="Shoelace rocks!"></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const App = () => (
<SlCopyButton value="Shoelace rocks!" />
);
```
## Examples
### Custom Labels
Copy Buttons display feedback in a tooltip. You can customize the labels using the `copy-label`, `success-label`, and `error-label` attributes.
```html:preview
<sl-copy-button
value="Custom labels are easy"
copy-label="Click to copy"
success-label="You did it!"
error-label="Whoops, your browser doesn't support this!"
></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const App = () => (
<SlCopyButton
value="Custom labels are easy"
copy-label="Click to copy"
success-label="You did it!"
error-label="Whoops, your browser doesn't support this!"
/>
);
```
### Custom Icons
Use the `copy-icon`, `success-icon`, and `error-icon` slots to customize the icons that get displayed for each state. You can use [`<sl-icon>`](/components/icon) or your own images.
```html:preview
<sl-copy-button value="Copied from a custom button">
<sl-icon slot="copy-icon" name="clipboard"></sl-icon>
<sl-icon slot="success-icon" name="clipboard-check"></sl-icon>
<sl-icon slot="error-icon" name="clipboard-x"></sl-icon>
</sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
import { SlIcon } from '@shoelace-style/shoelace/dist/react/sl-icon';
const App = () => (
<>
<SlCopyButton value="Copied from a custom button">
<SlIcon slot="copy-icon" name="clipboard" />
<SlIcon slot="success-icon" name="clipboard-check" />
<SlIcon slot="error-icon" name="clipboard-x" />
</SlCopyButton>
</>
);
```
### Copying Values From Other Elements
Normally, the data that gets copied will come from the component's `value` attribute, but you can copy data from any element within the same document by providing its `id` to the `from` attribute.
When using the `from` attribute, the element's [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) will be copied by default. Passing an attribute or property modifier will let you copy data from one of the element's attributes or properties instead.
To copy data from an attribute, use `from="id[attr]"` where `id` is the id of the target element and `attr` is the name of the attribute you'd like to copy. To copy data from a property, use `from="id.prop"` where `id` is the id of the target element and `prop` is the name of the property you'd like to copy.
```html:preview
<!-- Copies the span's textContent -->
<span id="my-phone">+1 (234) 456-7890</span>
<sl-copy-button from="my-phone"></sl-copy-button>
<br><br>
<!-- Copies the input's "value" property -->
<sl-input id="my-input" type="text" value="User input" style="display: inline-block; max-width: 300px;"></sl-input>
<sl-copy-button from="my-input.value"></sl-copy-button>
<br><br>
<!-- Copies the link's "href" attribute -->
<a id="my-link" href="https://shoelace.style/">Shoelace Website</a>
<sl-copy-button from="my-link[href]"></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
import { SlInput } from '@shoelace-style/shoelace/dist/react/sl-input';
const App = () => (
<>
{/* Copies the span's textContent */}
<span id="my-phone">+1 (234) 456-7890</span>
<SlCopyButton from="my-phone" />
<br /><br />
{/* Copies the input's "value" property */}
<SlInput id="my-input" type="text" />
<SlCopyButton from="my-input.value" />
<br /><br />
{/* Copies the link's "href" attribute */}
<a id="my-link" href="https://shoelace.style/">Shoelace Website</a>
<SlCopyButton from="my-link[href]" />
</>
);
```
### Handling Errors
A copy error will occur if the value is an empty string, if the `from` attribute points to an id that doesn't exist, or if the browser rejects the operation for any reason. When this happens, the `sl-error` event will be emitted.
This example demonstrates what happens when a copy error occurs. You can customize the error label and icon using the `error-label` attribute and the `error-icon` slot, respectively.
```html:preview
<sl-copy-button from="i-do-not-exist"></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const App = () => (
<SlCopyButton from="i-do-not-exist" />
);
```
### Disabled
Copy buttons can be disabled by adding the `disabled` attribute.
```html:preview
<sl-copy-button value="You can't copy me" disabled></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const App = () => (
<SlCopyButton value="You can't copy me" disabled />
);
```
### 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
<sl-copy-button value="Shoelace rocks!" feedback-duration="250"></sl-copy-button>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const App = () => (
<SlCopyButton value="Shoelace rocks!" feedback-duration={250} />
);
```
### Custom Styles
You can customize the button to your liking with CSS.
```html:preview
<sl-copy-button value="I'm so stylish" class="custom-styles">
<sl-icon slot="copy-icon" name="asterisk"></sl-icon>
<sl-icon slot="success-icon" name="check-lg"></sl-icon>
<sl-icon slot="error-icon" name="x-lg"></sl-icon>
</sl-copy-button>
<style>
.custom-styles {
--success-color: white;
--error-color: white;
color: white;
}
.custom-styles::part(button) {
background-color: #ff1493;
border: solid 4px #ff7ac1;
border-right-color: #ad005c;
border-bottom-color: #ad005c;
border-radius: 0;
transition: 100ms scale ease-in-out, 100ms translate ease-in-out;
}
.custom-styles::part(button):hover {
scale: 1.1;
}
.custom-styles::part(button):active {
translate: 0 2px;
}
.custom-styles::part(button):focus-visible {
outline: dashed 2px deeppink;
outline-offset: 4px;
}
</style>
```
```jsx:react
import { SlCopyButton } from '@shoelace-style/shoelace/dist/react/sl-copy-button';
const css = `
.custom-styles {
--success-color: white;
--error-color: white;
color: white;
}
.custom-styles::part(button) {
background-color: #ff1493;
border: solid 4px #ff7ac1;
border-right-color: #ad005c;
border-bottom-color: #ad005c;
border-radius: 0;
transition: 100ms scale ease-in-out, 100ms translate ease-in-out;
}
.custom-styles::part(button):hover {
scale: 1.1;
}
.custom-styles::part(button):active {
translate: 0 2px;
}
.custom-styles::part(button):focus-visible {
outline: dashed 2px deeppink;
outline-offset: 4px;
}
`;
const App = () => (
<>
<SlCopyButton value="I'm so stylish" className="custom-styles" />
<style>{css}</style>
</>
);
```

Wyświetl plik

@ -645,9 +645,7 @@ When using sprite sheets, the `sl-load` and `sl-error` events will not fire.
:::
:::danger
For security reasons, browsers may apply the same-origin policy on `<use>` elements located in the `<sl-icon>` shadow dom and
may refuse to load a cross-origin URL. There is currently no defined way to set a cross-origin policy for `<use>` elements.
For this reason, sprite sheets should only be used if you're self-hosting them.
For security reasons, browsers may apply the same-origin policy on `<use>` elements located in the `<sl-icon>` shadow DOM and may refuse to load a cross-origin URL. There is currently no defined way to set a cross-origin policy for `<use>` elements. For this reason, sprite sheets should only be used if you're self-hosting them.
:::
```html:preview

Wyświetl plik

@ -14,8 +14,10 @@ New versions of Shoelace are released as-needed and generally occur when a criti
## Next
- Added the `<sl-copy-button>` component [#1473]
- Fixed a bug in `<sl-dropdown>` where pressing [[Up]] or [[Down]] when focused on the trigger wouldn't focus the first/last menu items [#1472]
- Improved the behavior of the clear button in `<sl-input>` to prevent the component's width from shifting when toggled [#1496]
- Improved `<sl-tooltip>` to prevent user selection so the tooltip doesn't get highlighted when dragging selections
- Removed `sideEffects` key from `package.json`. Update React docs to use cherry-picking. [#1485]
- Updated Bootstrap Icons to 1.10.5

Wyświetl plik

@ -0,0 +1,257 @@
import { classMap } from 'lit/directives/class-map.js';
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property, query, state } from 'lit/decorators.js';
import ShoelaceElement from '../../internal/shoelace-element.js';
import SlIcon from '../icon/icon.component.js';
import SlTooltip from '../tooltip/tooltip.component.js';
import styles from './copy-button.styles.js';
import type { CSSResultGroup } from 'lit';
/**
* @summary Copies text data to the clipboard when the user clicks the trigger.
* @documentation https://shoelace.style/components/copy
* @status experimental
* @since 2.7
*
* @dependency sl-icon
* @dependency sl-tooltip
*
* @event sl-copy - Emitted when the data has been copied.
* @event sl-error - Emitted when the data could not be copied.
*
* @slot copy-icon - The icon to show in the default copy state. Works best with `<sl-icon>`.
* @slot success-icon - The icon to show when the content is copied. Works best with `<sl-icon>`.
* @slot error-icon - The icon to show when a copy error occurs. Works best with `<sl-icon>`.
*
* @csspart button - The internal `<button>` element.
* @csspart copy-icon - The container that holds the copy icon.
* @csspart success-icon - The container that holds the success icon.
* @csspart error-icon - The container that holds the error icon.
* @csspart tooltip__base - The tooltip's exported `base` part.
* @csspart tooltip__base__popup - The tooltip's exported `popup` part.
* @csspart tooltip__base__arrow - The tooltip's exported `arrow` part.
* @csspart tooltip__body - The tooltip's exported `body` part.
*
* @cssproperty --success-color - The color to use for success feedback.
* @cssproperty --error-color - The color to use for error feedback.
*
* @animation copy.in - The animation to use when feedback icons animate in.
* @animation copy.out - The animation to use when feedback icons animate out.
*/
export default class SlCopyButton extends ShoelaceElement {
static styles: CSSResultGroup = styles;
static dependencies = {
'sl-icon': SlIcon,
'sl-tooltip': SlTooltip
};
private readonly localize = new LocalizeController(this);
@query('slot[name="copy-icon"]') copyIcon: HTMLSlotElement;
@query('slot[name="success-icon"]') successIcon: HTMLSlotElement;
@query('slot[name="error-icon"]') errorIcon: HTMLSlotElement;
@query('sl-tooltip') tooltip: SlTooltip;
@state() isCopying = false;
@state() status: 'rest' | 'success' | 'error' = 'rest';
/** The text value to copy. */
@property() value = '';
/**
* An id that references an element in the same document from which data will be copied. If both this and `value` are
* present, this value will take precedence. By default, the target element's `textContent` will be copied. To copy an
* attribute, append the attribute name wrapped in square brackets, e.g. `from="el[value]"`. To copy a property,
* append a dot and the property name, e.g. `from="el.value"`.
*/
@property() from = '';
/** Disables the copy button. */
@property({ type: Boolean, reflect: true }) disabled = false;
/** A custom label to show in the tooltip. */
@property({ attribute: 'copy-label' }) copyLabel = '';
/** A custom label to show in the tooltip after copying. */
@property({ attribute: 'success-label' }) successLabel = '';
/** A custom label to show in the tooltip when a copy error occurs. */
@property({ attribute: 'error-label' }) errorLabel = '';
/** The length of time to show feedback before restoring the default trigger. */
@property({ attribute: 'feedback-duration', type: Number }) feedbackDuration = 1000;
/** The preferred placement of the tooltip. */
@property({ attribute: 'tooltip-placement' }) tooltipPlacement: 'top' | 'right' | 'bottom' | 'left' = 'top';
/**
* Enable this option to prevent the tooltip from being clipped when the component is placed inside a container with
* `overflow: auto|hidden|scroll`. Hoisting uses a fixed positioning strategy that works in many, but not all,
* scenarios.
*/
@property({ type: Boolean }) hoist = false;
private async handleCopy() {
if (this.disabled || this.isCopying) {
return;
}
this.isCopying = true;
// 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;
// Simple way to parse ids, properties, and attributes
const isProperty = this.from.includes('.');
const isAttribute = this.from.includes('[') && this.from.includes(']');
let id = this.from;
let field = '';
if (isProperty) {
// Split at the dot
[id, field] = this.from.trim().split('.');
} else if (isAttribute) {
// Trim the ] and split at the [
[id, field] = this.from.trim().replace(/\]$/, '').split('[');
}
// Locate the target element by id
const target = 'getElementById' in root ? root.getElementById(id) : null;
if (target) {
if (isAttribute) {
valueToCopy = target.getAttribute(field) || '';
} else if (isProperty) {
// @ts-expect-error - deal with it
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
valueToCopy = target[field] || '';
} else {
valueToCopy = target.textContent || '';
}
} else {
// No target
this.showStatus('error');
this.emit('sl-error');
}
}
// No value
if (!valueToCopy) {
this.showStatus('error');
this.emit('sl-error');
} else {
try {
await navigator.clipboard.writeText(valueToCopy);
this.showStatus('success');
this.emit('sl-copy', {
detail: {
value: valueToCopy
}
});
} catch (error) {
// Rejected by browser
this.showStatus('error');
this.emit('sl-error');
}
}
}
private async showStatus(status: 'success' | 'error') {
const copyLabel = this.copyLabel || this.localize.term('copy');
const successLabel = this.successLabel || this.localize.term('copied');
const errorLabel = this.errorLabel || this.localize.term('error');
const iconToShow = status === 'success' ? this.successIcon : this.errorIcon;
const showAnimation = getAnimation(this, 'copy.in', { dir: 'ltr' });
const hideAnimation = getAnimation(this, 'copy.out', { dir: 'ltr' });
this.tooltip.content = status === 'success' ? successLabel : errorLabel;
// Show the feedback icon
await this.copyIcon.animate(hideAnimation.keyframes, hideAnimation.options).finished;
this.copyIcon.hidden = true;
this.status = status;
iconToShow.hidden = false;
await iconToShow.animate(showAnimation.keyframes, showAnimation.options).finished;
// After a brief delay, restore the original state
setTimeout(async () => {
await iconToShow.animate(hideAnimation.keyframes, hideAnimation.options).finished;
iconToShow.hidden = true;
this.status = 'rest';
this.copyIcon.hidden = false;
await this.copyIcon.animate(showAnimation.keyframes, showAnimation.options).finished;
this.tooltip.content = copyLabel;
this.isCopying = false;
}, this.feedbackDuration);
}
render() {
const copyLabel = this.copyLabel || this.localize.term('copy');
return html`
<sl-tooltip
class=${classMap({
'copy-button': true,
'copy-button--success': this.status === 'success',
'copy-button--error': this.status === 'error'
})}
content=${copyLabel}
placement=${this.tooltipPlacement}
?disabled=${this.disabled}
?hoist=${this.hoist}
exportparts="
base:tooltip__base
base__popup:tooltip__base__popup
base__arrow:tooltip__base__arrow
body:tooltip__body
"
>
<button
class="copy-button__button"
part="button"
type="button"
?disabled=${this.disabled}
@click=${this.handleCopy}
>
<slot part="copy-icon" name="copy-icon">
<sl-icon library="system" name="copy"></sl-icon>
</slot>
<slot part="success-icon" name="success-icon" hidden>
<sl-icon library="system" name="check"></sl-icon>
</slot>
<slot part="error-icon" name="error-icon" hidden>
<sl-icon library="system" name="x-lg"></sl-icon>
</slot>
</button>
</sl-tooltip>
`;
}
}
setDefaultAnimation('copy.in', {
keyframes: [
{ scale: '.25', opacity: '.25' },
{ scale: '1', opacity: '1' }
],
options: { duration: 100 }
});
setDefaultAnimation('copy.out', {
keyframes: [
{ scale: '1', opacity: '1' },
{ scale: '.25', opacity: '0' }
],
options: { duration: 100 }
});
declare global {
interface HTMLElementTagNameMap {
'sl-copy-button': SlCopyButton;
}
}

Wyświetl plik

@ -0,0 +1,49 @@
import { css } from 'lit';
import componentStyles from '../../styles/component.styles.js';
export default css`
${componentStyles}
:host {
--error-color: var(--sl-color-danger-600);
--success-color: var(--sl-color-success-600);
display: inline-block;
}
.copy-button__button {
flex: 0 0 auto;
display: flex;
align-items: center;
background: none;
border: none;
border-radius: var(--sl-border-radius-medium);
font-size: inherit;
color: inherit;
padding: var(--sl-spacing-x-small);
cursor: pointer;
transition: var(--sl-transition-x-fast) color;
}
.copy-button--success .copy-button__button {
color: var(--success-color);
}
.copy-button--error .copy-button__button {
color: var(--error-color);
}
.copy-button__button:focus-visible {
outline: var(--sl-focus-ring);
outline-offset: var(--sl-focus-ring-offset);
}
.copy-button__button[disabled] {
opacity: 0.5;
cursor: not-allowed !important;
}
slot {
display: inline-flex;
}
`;

Wyświetl plik

@ -0,0 +1,20 @@
import '../../../dist/shoelace.js';
import { expect, fixture, html } from '@open-wc/testing';
import type SlCopyButton from './copy-button.js';
// We use aria-live to announce labels via tooltips
const ignoredRules = ['button-name'];
describe('<sl-copy-button>', () => {
let el: SlCopyButton;
describe('when provided no parameters', () => {
before(async () => {
el = await fixture(html`<sl-copy-button value="something"></sl-copy-button> `);
});
it('should pass accessibility tests', async () => {
await expect(el).to.be.accessible({ ignoredRules });
});
});
});

Wyświetl plik

@ -0,0 +1,4 @@
import SlCopyButton from './copy-button.component.js';
export * from './copy-button.component.js';
export default SlCopyButton;
SlCopyButton.define('sl-copy-button');

Wyświetl plik

@ -16,7 +16,7 @@ const icons = {
check: `
<svg part="checked-icon" class="checkbox__icon" viewBox="0 0 16 16">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g stroke="currentColor" stroke-width="2">
<g stroke="currentColor">
<g transform="translate(3.428571, 3.428571)">
<path d="M0,5.71428571 L3.42857143,9.14285714"></path>
<path d="M9.14285714,0 L3.42857143,9.14285714"></path>
@ -40,6 +40,11 @@ const icons = {
<path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
</svg>
`,
copy: `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-files" viewBox="0 0 16 16" part="svg">
<path d="M13 0H6a2 2 0 0 0-2 2 2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2 2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 13V4a2 2 0 0 0-2-2H5a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zM3 4a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4z"></path>
</svg>
`,
eye: `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>

Wyświetl plik

@ -99,8 +99,6 @@ export default class SlTooltip extends ShoelaceElement {
constructor() {
super();
// TODO (justinfagnani): does this need to be done in firstUpdated for some
// reason? If so, document why in a comment.
this.addEventListener('blur', this.handleBlur, true);
this.addEventListener('focus', this.handleFocus, true);
this.addEventListener('click', this.handleClick);

Wyświetl plik

@ -51,5 +51,6 @@ export default css`
color: var(--sl-tooltip-color);
padding: var(--sl-tooltip-padding);
pointer-events: none;
user-select: none;
}
`;

Wyświetl plik

@ -8,6 +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 { default as SlCopyEvent } from './sl-copy';
export type { default as SlErrorEvent } from './sl-error';
export type { default as SlExpandEvent } from './sl-expand';
export type { default as SlFinishEvent } from './sl-finish';

Wyświetl plik

@ -0,0 +1,9 @@
type SlCopyEvent = CustomEvent<{ value: string }>;
declare global {
interface GlobalEventHandlersEventMap {
'sl-copy': SlCopyEvent;
}
}
export default SlCopyEvent;

Wyświetl plik

@ -13,6 +13,7 @@ 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 SlColorPicker } from './components/color-picker/color-picker.js';
export { default as SlCopyButton } from './components/copy-button/copy-button.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';

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -9,8 +9,10 @@ const translation: Translation = {
carousel: 'چرخ فلک',
clearEntry: 'پاک کردن ورودی',
close: 'بستن',
copied: 'کپی شد',
copy: 'رونوشت',
currentValue: 'مقدار فعلی',
error: 'خطا',
goToSlide: (slide, count) => `رفتن به اسلاید ${slide} از ${count}`,
hidePassword: 'پنهان کردن رمز',
loading: 'بارگذاری',

Wyświetl plik

@ -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',

Wyświetl plik

@ -9,8 +9,10 @@ const translation: Translation = {
carousel: 'קרוסלה',
clearEntry: 'נקה קלט',
close: 'סגור',
copied: 'מוּעֲתָק',
copy: 'העתק',
currentValue: 'ערך נוכחי',
error: 'שְׁגִיאָה',
goToSlide: (slide, count) => `עבור לשקופית ${slide} של ${count}`,
hidePassword: 'הסתר סיסמא',
loading: 'טוען',

Wyświetl plik

@ -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',

Wyświetl plik

@ -9,8 +9,10 @@ const translation: Translation = {
carousel: 'カルーセル',
clearEntry: 'クリアエントリ',
close: '閉じる',
copied: 'コピーされました',
copy: 'コピー',
currentValue: '現在の価値',
error: 'エラー',
goToSlide: (slide, count) => `${count} 枚中 ${slide} 枚のスライドに移動`,
hidePassword: 'パスワードを隠す',
loading: '読み込み中',

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -9,8 +9,10 @@ const translation: Translation = {
carousel: 'Карусель',
clearEntry: 'Очистить запись',
close: 'Закрыть',
copied: 'Скопировано',
copy: 'Скопировать',
currentValue: 'Текущее значение',
error: 'Ошибка',
goToSlide: (slide, count) => `Перейти к слайду ${slide} из ${count}`,
hidePassword: 'Скрыть пароль',
loading: 'Загрузка',

Wyświetl plik

@ -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',

Wyświetl plik

@ -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',

Wyświetl plik

@ -9,8 +9,10 @@ const translation: Translation = {
carousel: '旋轉木馬',
clearEntry: '清空',
close: '關閉',
copied: '已復制',
copy: '複製',
currentValue: '當前值',
error: '錯誤',
goToSlide: (slide, count) => `轉到第 ${slide} 張幻燈片,共 ${count}`,
hidePassword: '隱藏密碼',
loading: '載入中',

Wyświetl plik

@ -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;