diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index a4cfb1b1..58d94001 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -50,6 +50,7 @@
- Utility Components
- [Animation](/components/animation.md)
- [Format Bytes](/components/format-bytes.md)
+ - [Format Number](/components/format-number.md)
- [Include](/components/include.md)
- [Resize Observer](/components/resize-observer.md)
- [Theme](/components/theme.md)
diff --git a/docs/components/format-number.md b/docs/components/format-number.md
new file mode 100644
index 00000000..bcfd1899
--- /dev/null
+++ b/docs/components/format-number.md
@@ -0,0 +1,61 @@
+# Format Number
+
+[component-header:sl-format-number]
+
+Formats a number using the specified locale and options.
+
+Localization is handled by the browser's built-in [Intl: NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat). As such, there's no need to load language packs or omit those you don't plan on using.
+
+```html preview
+
+
+
+
+
+
+
+```
+
+## Examples
+
+### Percentages
+
+To get the value as a percent, set the `type` attribute to `percent`.
+
+```html preview
+
+
+
+
+
+```
+
+### Localization
+
+Use the `locale` attribute to set the number formatting locale.
+
+```html preview
+English:
+German:
+Russian:
+```
+
+### Currency
+
+To format a number as a monetary value, set the `type` attribute to `currency` and set the `currency` attribute to the desired ISO 4217 currency code. You should also specify `locale` to ensure the the number is formatted correctly for the target locale.
+
+```html preview
+
+
+
+
+
+```
+
+[component-metadata:sl-format-number]
diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md
index d16bf759..664cea8c 100644
--- a/docs/getting-started/changelog.md
+++ b/docs/getting-started/changelog.md
@@ -8,9 +8,10 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
## Next
+- Added `sl-format-number` component
+- Added `closable` prop to `sl-tab`
- Added experimental `sl-resize-observer` utility
- Added experimental `sl-theme` utility and updated theming documentation
-- Added `closable` prop to `sl-tab`
- Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme
- Fixed a bug where `sl-select` would show an autocomplete menu
- Improved placeholder contrast in dark theme
diff --git a/src/components.d.ts b/src/components.d.ts
index db418df2..716a355c 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -468,6 +468,52 @@ export namespace Components {
*/
"value": number;
}
+ interface SlFormatNumber {
+ /**
+ * The currency to use when formatting. Must be an ISO 4217 currency code such as `USD` or `EUR`.
+ */
+ "currency": string;
+ /**
+ * How to display the currency.
+ */
+ "currencyDisplay": 'symbol' | 'narrowSymbol' | 'code' | 'name';
+ /**
+ * The locale to use when formatting the number.
+ */
+ "locale": string;
+ /**
+ * The maximum number of fraction digits to use. Possible values are 0 - 20.
+ */
+ "maximumFractionDigits": number;
+ /**
+ * The maximum number of significant digits to use,. Possible values are 1 - 21.
+ */
+ "maximumSignificantDigits": number;
+ /**
+ * The minimum number of fraction digits to use. Possible values are 0 - 20.
+ */
+ "minimumFractionDigits": number;
+ /**
+ * The minimum number of integer digits to use. Possible values are 1 - 21.
+ */
+ "minimumIntegerDigits": number;
+ /**
+ * The minimum number of significant digits to use. Possible values are 1 - 21.
+ */
+ "minimumSignificantDigits": number;
+ /**
+ * Turns off grouping separators.
+ */
+ "noGrouping": boolean;
+ /**
+ * The formatting style to use.
+ */
+ "type": 'currency' | 'decimal' | 'percent';
+ /**
+ * The number to format in bytes.
+ */
+ "value": number;
+ }
interface SlIcon {
/**
* An alternative description to use for accessibility. If omitted, the name or src will be used to generate it.
@@ -1292,6 +1338,12 @@ declare global {
prototype: HTMLSlFormatBytesElement;
new (): HTMLSlFormatBytesElement;
};
+ interface HTMLSlFormatNumberElement extends Components.SlFormatNumber, HTMLStencilElement {
+ }
+ var HTMLSlFormatNumberElement: {
+ prototype: HTMLSlFormatNumberElement;
+ new (): HTMLSlFormatNumberElement;
+ };
interface HTMLSlIconElement extends Components.SlIcon, HTMLStencilElement {
}
var HTMLSlIconElement: {
@@ -1476,6 +1528,7 @@ declare global {
"sl-dropdown": HTMLSlDropdownElement;
"sl-form": HTMLSlFormElement;
"sl-format-bytes": HTMLSlFormatBytesElement;
+ "sl-format-number": HTMLSlFormatNumberElement;
"sl-icon": HTMLSlIconElement;
"sl-icon-button": HTMLSlIconButtonElement;
"sl-icon-library": HTMLSlIconLibraryElement;
@@ -2000,6 +2053,52 @@ declare namespace LocalJSX {
*/
"value"?: number;
}
+ interface SlFormatNumber {
+ /**
+ * The currency to use when formatting. Must be an ISO 4217 currency code such as `USD` or `EUR`.
+ */
+ "currency"?: string;
+ /**
+ * How to display the currency.
+ */
+ "currencyDisplay"?: 'symbol' | 'narrowSymbol' | 'code' | 'name';
+ /**
+ * The locale to use when formatting the number.
+ */
+ "locale"?: string;
+ /**
+ * The maximum number of fraction digits to use. Possible values are 0 - 20.
+ */
+ "maximumFractionDigits"?: number;
+ /**
+ * The maximum number of significant digits to use,. Possible values are 1 - 21.
+ */
+ "maximumSignificantDigits"?: number;
+ /**
+ * The minimum number of fraction digits to use. Possible values are 0 - 20.
+ */
+ "minimumFractionDigits"?: number;
+ /**
+ * The minimum number of integer digits to use. Possible values are 1 - 21.
+ */
+ "minimumIntegerDigits"?: number;
+ /**
+ * The minimum number of significant digits to use. Possible values are 1 - 21.
+ */
+ "minimumSignificantDigits"?: number;
+ /**
+ * Turns off grouping separators.
+ */
+ "noGrouping"?: boolean;
+ /**
+ * The formatting style to use.
+ */
+ "type"?: 'currency' | 'decimal' | 'percent';
+ /**
+ * The number to format in bytes.
+ */
+ "value"?: number;
+ }
interface SlIcon {
/**
* An alternative description to use for accessibility. If omitted, the name or src will be used to generate it.
@@ -2747,6 +2846,7 @@ declare namespace LocalJSX {
"sl-dropdown": SlDropdown;
"sl-form": SlForm;
"sl-format-bytes": SlFormatBytes;
+ "sl-format-number": SlFormatNumber;
"sl-icon": SlIcon;
"sl-icon-button": SlIconButton;
"sl-icon-library": SlIconLibrary;
@@ -2796,6 +2896,7 @@ declare module "@stencil/core" {
"sl-dropdown": LocalJSX.SlDropdown & JSXBase.HTMLAttributes;
"sl-form": LocalJSX.SlForm & JSXBase.HTMLAttributes;
"sl-format-bytes": LocalJSX.SlFormatBytes & JSXBase.HTMLAttributes;
+ "sl-format-number": LocalJSX.SlFormatNumber & JSXBase.HTMLAttributes;
"sl-icon": LocalJSX.SlIcon & JSXBase.HTMLAttributes;
"sl-icon-button": LocalJSX.SlIconButton & JSXBase.HTMLAttributes;
"sl-icon-library": LocalJSX.SlIconLibrary & JSXBase.HTMLAttributes;
diff --git a/src/components/format-number/format-number.tsx b/src/components/format-number/format-number.tsx
new file mode 100644
index 00000000..d5609ec6
--- /dev/null
+++ b/src/components/format-number/format-number.tsx
@@ -0,0 +1,65 @@
+import { Component, Prop } from '@stencil/core';
+
+/**
+ * @since 2.0
+ * @status stable
+ */
+
+@Component({
+ tag: 'sl-format-number',
+ shadow: true
+})
+export class FormatBytes {
+ /** The number to format in bytes. */
+ @Prop() value = 0;
+
+ /** The locale to use when formatting the number. */
+ @Prop() locale: string;
+
+ /** The formatting style to use. */
+ @Prop() type: 'currency' | 'decimal' | 'percent' = 'decimal';
+
+ /** Turns off grouping separators. */
+ @Prop() noGrouping = false;
+
+ /** The currency to use when formatting. Must be an ISO 4217 currency code such as `USD` or `EUR`. */
+ @Prop() currency = 'USD';
+
+ /** How to display the currency. */
+ @Prop() currencyDisplay: 'symbol' | 'narrowSymbol' | 'code' | 'name' = 'symbol';
+
+ /** The minimum number of integer digits to use. Possible values are 1 - 21. */
+ @Prop() minimumIntegerDigits: number;
+
+ /** The minimum number of fraction digits to use. Possible values are 0 - 20. */
+ @Prop() minimumFractionDigits: number;
+
+ /** The maximum number of fraction digits to use. Possible values are 0 - 20. */
+ @Prop() maximumFractionDigits: number;
+
+ /** The minimum number of significant digits to use. Possible values are 1 - 21. */
+ @Prop() minimumSignificantDigits: number;
+
+ /** The maximum number of significant digits to use,. Possible values are 1 - 21. */
+ @Prop() maximumSignificantDigits: number;
+
+ render() {
+ const number = Number(this.value);
+
+ if (isNaN(number)) {
+ return '';
+ }
+
+ return new Intl.NumberFormat(this.locale, {
+ style: this.type,
+ currency: this.currency,
+ currencyDisplay: this.currencyDisplay,
+ useGrouping: !this.noGrouping,
+ minimumIntegerDigits: this.minimumIntegerDigits,
+ minimumFractionDigits: this.minimumFractionDigits,
+ maximumFractionDigits: this.maximumFractionDigits,
+ minimumSignificantDigits: this.minimumSignificantDigits,
+ maximumSignificantDigits: this.maximumSignificantDigits
+ }).format(number);
+ }
+}