Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
18fa942
upgrade packages #TECH-409
neotob Aug 22, 2025
aed5619
Merge branch 'main' into feature/tech-409
neotob Aug 22, 2025
583bce4
fix
neotob Aug 22, 2025
e5fb770
verbose
neotob Aug 22, 2025
ef20d93
try
neotob Aug 22, 2025
e21a8d5
fix
neotob Aug 22, 2025
454ca81
try
neotob Aug 22, 2025
29e7716
try
neotob Aug 22, 2025
b24af05
try
neotob Aug 25, 2025
2022feb
try
neotob Aug 25, 2025
974a71f
test
neotob Aug 26, 2025
d095335
test
neotob Aug 26, 2025
dc6ae92
try
neotob Aug 26, 2025
ad69c47
try
neotob Aug 26, 2025
e4f90aa
test
neotob Aug 26, 2025
c4bb7c8
try
neotob Aug 27, 2025
91638d3
try
neotob Aug 27, 2025
32cc216
fix
neotob Aug 27, 2025
d5cb6b0
fix
neotob Aug 27, 2025
02d6c00
fix
neotob Sep 5, 2025
c4bd1d3
Merge branch 'main' into feature/tech-409
neotob Sep 5, 2025
09ab31c
update
neotob Sep 5, 2025
d15ec88
update storybook
neotob Sep 5, 2025
5460335
fix
neotob Sep 24, 2025
dbd8ee0
Merge main
neotob Sep 24, 2025
55f60d7
fix
neotob Sep 24, 2025
90295d1
Merge branch 'main' into feature/tech-409
neotob Feb 13, 2026
ffdb93c
up
neotob Feb 13, 2026
c2caca8
t
neotob Feb 13, 2026
7016163
fix
neotob Feb 13, 2026
3470cb4
t
neotob Feb 16, 2026
67d3a32
t
neotob Feb 16, 2026
392e3d7
t
neotob Feb 16, 2026
a9accb9
t
neotob Feb 16, 2026
0f67ee2
t
neotob Feb 16, 2026
e5c2ebf
t
neotob Feb 16, 2026
2663107
update
neotob Feb 19, 2026
49ce9c9
t
neotob Feb 20, 2026
8271798
f
neotob Feb 20, 2026
96bf265
x
manni497 Feb 23, 2026
dda0285
x
manni497 Feb 23, 2026
3fbe49f
t
neotob Feb 24, 2026
02e190a
x
manni497 Feb 24, 2026
ebbbd65
x
manni497 Feb 24, 2026
00073f3
x
manni497 Feb 24, 2026
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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x, 22.x]
node-version: [20.x, 22.x, 24.x]
react-version: [^18.2.0, ^19.0.0]
steps:
- uses: actions/checkout@v4

Expand All @@ -84,6 +85,7 @@ jobs:
cache: "yarn"

- run: yarn --frozen-lockfile
- run: yarn add react@${{ matrix.react-version }} react-dom@${{ matrix.react-version }} --dev
- run: yarn lint
- run: yarn build
- run: yarn prettier-check
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ storybook-static
terraform

.npmrc
*storybook.log

# Ignore vs folder
.vs
.vs
16 changes: 0 additions & 16 deletions .storybook/main.js

This file was deleted.

24 changes: 24 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { StorybookConfig } from "@storybook/react-webpack5";
import { TsconfigPathsPlugin } from "tsconfig-paths-webpack-plugin";

const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: ["@storybook/addon-webpack5-compiler-swc", "@storybook/addon-docs"],
framework: {
name: "@storybook/react-webpack5",
options: {},
},
webpackFinal: (config) => {
if (config && config.resolve) {
config.resolve.plugins = [
...(config.resolve.plugins || []),
new TsconfigPathsPlugin({
extensions: config.resolve.extensions,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
];
}
return config;
},
};
export default config;
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- updated most dependencies to newest possible version

## [3.17.0] - 2026-02-09

### Fixed
Expand Down Expand Up @@ -44,7 +48,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `TelephoneNumberInput` countries order, in order to be alphabetically sorted.
- Required field label on `FormGroupLayoutLabel`, `ColorPicker`, `TelephoneNumberInput`, `TypeaheadTextField` (hence `StaticTypeaheadInput` and `AsyncTypeaheadInput`) in order to display \* also on nested and array fields.

1. `requiredFields` can still accept a `FieldPath<T>[]`
2. In order to be complaint with `FieldPath` react-hook-form type (`object.${number}.property`) array properties provide a wildcard:

Expand Down Expand Up @@ -250,7 +253,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- :boom: `AsyncTypeAheadInput` based on MUI Autocomplete component.
- :boom: renamed `AsyncTypeaheadProps` to `AsyncTypeaheadInputProps`.

1. The component is by default **form** controlled. However, updating values using form methods could lead to an unexpected behavior because MUI library requires consistency between options and value. In order to manually to control the input, a ref is exposed which allows to mutually modify input value and form value.
2. `inputRef` is exposed to clear, reset or set new selected options, as mentioned in point 1.
3. `defaultSelected` options is still needed as in previous version.
Expand All @@ -260,7 +262,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7. `onInputChange` exposes the reason why the input-text changes. Check whether reason is `input` for checking only the typing event.

- :boom: `StaticTypeAheadInput` based on MUI Autocomplete component.

1. The component is fully **form** controlled.
2. In order to control input value, use form methods being sure to be consistent between the set value and available options. Therefore, any input ref is exposed anymore.
3. No need to specify a `defaultSelected` option according to point 1. The input automatically select options based on form value.
Expand Down
7 changes: 4 additions & 3 deletions cypress/cypress/component/AutoSubmit/AutoSumbit.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
import { Form, Input } from "react-hook-form-components";
import * as yup from "yup";
import { generateOptions } from "../../helpers/typeahead";
import { mount } from "cypress/react";

it("radio button multiple autosave works", () => {
const name1 = faker.random.alpha(10);
Expand All @@ -17,7 +18,7 @@ it("radio button multiple autosave works", () => {
const { objectOptions: options1 } = generateOptions(faker.datatype.number({ min: 1, max: 10 }));
const { objectOptions: options2 } = generateOptions(faker.datatype.number({ min: 1, max: 10 }));

cy.mount(
mount(
<>
<Form onSubmit={cy.spy().as("onSubmitSpy1")} resolver={yupResolver(schema1)} autoSubmitConfig={{ wait: 500 }}>
<Input type="radio" label="hello" name={name1} helpText="help" options={options1} />
Expand Down Expand Up @@ -59,7 +60,7 @@ it("radio button autosave only once", () => {

const { objectOptions: options } = generateOptions(faker.datatype.number({ min: 1, max: 10 }));

cy.mount(
mount(
<Form onSubmit={cy.spy().as("onSubmitSpy")} resolver={yupResolver(schema)} autoSubmitConfig={{ wait: 500 }}>
<Input type="radio" label="hello" name={name} helpText="help" options={options} />
</Form>,
Expand All @@ -83,7 +84,7 @@ it("text input autosave only once", () => {

const randomText = faker.random.alphaNumeric(10);

cy.mount(
mount(
<Form onSubmit={cy.spy().as("onSubmitSpy")} resolver={yupResolver(schema)} autoSubmitConfig={{ wait: 500 }}>
<Input type="text" label={name} name={name} />
</Form>,
Expand Down
2 changes: 1 addition & 1 deletion cypress/cypress/component/ClassName/ClassName.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Form, Input, DatePickerInput, AsyncTypeaheadInput, StaticTypeaheadInput, FormattedInput } from "react-hook-form-components";
import { faker } from "@faker-js/faker";
import { fetchMock, generateOptions } from "../../helpers/typeahead";
import { mount } from "cypress/react18";
import { mount } from "cypress/react";

it("input has correct classname", () => {
const name = faker.random.alpha(10);
Expand Down
2 changes: 1 addition & 1 deletion cypress/cypress/component/ColorPicker/ColorPicker.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Form, ColorPickerInput } from "react-hook-form-components";
import { faker } from "@faker-js/faker";
import { mount } from "cypress/react18";
import { mount } from "cypress/react";

it("select correct color by specific format", () => {
const hexName = faker.random.alpha(10);
Expand Down
35 changes: 18 additions & 17 deletions cypress/cypress/component/Datepicker/DatePickerInput.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* eslint-disable max-lines */
import { DatePickerInput, Form, getUtcTimeZeroDate } from "react-hook-form-components";
import "react-datepicker/dist/react-datepicker.css";
import "react-hook-form-components/styles.css";
import { faker } from "@faker-js/faker";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { faCalendar } from "@fortawesome/free-solid-svg-icons";
import { faCalendar, faClock } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, InputGroupText } from "reactstrap";
import { Button, InputGroupText } from "@neolution-ch/reactstrap";
import { mount } from "cypress/react";

import { SinonSpy } from "cypress/types/sinon";
import { useRef, useEffect, FC } from "react";
Expand All @@ -19,7 +19,7 @@ it("selecting today works", () => {
[name]: yup.date().required(),
});

cy.mount(
mount(
<Form onSubmit={cy.spy().as("onSubmitSpy")} resolver={yupResolver(schema)}>
<DatePickerInput name={name} label={name} />

Expand Down Expand Up @@ -51,7 +51,7 @@ it("setting intial value as iso string works", () => {
console.log(JSON.stringify(values));
};

cy.mount(
mount(
<Form
onSubmit={cy.spy(x).as("onSubmitSpy")}
resolver={yupResolver(schema)}
Expand Down Expand Up @@ -80,7 +80,7 @@ it("setting intial value as date object works", () => {
[name]: yup.date().required(),
});

cy.mount(
mount(
<Form
onSubmit={cy.spy().as("onSubmitSpy")}
resolver={yupResolver(schema)}
Expand All @@ -104,7 +104,7 @@ it("setting intial value as date object works", () => {
it("is disabled", () => {
const name = faker.random.word();

cy.mount(
mount(
<Form
onSubmit={() => {
// Do nothing
Expand All @@ -123,7 +123,7 @@ it("contains calendar icon if provided in DateInput", () => {
[name]: yup.date(),
});

cy.mount(
mount(
<Form
onSubmit={() => {
// Nothing to do
Expand All @@ -133,21 +133,22 @@ it("contains calendar icon if provided in DateInput", () => {
<DatePickerInput
name={name}
label={name}
addonLeft={
addonRight={
<InputGroupText>
<FontAwesomeIcon icon={faCalendar} />
</InputGroupText>
}
addonRight={
addonLeft={
<InputGroupText>
<FontAwesomeIcon icon={faCalendar} />
<FontAwesomeIcon icon={faClock} />
</InputGroupText>
}
/>
</Form>,
);

cy.get(`label[for=${name}]`).parent().find("svg[data-icon=calendar]");
cy.get(`label[for=${name}]`).parent().find("svg[data-icon=clock]");
});

it("not contains calendar icon if not provided in DateInput", () => {
Expand All @@ -156,7 +157,7 @@ it("not contains calendar icon if not provided in DateInput", () => {
[name]: yup.date(),
});

cy.mount(
mount(
<Form
onSubmit={() => {
// Nothing to do
Expand Down Expand Up @@ -186,7 +187,7 @@ it("passing an IANA timezone works", () => {
const fixedDate = new Date(isoInputDate);
const inputJsonString = JSON.stringify(fixedDate);

cy.mount(
mount(
<Form<FormFields>
defaultValues={{
[name]: fixedDate,
Expand Down Expand Up @@ -225,7 +226,7 @@ it("passing the ref works", () => {
});

const DatePickerWithRef: FC = () => {
const ref = useRef<ReactDatePickers<never, undefined>>(null);
const ref = useRef<ReactDatePickers>(null);

useEffect(() => {
if (ref && ref.current) {
Expand All @@ -248,7 +249,7 @@ it("passing the ref works", () => {
);
};

cy.mount(<DatePickerWithRef />);
mount(<DatePickerWithRef />);

cy.get(".react-datepicker-popper").should("be.visible");
});
Expand All @@ -259,7 +260,7 @@ it("addon works as a function (with onClick)", () => {
[name]: yup.date(),
});

cy.mount(
mount(
<Form
onSubmit={() => {
// Nothing to do
Expand Down
4 changes: 2 additions & 2 deletions cypress/cypress/component/Disabled/Disabled.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
StaticTypeaheadInput,
useFormContext,
} from "react-hook-form-components";
import { Input as ReactstrapInput, Label } from "reactstrap";
import { mount } from "cypress/react18";
import { Input as ReactstrapInput, Label } from "@neolution-ch/reactstrap";
import { mount } from "cypress/react";

it("disable all fields when readonly attribute is set", () => {
const inputName = faker.random.alpha(10);
Expand Down
5 changes: 3 additions & 2 deletions cypress/cypress/component/Form/Form.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Form, FormattedInput } from "react-hook-form-components";
import { NumericFormatProps, numericFormatter } from "react-number-format";
import { useRef } from "react";
import * as yup from "yup";
import { mount } from "cypress/react";

const numericFormat: NumericFormatProps = {
thousandSeparator: faker.random.alpha(),
Expand All @@ -30,7 +31,7 @@ it("submitting through the ref works", () => {
</Form>
);
};
cy.mount(<FormWithRef />);
mount(<FormWithRef />);

cy.contains("label", name).click();
cy.focused().type(randomNumber.toString());
Expand Down Expand Up @@ -60,7 +61,7 @@ it("submitting through the ref checks for yup errors", () => {
</Form>
);
};
cy.mount(<FormWithRef />);
mount(<FormWithRef />);

cy.contains("label", name).click();
cy.focused().type(randomNumber.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { faker } from "@faker-js/faker";
import { yupResolver } from "@hookform/resolvers/yup";
import { Form, Input, StaticTypeaheadInput, AsyncTypeaheadInput, DatePickerInput, FormattedInput } from "react-hook-form-components";
import * as yup from "yup";
import { mount } from "cypress/react18";
import { mount } from "cypress/react";

it("adding * character if string label works", () => {
const name = faker.random.alpha(10);
Expand Down
Loading
Loading