Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), enforced with [semantic-release](https://github.com/semantic-release/semantic-release).

## [11.2.0](https://github.com/silinternational/ui-components/compare/v11.1.2...v11.2.0) (2024-04-09)


### Added

* **TextInputs:** add showError, showWarn props to MoneyInput, TextArea and TextField ([c143895](https://github.com/silinternational/ui-components/commit/c143895280c354e586e20c614919b1130d3e66e6))

### Fixed

* **TextInputs:** use latest material docs to fix icon spacing issues on TextField and MoneyInput ([2df920b](https://github.com/silinternational/ui-components/commit/2df920bf89df513213bc99067a565112850d5439))

### [11.1.2](https://github.com/silinternational/ui-components/compare/v11.1.1...v11.1.2) (2024-04-08)


Expand Down
60 changes: 27 additions & 33 deletions components/mdc/TextInput/MoneyInput.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- https://github.com/material-components/material-components-web/tree/master/packages/mdc-textfield -->
<script>
/** A Svelte component that represents a text input for money values. */
import { getDecimalPlacesLength } from './helpers'
import { addOrRemoveInvalidClass, getDecimalPlacesLength } from './helpers'
import { generateRandomID } from '../../../random'
import { MDCTextField } from '@material/textfield'
import { afterUpdate, onMount } from 'svelte'
Expand All @@ -28,6 +28,10 @@ export let disabled = false
export let required = false
/** @type {string} The description to display below the input. */
export let description = ''
/** @type {boolean} lets the component know to use error class. */
export let showError = false
/** @type {boolean} lets the component know to use warn class. */
export let showWarn = false

const labelID = generateRandomID('text-label-')

Expand All @@ -49,6 +53,9 @@ $: valueHasTooManyDecPlaces = getDecimalPlacesLength(internalValue) > getDecimal
$: valueNotDivisibleByStep =
(internalValue && (internalValue / Number(step)).toFixed(2) % 1 !== 0) || valueHasTooManyDecPlaces
$: internalValue = Number(value) || 0
$: warn = showWarn
$: value, addOrRemoveInvalidClass(error, element)
$: addOrRemoveInvalidClass(showError || showWarn, element)

onMount(() => {
mdcTextField = new MDCTextField(element)
Expand All @@ -60,29 +67,29 @@ afterUpdate(() => (width = `${element?.offsetWidth}px`))
const focus = (node) => autofocus && node.focus()
</script>

<style>
.material-icons {
color: rgb(133, 140, 148);
position: relative;
top: 0.4rem;
right: 0.6rem;
}
.label-margin {
margin-left: 1.1rem;
}
.mdc-text-field--label-floating .mdc-floating-label {
margin-left: 0;
}
</style>

<label
class="mdc-text-field mdc-text-field--outlined {$$props.class || ''} textfield-radius"
class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon {$$props.class ||
''} textfield-radius"
class:mdc-text-field--no-label={!label}
class:mdc-text-field--disabled={disabled}
class:mdc-text-field--invalid={error}
class:warn
class:showError
bind:this={element}
>
<i class="material-icons" class:error aria-hidden="true">attach_money</i>
<span class="mdc-notched-outline">
<span class="mdc-notched-outline__leading" />
{#if label}
<span class="mdc-notched-outline__notch">
<span class="mdc-floating-label" class:error id={labelID}>
{label}
</span>
</span>
{/if}
<span class="mdc-notched-outline__trailing" />
</span>
<i class="material-icons mdc-text-field__icon mdc-text-field__icon--leading" class:error aria-hidden="true">
attach_money
</i>
<input
{step}
type="number"
Expand All @@ -107,21 +114,8 @@ const focus = (node) => autofocus && node.focus()
{required}
/>
{#if showErrorIcon}
<span class="mdc-text-field__affix mdc-text-field__affix--suffix">
<i class="material-icons error" aria-hidden="true"> error</i>
</span>
<i class="material-icons mdc-text-field__icon mdc-text-field__icon--trailing error" aria-hidden="true"> error</i>
{/if}
<span class="mdc-notched-outline">
<span class="mdc-notched-outline__leading" />
{#if label}
<span class="mdc-notched-outline__notch">
<span class="mdc-floating-label label-margin" class:error id={labelID}>
{label}
</span>
</span>
{/if}
<span class="mdc-notched-outline__trailing" />
</span>
</label>
<div class="mdc-text-field-helper-line" style="width: {width};">
<div
Expand Down
8 changes: 8 additions & 0 deletions components/mdc/TextInput/TextArea.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export let required = false
export let description = ''
/** @type {string} The name of the textarea field. */
export let name = ''
/** @type {boolean} lets the component know to use error class. */
export let showError = false
/** @type {boolean} lets the component know to use warn class. */
export let showWarn = false

const labelID = generateRandomID('textarea-label-')

Expand All @@ -37,7 +41,9 @@ let hasBlurred = false
$: hasExceededMaxLength = maxlength && value.length > maxlength
$: error = hasExceededMaxLength || (hasFocused && hasBlurred && required && valueIsEmpty)
$: valueIsEmpty = value === ' ' || !value
$: warn = showWarn
$: !valueIsEmpty && addOrRemoveInvalidClass(error, element)
$: addOrRemoveInvalidClass(showError || showWarn, element)

onMount(() => {
resize()
Expand Down Expand Up @@ -78,6 +84,8 @@ label {
class:mdc-text-field--no-label={!label}
class:mdc-text-field--label-floating={label}
class:mdc-text-field--with-internal-counter={maxlength}
class:warn
class:showError
bind:this={element}
>
<textarea
Expand Down
59 changes: 27 additions & 32 deletions components/mdc/TextInput/TextField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export let icon = ''
export let description = ''
/** @type {string} The name of the text input field. */
export let name = ''
/** @type {boolean} lets the component know to use error class. */
export let showError = false
/** @type {boolean} lets the component know to use warn class. */
export let showWarn = false

const labelID = generateRandomID('text-label-')

Expand All @@ -37,8 +41,10 @@ let hasBlurred = false
$: mdcTextField.value = value
$: hasExceededMaxLength = maxlength && value.length > maxlength
$: error = hasExceededMaxLength || (hasFocused && hasBlurred && required && !value)
$: warn = showWarn
$: showCounter = maxlength && value.length / maxlength > 0.85
$: value && addOrRemoveInvalidClass(error, element)
$: value, addOrRemoveInvalidClass(error, element)
$: addOrRemoveInvalidClass(showError || showWarn, element)

onMount(() => {
mdcTextField = new MDCTextField(element)
Expand All @@ -52,28 +58,31 @@ afterUpdate(() => {
const focus = (node) => autofocus && node.focus()
</script>

<style>
.material-icons {
color: rgb(133, 140, 148);
position: relative;
top: 0.4rem;
right: 0.6rem;
}
.label-margin {
margin-left: 1.1rem;
}
.mdc-text-field--label-floating .mdc-floating-label {
margin-left: 0;
}
</style>

<label
class="mdc-text-field mdc-text-field--outlined {$$props.class || ''} textfield-radius"
class:mdc-text-field--no-label={!label}
class:mdc-text-field--disabled={disabled}
class:warn
class:showError
class:mdc-text-field--with-leading-icon={icon}
bind:this={element}
>
<i class="material-icons" class:error aria-hidden="true">{icon}</i>
<span class="mdc-notched-outline">
<span class="mdc-notched-outline__leading" />
{#if label}
<span class="mdc-notched-outline__notch">
<span class="mdc-floating-label" class:error id={labelID}>
{label}
</span>
</span>
{/if}
<span class="mdc-notched-outline__trailing" />
</span>
{#if icon}
<i class="material-icons mdc-text-field__icon mdc-text-field__icon--leading" class:error aria-hidden="true">
{icon}</i
>
{/if}
<input
type="text"
class="mdc-text-field__input"
Expand All @@ -96,22 +105,8 @@ const focus = (node) => autofocus && node.focus()
{placeholder}
/>
{#if hasExceededMaxLength}
<span class="mdc-text-field__affix mdc-text-field__affix--suffix"
><i class="material-icons error" aria-hidden="true">error</i></span
>
<i class="material-icons mdc-text-field__icon mdc-text-field__icon--trailing error" aria-hidden="true">error</i>
{/if}

<span class="mdc-notched-outline">
<span class="mdc-notched-outline__leading" />
{#if label}
<span class="mdc-notched-outline__notch">
<span class="mdc-floating-label" class:label-margin={icon} class:error id={labelID}>
{label}
</span>
</span>
{/if}
<span class="mdc-notched-outline__trailing" />
</span>
</label>
<div class="mdc-text-field-helper-line" style="width: {width};">
<div
Expand Down
33 changes: 33 additions & 0 deletions components/mdc/TextInput/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
//@use "@material/line-ripple/mdc-line-ripple"; // Only needed if using ripple.
@use '@material/notched-outline/mdc-notched-outline';
@use '@material/textfield';
@use '@material/textfield/icon';

@include textfield.core-styles;
@include icon.icon-core-styles;

:root {
--mdc-theme-error: #c30000;
--mdc-theme-warn: #f48c03;
}

$radius: 8px !default;
$error: var(--mdc-theme-status-error, var(--mdc-theme-error)) !default;
$warn: var(--mdc-theme-status-warn, var(--mdc-theme-warn)) !default;

/* TODO should be cleaned up later, this code is in multiple files but only needs to be in the master css*/

Expand All @@ -20,6 +29,30 @@ $radius: 8px !default;
.error {
color: var(--mdc-theme-status-error, var(--mdc-theme-error)) !important;
}
.showError.mdc-text-field--invalid {
@include textfield.outline-color($error);
@include textfield.hover-outline-color($error);
@include textfield.ink-color($error);
@include textfield.placeholder-color($error);
@include textfield.label-color($error);
@include icon.leading-icon-color($error);
@include icon.trailing-icon-color($error);
@include textfield.caret-color($error);
@include textfield.prefix-color($error);
@include textfield.suffix-color($error);
}
.warn.mdc-text-field--invalid {
@include textfield.outline-color($warn);
@include textfield.hover-outline-color($warn);
@include textfield.ink-color($warn);
@include textfield.placeholder-color($warn);
@include textfield.label-color($warn);
@include icon.leading-icon-color($warn);
@include icon.trailing-icon-color($warn);
@include textfield.caret-color($warn);
@include textfield.prefix-color($warn);
@include textfield.suffix-color($warn);
}
.required {
color: var(--mdc-required-input, rgba(0, 0, 0, 0.6));
}
Expand Down
6 changes: 6 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ declare module '@silintl/ui-components' {
step?: number | string
description?: string
class?: string
showWarn?: boolean
showError?: boolean
}
export class MoneyInput extends SvelteComponentTyped<MoneyInputProps> {}

Expand Down Expand Up @@ -285,6 +287,8 @@ declare module '@silintl/ui-components' {
rtl?: boolean
description?: string
class?: string
showWarn?: boolean
showError?: boolean
}
export class TextArea extends SvelteComponentTyped<TextAreaProps> {}

Expand All @@ -300,6 +304,8 @@ declare module '@silintl/ui-components' {
required?: boolean
description?: string
class?: string
showWarn?: boolean
showError?: boolean
}
export class TextField extends SvelteComponentTyped<TextFieldProps> {}

Expand Down
19 changes: 14 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@silintl/ui-components",
"version": "11.1.2",
"version": "11.2.0",
"description": "Reusable Svelte components for some internal applications",
"main": "index.mjs",
"module": "index.mjs",
Expand Down
Loading