Skip to content

Commit

Permalink
Merge pull request #245 from capitec/develop
Browse files Browse the repository at this point in the history
Merge latest changes on develop to main
  • Loading branch information
chromaticWaster authored Oct 3, 2024
2 parents 6810a71 + 7e3f88c commit 4a5bf4b
Show file tree
Hide file tree
Showing 260 changed files with 926 additions and 359 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
551 changes: 325 additions & 226 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@capitec/omni-components",
"version": "0.9.9",
"version": "0.9.11",
"type": "module",
"description": "Modern UI component library for mobile and web",
"scripts": {
Expand Down
33 changes: 33 additions & 0 deletions src/email-field/EmailField.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ test(`Email Field - Visual and Behaviour`, async ({ page }) => {
await page.goto('/components/email-field/');
await page.evaluate(() => document.fonts.ready);

// Locate the email field component.
const emailField = page.locator('[data-testid]').first();
emailField.evaluate(async (t: EmailField) => {
t.value = '';
Expand All @@ -30,6 +31,7 @@ test(`Email Field - Visual and Behaviour`, async ({ page }) => {

const inputField = emailField.locator('#inputField');

// Update component value.
const value = '[email protected]';
await inputField.type(value);

Expand All @@ -40,6 +42,37 @@ test(`Email Field - Visual and Behaviour`, async ({ page }) => {
});
});

test(`Email Field - Max Length Behaviour`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/email-field/');
await page.evaluate(() => document.fonts.ready);

const container = page.locator('.Max_Length');
const emailField = container.locator('[data-testid]').first();
emailField.evaluate(async (t: EmailField) => {
t.value = '';
t.maxLength = 4;
await t.updateComplete;
});

// Confirm that the component matches the provided screenshot.
await expect(emailField).toHaveScreenshot('email-field.png');

const inputFn = await mockEventListener(emailField, 'input');

const inputField = emailField.locator('#inputField');

const typedValue = '[email protected]';
const value = 'mail';
await inputField.type(typedValue);

await expect(emailField).toHaveScreenshot('email-field-value.png');
await expect(inputField).toHaveValue(value);

await expect(inputFn).toBeCalledTimes(typedValue.length);
});
});

test('Email Field - Label Behaviour', testLabelBehaviour('omni-email-field'));
test('Email Field - Hint Behaviour', testHintBehaviour('omni-email-field'));
test('Email Field - Error Behaviour', testErrorBehaviour('omni-email-field'));
Expand Down
39 changes: 36 additions & 3 deletions src/email-field/EmailField.stories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { html, nothing } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import {
LabelStory,
Expand All @@ -16,13 +17,17 @@ import { ifNotEmpty } from '../utils/Directives.js';
import { assignToSlot, ComponentStoryFormat, getSourceFromLit } from '../utils/StoryUtils.js';

import './EmailField.js';
interface Args extends BaseArgs {
maxLength: number;
}

export const Interactive: ComponentStoryFormat<BaseArgs> = {
render: (args: BaseArgs) => html`
export const Interactive: ComponentStoryFormat<Args> = {
render: (args: Args) => html`
<omni-email-field
data-testid="test-email-field"
label="${ifNotEmpty(args.label)}"
value="${args.value}"
max-length=${ifDefined(args.maxLength)}
hint="${ifNotEmpty(args.hint)}"
error="${ifNotEmpty(args.error)}"
?disabled="${args.disabled}"
Expand Down Expand Up @@ -51,7 +56,35 @@ export const Interactive: ComponentStoryFormat<BaseArgs> = {
clearable: false,
prefix: '',
suffix: '',
clear: ''
clear: '',
maxLength: undefined
}
};

export const Max_Length: ComponentStoryFormat<Args> = {
render: (args: Args) => html`
<omni-email-field
data-testid="test-email-field"
label="${ifNotEmpty(args.label)}"
value="${args.value}"
max-length=${ifDefined(args.maxLength)}>
</omni-email-field>
`,
frameworkSources: [
{
framework: 'React',
load: (args) => `import { OmniEmailField } from "@capitec/omni-components-react/email-field";
const App = () => <OmniEmailField${args.label ? ` label='${args.label}'` : ''}${args.value ? ` value='${args.value}'` : ''}${
args.maxLength ? ` max-length='${args.maxLength}'` : ''
}/>;`
}
],
name: 'Max Length',
description: 'Limit the character input length based on the value provided to the email field.',
args: {
label: 'Max Length',
maxLength: 5
}
};

Expand Down
32 changes: 31 additions & 1 deletion src/email-field/EmailField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { OmniFormElement } from '../core/OmniFormElement.js';
* <omni-email-field
* label="Enter a value"
* value="[email protected]"
* max-length: 5
* hint="Required"
* error="Field level error message"
* disabled>
Expand All @@ -36,6 +37,8 @@ import { OmniFormElement } from '../core/OmniFormElement.js';
*
* @cssprop --omni-email-field-disabled-font-color - Email field disabled font color.
* @cssprop --omni-email-field-error-font-color - Email field error font color.
*
* @cssprop --omni-email-field-autofill-hover-transition - Email field suggestions input hover color.
*/
@customElement('omni-email-field')
export class EmailField extends OmniFormElement {
Expand All @@ -48,6 +51,12 @@ export class EmailField extends OmniFormElement {
*/
@property({ type: Boolean, reflect: true, attribute: 'no-native-keyboard' }) noNativeKeyboard?: boolean;

/**
* Maximum character input length.
* @attr [max-length]
*/
@property({ type: Number, reflect: true, attribute: 'max-length' }) maxLength?: number;

override connectedCallback() {
super.connectedCallback();
this.addEventListener('input', this._keyInput.bind(this), {
Expand All @@ -58,6 +67,15 @@ export class EmailField extends OmniFormElement {
});
}

// If a value is bound when the component is first updated slice the value based on the max length.
protected override async firstUpdated(): Promise<void> {
if (this.value !== null && this.value !== undefined) {
if (this.maxLength) {
this._inputElement!.value = String(this.value).slice(0, this.maxLength);
}
}
}

override focus(options?: FocusOptions | undefined): void {
if (this._inputElement) {
this._inputElement.focus(options);
Expand All @@ -74,6 +92,12 @@ export class EmailField extends OmniFormElement {

_keyInput() {
const input = this._inputElement as HTMLInputElement;
// If the input has a value and the max length property is set then slice the value according to the max length.
if (input?.value && this.maxLength) {
if (input.value.length > this.maxLength) {
input.value = input.value.slice(0, this.maxLength);
}
}
this.value = input.value;
}

Expand Down Expand Up @@ -109,7 +133,13 @@ export class EmailField extends OmniFormElement {
.field.error {
color: var(--omni-email-field-error-font-color, var(--omni-font-color));
}
}
/* Grant the ability to set the hover color when cursor hovers over auto selectable options */
input:-webkit-autofill,
input:-webkit-autofill:focus {
transition: var(--omni-email-field-autofill-hover-transition) !important;
}
`
];
}
Expand Down
2 changes: 2 additions & 0 deletions src/email-field/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Email input control, used in forms for input validation and to display correct v
| `hint` | `hint` | | `string \| undefined` | | Hint message to assist the user. |
| `label` | `label` | | `string \| undefined` | | Text label. |
| `lang` | | | `string` | | |
| `maxLength` | `max-length` | | `number \| undefined` | | Maximum character input length. |
| `noNativeKeyboard` | `no-native-keyboard` | | `boolean \| undefined` | | Disables native on screen keyboards for the component. |
| `override` | `override` | | | | Used to set the base direction of text for display |
| `styles` | | readonly | `CSSResultGroup[]` | | |
Expand Down Expand Up @@ -57,6 +58,7 @@ Email input control, used in forms for input validation and to display correct v
| `--omni-container-font-family` | Container font family. |
| `--omni-container-height` | Container height. |
| `--omni-container-width` | Container width. |
| `--omni-email-field-autofill-hover-transition` | Email field suggestions input hover color. |
| `--omni-email-field-disabled-font-color` | Email field disabled font color. |
| `--omni-email-field-error-font-color` | Email field error font color. |
| `--omni-email-field-font-color` | Email field font color. |
Expand Down
4 changes: 4 additions & 0 deletions src/icon/Icon.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ test(`Icon - Visual`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/icon/');

// Locate the icon component.
const icon = page.locator('.Interactive').getByTestId('test-icon');

await expect(icon).toHaveScreenshot('icon-initial.png');
Expand All @@ -14,6 +15,7 @@ test(`Icon - Local Source Visual`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/icon/');

// Locate the icon component.
const icon = page.locator('.Local_Source').getByTestId('test-icon');

await expect(icon).toHaveScreenshot('icon-initial.png');
Expand All @@ -24,6 +26,7 @@ test(`Icon - Remote Source Visual`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/icon/');

// Locate the icon component.
const icon = page.locator('.Remote_Source').getByTestId('test-icon');

await expect(icon).toHaveScreenshot('icon-initial.png');
Expand All @@ -44,6 +47,7 @@ test(`Icon - Asymmetrical Visual and Behaviour`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/icon/');

// Locate the icon component.
const icon = page.locator('.Asymmetrical').getByTestId('test-icon');

const svg = icon.locator('svg');
Expand Down
2 changes: 2 additions & 0 deletions src/modal/Modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import '../render-element/RenderElement.js';
* @cssprop --omni-modal-container-padding - Padding for modal content container.
* @cssprop --omni-modal-container-box-shadow - Box shadow for modal content container.
* @cssprop --omni-modal-max-width - Max width for modal content container.
* @cssprop --omni-modal-min-width - Min width for modal content container.
* @cssprop --omni-modal-max-height - Max height for modal content container.
*
* @cssprop --omni-modal-header-font-color - Font color for modal header.
Expand Down Expand Up @@ -254,6 +255,7 @@ export class Modal extends OmniElement {
background: transparent;
box-shadow: var(--omni-modal-container-box-shadow);
max-width: var(--omni-modal-max-width,100%);
min-width: var(--omni-modal-min-width, auto);
max-height: var(--omni-modal-max-height, 100%);
}
Expand Down
1 change: 1 addition & 0 deletions src/modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Control to display modal content with optional header and footer content.
| `--omni-modal-header-padding-top` | Top padding for modal header. |
| `--omni-modal-max-height` | Max height for modal content container. |
| `--omni-modal-max-width` | Max width for modal content container. |
| `--omni-modal-min-width` | Min width for modal content container. |
| `--omni-modal-no-footer-body-border-bottom-radius` | Bottom border radius for modal body when there is no footer. |
| `--omni-modal-no-header-body-border-top-radius` | Top border radius for modal body when there is no header. |
| `--omni-theme-accent-active-color` | Theme accent active color. |
Expand Down
33 changes: 33 additions & 0 deletions src/number-field/NumberField.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ test(`Number Field - Visual and Behaviour`, async ({ page }) => {
await page.goto('/components/number-field/');
await page.evaluate(() => document.fonts.ready);

// Locate number field component.
const numberField = page.locator('[data-testid]').first();
numberField.evaluate(async (t: NumberField) => {
t.value = '';
Expand All @@ -40,6 +41,38 @@ test(`Number Field - Visual and Behaviour`, async ({ page }) => {
});
});

test(`Number Field - Max Length Behaviour`, async ({ page }) => {
await withCoverage(page, async () => {
await page.goto('/components/number-field/');
await page.evaluate(() => document.fonts.ready);

const container = page.locator('.Max_Length');
const numberField = container.locator('[data-testid]').first();
numberField.evaluate(async (t: NumberField) => {
t.value = '';
t.maxLength = 4;
await t.updateComplete;
});

// Confirm that the component matches the provided screenshot.
await expect(numberField).toHaveScreenshot('number-field.png');

const inputFn = await mockEventListener(numberField, 'input');

const inputField = numberField.locator('#inputField');

// Update the value of the number field.
const typedValue = '12345';
const value = '1234';
await inputField.type(typedValue);

await expect(numberField).toHaveScreenshot('number-field-value.png');
await expect(inputField).toHaveValue(value);

await expect(inputFn).toBeCalledTimes(typedValue.length);
});
});

test('Number Field - Label Behaviour', testLabelBehaviour('omni-number-field'));
test('Number Field - Hint Behaviour', testHintBehaviour('omni-number-field'));
test('Number Field - Error Behaviour', testErrorBehaviour('omni-number-field'));
Expand Down
39 changes: 36 additions & 3 deletions src/number-field/NumberField.stories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { html, nothing } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import {
LabelStory,
Expand All @@ -16,13 +17,17 @@ import { ifNotEmpty } from '../utils/Directives.js';
import { assignToSlot, ComponentStoryFormat, getSourceFromLit } from '../utils/StoryUtils.js';

import './NumberField.js';
interface Args extends BaseArgs {
maxLength: number;
}

export const Interactive: ComponentStoryFormat<BaseArgs> = {
render: (args: BaseArgs) => html`
export const Interactive: ComponentStoryFormat<Args> = {
render: (args: Args) => html`
<omni-number-field
data-testid="test-number-field"
label="${ifNotEmpty(args.label)}"
value="${args.value}"
max-length=${ifDefined(args.maxLength)}
hint="${ifNotEmpty(args.hint)}"
error="${ifNotEmpty(args.error)}"
?disabled="${args.disabled}"
Expand Down Expand Up @@ -50,7 +55,35 @@ export const Interactive: ComponentStoryFormat<BaseArgs> = {
disabled: false,
prefix: '',
suffix: '',
clear: ''
clear: '',
maxLength: undefined
}
};

export const Max_Length: ComponentStoryFormat<Args> = {
render: (args: Args) => html`
<omni-number-field
data-testid="test-number-field"
label="${ifNotEmpty(args.label)}"
value="${args.value}"
max-length=${ifDefined(args.maxLength)}>
</omni-number-field>
`,
frameworkSources: [
{
framework: 'React',
load: (args) => `import { OmniNumberField } from "@capitec/omni-components-react/number-field";
const App = () => <OmniNumberField${args.label ? ` label='${args.label}'` : ''}${args.value ? ` value='${args.value}'` : ''}${
args.maxLength ? ` max-length='${args.maxLength}'` : ''
}/>;`
}
],
name: 'Max Length',
description: 'Limit the numeric input length based on the value provided.',
args: {
label: 'Max Length',
maxLength: 5
}
};

Expand Down
Loading

0 comments on commit 4a5bf4b

Please sign in to comment.