diff --git a/flow-components-bom/pom.xml b/flow-components-bom/pom.xml index 76be01ecbdf..00d90a2d8b7 100644 --- a/flow-components-bom/pom.xml +++ b/flow-components-bom/pom.xml @@ -417,6 +417,16 @@ vaadin-side-nav-testbench ${project.version} + + com.vaadin + vaadin-slider-flow + ${project.version} + + + com.vaadin + vaadin-slider-testbench + ${project.version} + com.vaadin vaadin-split-layout-flow diff --git a/pom.xml b/pom.xml index a9e2a00523c..a9b5100b088 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ vaadin-spreadsheet-flow-parent vaadin-field-highlighter-flow-parent vaadin-side-nav-flow-parent + vaadin-slider-flow-parent vaadin-master-detail-layout-flow-parent vaadin-ai-components-flow-parent diff --git a/vaadin-slider-flow-parent/LICENSE b/vaadin-slider-flow-parent/LICENSE new file mode 100644 index 00000000000..a8cdb96073f --- /dev/null +++ b/vaadin-slider-flow-parent/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2000-2026 Vaadin Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vaadin-slider-flow-parent/README.md b/vaadin-slider-flow-parent/README.md new file mode 100644 index 00000000000..4ca53b4383c --- /dev/null +++ b/vaadin-slider-flow-parent/README.md @@ -0,0 +1,20 @@ +# Slider component for Vaadin Flow + +This project is the Component wrapper implementation of [``](https://github.com/vaadin/web-components/tree/main/packages/slider) +element for use from the server side with [Vaadin Flow](https://github.com/vaadin/flow). + +## Using the component in a Flow application + +To use the component in an application using maven, +add the following dependency to your `pom.xml`: +``` + + com.vaadin + vaadin-slider-flow + ${component.version} + +``` + +## License + +Apache License 2.0 diff --git a/vaadin-slider-flow-parent/pom.xml b/vaadin-slider-flow-parent/pom.xml new file mode 100644 index 00000000000..9aa460c95ad --- /dev/null +++ b/vaadin-slider-flow-parent/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + com.vaadin + vaadin-flow-components + 25.1-SNAPSHOT + + vaadin-slider-flow-parent + pom + Vaadin Slider Parent + Vaadin Slider Parent + + vaadin-slider-flow + vaadin-slider-testbench + + + + + default + + + !release + + + + vaadin-slider-flow-integration-tests + + + + diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/pom.xml b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/pom.xml new file mode 100644 index 00000000000..0ab323d8c2e --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + + com.vaadin + vaadin-slider-flow-parent + 25.1-SNAPSHOT + + vaadin-slider-integration-tests + war + Vaadin Slider Integration Tests + Vaadin Slider Integration Tests + + + com.vaadin + flow-client + + + com.vaadin + flow-html-components + + + com.vaadin + flow-test-generic + test + + + com.vaadin + flow-test-util + test + + + com.vaadin + vaadin-dev-server + + + com.vaadin + vaadin-flow-components-test-util + ${project.version} + test + + + com.vaadin + vaadin-slider-flow + ${project.version} + + + com.vaadin + vaadin-slider-testbench + ${project.version} + + + com.vaadin + vaadin-testbench-core + test + + + org.slf4j + slf4j-simple + + + + + + maven-clean-plugin + + + + ${project.basedir} + + package*.json + pnpm* + vite.generated.ts + types.d.ts + tsconfig.json + frontend/routes.tsx + frontend/App.tsx + + + + ${project.basedir}/node_modules + + + ${project.basedir}/frontend/generated + + + + + + maven-failsafe-plugin + + + maven-resources-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + true + + + + org.codehaus.mojo + properties-maven-plugin + + + maven-install-plugin + + true + + + + + + + build-frontend + + + !skipFrontend + + + + + + com.vaadin + flow-maven-plugin + + ./frontend + + + + + + + run-jetty + + + !skipJetty + + + + + + org.eclipse.jetty.ee10 + jetty-ee10-maven-plugin + + 5 + + + + + + + diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/BasicPage.java b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/BasicPage.java new file mode 100644 index 00000000000..7332b70b027 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/BasicPage.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.slider.Slider; +import com.vaadin.flow.router.Route; + +@Route("vaadin-slider/basic") +public class BasicPage extends Div { + + public BasicPage() { + Slider slider = new Slider(10, 200, 50); + slider.setStep(5); + add(slider); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicPage.java b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicPage.java new file mode 100644 index 00000000000..167d28bf100 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicPage.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.slider.RangeSlider; +import com.vaadin.flow.component.slider.RangeSliderValue; +import com.vaadin.flow.router.Route; + +@Route("vaadin-range-slider/basic") +public class RangeSliderBasicPage extends Div { + + public RangeSliderBasicPage() { + RangeSlider rangeSlider = new RangeSlider(10, 200, 5, + new RangeSliderValue(25, 150)); + add(rangeSlider); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/resources/vaadin-featureflags.properties b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/resources/vaadin-featureflags.properties new file mode 100644 index 00000000000..1cd3ee28642 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/main/resources/vaadin-featureflags.properties @@ -0,0 +1 @@ +com.vaadin.experimental.sliderComponent=true diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/BasicIT.java b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/BasicIT.java new file mode 100644 index 00000000000..2d507973d9e --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/BasicIT.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.flow.component.slider.testbench.SliderElement; +import com.vaadin.flow.testutil.TestPath; +import com.vaadin.tests.AbstractComponentIT; + +@TestPath("vaadin-slider/basic") +public class BasicIT extends AbstractComponentIT { + + private SliderElement slider; + + @Before + public void init() { + open(); + slider = $(SliderElement.class).first(); + } + + @Test + public void basicProperties() { + Assert.assertEquals(10, slider.getMin(), 0); + Assert.assertEquals(200, slider.getMax(), 0); + Assert.assertEquals(50, slider.getValue(), 0); + Assert.assertEquals(5, slider.getStep(), 0); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicIT.java b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicIT.java new file mode 100644 index 00000000000..913a11d32b3 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderBasicIT.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.flow.component.slider.testbench.RangeSliderElement; +import com.vaadin.flow.testutil.TestPath; +import com.vaadin.tests.AbstractComponentIT; + +@TestPath("vaadin-range-slider/basic") +public class RangeSliderBasicIT extends AbstractComponentIT { + + private RangeSliderElement rangeSlider; + + @Before + public void init() { + open(); + rangeSlider = $(RangeSliderElement.class).first(); + } + + @Test + public void basicProperties() { + Assert.assertEquals(10, rangeSlider.getMin(), 0); + Assert.assertEquals(200, rangeSlider.getMax(), 0); + Assert.assertEquals(5, rangeSlider.getStep(), 0); + Assert.assertEquals(25, rangeSlider.getStartValue(), 0); + Assert.assertEquals(150, rangeSlider.getEndValue(), 0); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/vite.config.ts b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/vite.config.ts new file mode 100644 index 00000000000..bd0ce4ce0ae --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow-integration-tests/vite.config.ts @@ -0,0 +1,16 @@ +// @ts-ignore can not be resolved until NPM packages are installed +import { defineConfig, UserConfigFn } from 'vite'; +// @ts-ignore can not be resolved until Flow generates base Vite config +import { vaadinConfig } from './vite.generated'; +import { sharedConfig, mergeConfigs } from '../../shared/shared-vite-config'; + +const customConfig: UserConfigFn = (env) => ({ + // Here you can add custom Vite parameters + // https://vitejs.dev/config/ +}); + +export default defineConfig((env) => mergeConfigs( + vaadinConfig(env), + sharedConfig(env), + customConfig(env) +)); diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/pom.xml b/vaadin-slider-flow-parent/vaadin-slider-flow/pom.xml new file mode 100644 index 00000000000..566208d8ebd --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + com.vaadin + vaadin-slider-flow-parent + 25.1-SNAPSHOT + + vaadin-slider-flow + jar + Vaadin Slider + Vaadin Slider + + -javaagent:${org.mockito:mockito-core:jar} + + + + com.vaadin + flow-server + provided + + + com.vaadin + flow-test-generic + test + + + com.vaadin + vaadin-flow-components-base + ${project.version} + + + com.vaadin + vaadin-flow-components-test-util + ${project.version} + test + + + jakarta.platform + jakarta.jakartaee-web-api + test + + + jakarta.servlet + jakarta.servlet-api + + + org.slf4j + slf4j-simple + test + + + + + + biz.aQute.bnd + bnd-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + + + attach-docs + + + with-docs + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.codehaus.mojo + build-helper-maven-plugin + + + + + + diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/ExperimentalFeatureException.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/ExperimentalFeatureException.java new file mode 100644 index 00000000000..ae2d76cf2b5 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/ExperimentalFeatureException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +/** + * An exception which is thrown when somebody attempts to use the {@link Slider} + * component without activating the associated feature flag first. + * + * @author Vaadin Ltd + */ +public class ExperimentalFeatureException extends RuntimeException { + public ExperimentalFeatureException() { + super("The Slider component is currently an experimental feature and needs to be " + + "explicitly enabled. The component can be enabled using Copilot, in the " + + "experimental features tab, or by adding a " + + "`src/main/resources/vaadin-featureflags.properties` file with the following content: " + + "`com.vaadin.experimental.sliderComponent=true`"); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSlider.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSlider.java new file mode 100644 index 00000000000..40692381b68 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSlider.java @@ -0,0 +1,385 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +import java.util.Arrays; +import java.util.Objects; + +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.function.SerializableBiFunction; +import com.vaadin.flow.internal.JacksonUtils; + +import tools.jackson.databind.node.ArrayNode; + +/** + * RangeSlider is an input field that allows the user to select a numeric range + * within bounds by dragging two handles along a track or using arrow keys for + * precise input. + * + * @author Vaadin Ltd. + */ +@Tag("vaadin-range-slider") +// @NpmPackage(value = "@vaadin/slider", version = "25.1.0-alpha1") +// @JsModule("@vaadin/slider/src/vaadin-range-slider.js") +public class RangeSlider extends SliderBase { + private static final double DEFAULT_MIN = 0; + private static final double DEFAULT_MAX = 100; + private static final double DEFAULT_STEP = 1; + + private static final SerializableBiFunction PARSER = ( + component, arrayValue) -> { + RangeSliderValue value = new RangeSliderValue( + arrayValue.get(0).asDouble(), arrayValue.get(1).asDouble()); + + return component.requireValidValue(value); + }; + + private static final SerializableBiFunction FORMATTER = ( + component, value) -> { + component.requireValidValue(value); + + return JacksonUtils + .listToJson(Arrays.asList(value.start(), value.end())); + }; + + /** + * Constructs a {@code RangeSlider} with range 0-100 and initial value + * 0-100. + *

+ * The step defaults to 1. + */ + public RangeSlider() { + this(DEFAULT_MIN, DEFAULT_MAX, DEFAULT_STEP, + new RangeSliderValue(DEFAULT_MIN, DEFAULT_MAX)); + } + + /** + * Constructs a {@code RangeSlider} with range 0-100, initial value 0-100, + * and a value change listener. + *

+ * The step defaults to 1. + * + * @param listener + * the value change listener + */ + public RangeSlider( + ValueChangeListener> listener) { + this(DEFAULT_MIN, DEFAULT_MAX, DEFAULT_STEP, + new RangeSliderValue(DEFAULT_MIN, DEFAULT_MAX), listener); + } + + /** + * Constructs a {@code RangeSlider} with the given range and initial value. + *

+ * The step defaults to 1. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + */ + public RangeSlider(double min, double max, RangeSliderValue value) { + this(min, max, DEFAULT_STEP, value); + } + + /** + * Constructs a {@code RangeSlider} with the given range, initial value, and + * a value change listener. + *

+ * The step defaults to 1. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public RangeSlider(double min, double max, RangeSliderValue value, + ValueChangeListener> listener) { + this(min, max, DEFAULT_STEP, value, listener); + } + + /** + * Constructs a {@code RangeSlider} with the given range, step, and initial + * value. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + */ + public RangeSlider(double min, double max, double step, + RangeSliderValue value) { + super(min, max, step, value, ArrayNode.class, PARSER, FORMATTER); + } + + /** + * Constructs a {@code RangeSlider} with the given range, step, initial + * value, and a value change listener. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public RangeSlider(double min, double max, double step, + RangeSliderValue value, + ValueChangeListener> listener) { + this(min, max, step, value); + addValueChangeListener(listener); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range 0-100, and + * initial value 0-100. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + */ + public RangeSlider(String label) { + this(); + setLabel(label); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range 0-100, + * initial value 0-100, and a value change listener. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + * @param listener + * the value change listener + */ + public RangeSlider(String label, + ValueChangeListener> listener) { + this(listener); + setLabel(label); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range, and initial + * value. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + */ + public RangeSlider(String label, double min, double max, + RangeSliderValue value) { + this(min, max, value); + setLabel(label); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range, initial + * value, and a value change listener. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public RangeSlider(String label, double min, double max, + RangeSliderValue value, + ValueChangeListener> listener) { + this(min, max, value, listener); + setLabel(label); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range, step, and + * initial value. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + */ + public RangeSlider(String label, double min, double max, double step, + RangeSliderValue value) { + this(min, max, step, value); + setLabel(label); + } + + /** + * Constructs a {@code RangeSlider} with the given label, range, step, + * initial value, and a value change listener. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public RangeSlider(String label, double min, double max, double step, + RangeSliderValue value, + ValueChangeListener> listener) { + this(min, max, step, value, listener); + setLabel(label); + } + + /** + * Sets the minimum value of the slider. + * + * @param min + * the minimum value + * @throws IllegalArgumentException + * if the min is greater than the max value + * @throws IllegalArgumentException + * if the current start value is below the new minimum value + */ + public void setMin(double min) { + if (getValue().start() < min) { + throw new IllegalArgumentException( + "The current start value {} is below the new minimum value {}" + .formatted(getValue().start(), min)); + } + + super.setMinDouble(min); + } + + /** + * Gets the minimum value of the slider. + * + * @return the minimum value + */ + public double getMin() { + return getMinDouble(); + } + + /** + * Sets the maximum value of the slider. + * + * @param max + * the maximum value + * @throws IllegalArgumentException + * if the max is less than the min value + * @throws IllegalArgumentException + * if the current end value exceeds the new maximum value + */ + public void setMax(double max) { + if (getValue().end() > max) { + throw new IllegalArgumentException( + "The current end value {} exceeds the new maximum value {}" + .formatted(getValue().end(), max)); + } + + super.setMaxDouble(max); + } + + /** + * Gets the maximum value of the slider. + * + * @return the maximum value + */ + public double getMax() { + return getMaxDouble(); + } + + /** + * Sets the step value of the slider. The step is the amount the value + * changes when the user moves a handle. + * + * @param step + * the step value + * @throws IllegalArgumentException + * if the step is less than or equal to zero + * @throws IllegalArgumentException + * if the current value is not aligned with the new step value + */ + public void setStep(double step) { + if (getValue().start() % step != 0 || getValue().end() % step != 0) { + throw new IllegalArgumentException( + "The current value [{}, {}] is not aligned with the new step value {}" + .formatted(getValue().start(), getValue().end(), + step)); + } + + super.setStepDouble(step); + } + + /** + * Gets the step value of the slider. + * + * @return the step value + */ + public double getStep() { + return getStepDouble(); + } + + private RangeSliderValue requireValidValue(RangeSliderValue value) { + Objects.requireNonNull(value, "Value cannot be null"); + + if (value.start() < getMin() || value.end() > getMax()) { + throw new IllegalArgumentException( + "The value must be between min and max"); + } + + if (value.start() % getStep() != 0 || value.end() % getStep() != 0) { + throw new IllegalArgumentException( + "The value is not aligned with the step value"); + } + + return value; + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSliderValue.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSliderValue.java new file mode 100644 index 00000000000..76a9d7e3300 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/RangeSliderValue.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +import java.io.Serializable; + +/** + * Represents the value of a {@link RangeSlider}, consisting of a start and end + * value. + * + * @param start + * the start value of the range + * @param end + * the end value of the range + * + * @author Vaadin Ltd + */ +public record RangeSliderValue(double start, + double end) implements Serializable { + + /** + * Creates a new RangeSliderValue with the given start and end values. + * + * @param start + * the start value of the range + * @param end + * the end value of the range + * @throws IllegalArgumentException + * if start is greater than end + */ + public RangeSliderValue { + if (start > end) { + throw new IllegalArgumentException( + "Start value cannot be greater than end value"); + } + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/Slider.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/Slider.java new file mode 100644 index 00000000000..a7301acb602 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/Slider.java @@ -0,0 +1,363 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +import java.util.Objects; + +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.function.SerializableBiFunction; + +/** + * Slider is an input field that allows the user to select a numeric value + * within a range by dragging a handle along a track or using arrow keys for + * precise input. + * + * @author Vaadin Ltd. + */ +@Tag("vaadin-slider") +// @NpmPackage(value = "@vaadin/slider", version = "25.1.0-alpha1") +// @JsModule("@vaadin/slider/src/vaadin-slider.js") +public class Slider extends SliderBase { + private static final double DEFAULT_MIN = 0; + private static final double DEFAULT_MAX = 100; + private static final double DEFAULT_STEP = 1; + + private static final SerializableBiFunction PARSER = (component, value) -> { + return component.requireValidValue(value); + }; + + private static final SerializableBiFunction FORMATTER = (component, value) -> { + return component.requireValidValue(value); + }; + + /** + * Constructs a {@code Slider} with range 0-100 and initial value 0. + *

+ * The step defaults to 1. + */ + public Slider() { + this(DEFAULT_MIN, DEFAULT_MAX, DEFAULT_STEP, DEFAULT_MIN); + } + + /** + * Constructs a {@code Slider} with range 0-100, initial value 0, and a + * value change listener. + *

+ * The step defaults to 1. + * + * @param listener + * the value change listener + */ + public Slider( + ValueChangeListener> listener) { + this(DEFAULT_MIN, DEFAULT_MAX, DEFAULT_STEP, DEFAULT_MIN, listener); + } + + /** + * Constructs a {@code Slider} with the given range and initial value. + *

+ * The step defaults to 1. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + */ + public Slider(double min, double max, double value) { + this(min, max, DEFAULT_STEP, value); + } + + /** + * Constructs a {@code Slider} with the given range, initial value, and a + * value change listener. + *

+ * The step defaults to 1. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public Slider(double min, double max, double value, + ValueChangeListener> listener) { + this(min, max, DEFAULT_STEP, value, listener); + } + + /** + * Constructs a {@code Slider} with the given range, step, and initial + * value. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + */ + public Slider(double min, double max, double step, double value) { + super(min, max, step, value, Double.class, PARSER, FORMATTER); + } + + /** + * Constructs a {@code Slider} with the given range, step, initial value, + * and a value change listener. + * + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public Slider(double min, double max, double step, double value, + ValueChangeListener> listener) { + this(min, max, step, value); + addValueChangeListener(listener); + } + + /** + * Constructs a {@code Slider} with the given label, range 0-100, and + * initial value 0. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + */ + public Slider(String label) { + this(); + setLabel(label); + } + + /** + * Constructs a {@code Slider} with the given label, range 0-100, initial + * value 0, and a value change listener. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + * @param listener + * the value change listener + */ + public Slider(String label, + ValueChangeListener> listener) { + this(listener); + setLabel(label); + } + + /** + * Constructs a {@code Slider} with the given label, range, and initial + * value. + *

+ * The step defaults to 1. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + */ + public Slider(String label, double min, double max, double value) { + this(min, max, value); + setLabel(label); + } + + /** + * Constructs a {@code Slider} with the given label, range, initial value, + * and a value change listener. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public Slider(String label, double min, double max, double value, + ValueChangeListener> listener) { + this(min, max, value, listener); + setLabel(label); + } + + /** + * Constructs a {@code Slider} with the given label, range, step, and + * initial value. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + */ + public Slider(String label, double min, double max, double step, + double value) { + this(min, max, step, value); + setLabel(label); + } + + /** + * Constructs a {@code Slider} with the given label, range, step, initial + * value, and a value change listener. + * + * @param label + * the text to set as the label + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + * @param listener + * the value change listener + */ + public Slider(String label, double min, double max, double step, + double value, + ValueChangeListener> listener) { + this(min, max, step, value, listener); + setLabel(label); + } + + /** + * Sets the minimum value of the slider. + * + * @param min + * the minimum value + * @throws IllegalArgumentException + * if the min is greater than the max value + * @throws IllegalArgumentException + * if the current value is less than the new minimum value + */ + public void setMin(double min) { + if (getValue() < min) { + throw new IllegalArgumentException( + "The current value {} is less than the new minimum value {}".formatted( + getValue(), min)); + } + + super.setMinDouble(min); + } + + /** + * Gets the minimum value of the slider. + * + * @return the minimum value + */ + public double getMin() { + return getMinDouble(); + } + + /** + * Sets the maximum value of the slider. + * + * @param max + * the maximum value + * @throws IllegalArgumentException + * if the max is less than the min value + * @throws IllegalArgumentException + * if the current value is greater than the new maximum value + */ + public void setMax(double max) { + if (getValue() > max) { + throw new IllegalArgumentException( + "The current value {} is greater than the new maximum value {}".formatted( + getValue(), max)); + } + + super.setMaxDouble(max); + } + + /** + * Gets the maximum value of the slider. + * + * @return the maximum value + */ + public double getMax() { + return getMaxDouble(); + } + + /** + * Sets the step value of the slider. The step is the amount the value + * changes when the user moves the handle. + * + * @param step + * the step value + * @throws IllegalArgumentExceptionm + * if the step is less than or equal to zero + * @throws IllegalArgumentException + * if the current value is not aligned with the new step value + */ + public void setStep(double step) { + if (getValue() % step != 0) { + throw new IllegalArgumentException( + "The current value {} is not aligned with the new step value {}".formatted( + getValue(), step)); + } + + super.setStepDouble(step); + } + + /** + * Gets the step value of the slider. + * + * @return the step value + */ + public double getStep() { + return getStepDouble(); + } + + private double requireValidValue(Double value) { + Objects.requireNonNull(value, "Value cannot be null"); + + if (value < getMin() || value > getMax()) { + throw new IllegalArgumentException( + "The value must be between min and max"); + } + + if (value % getStep() != 0) { + throw new IllegalArgumentException( + "The value is not aligned with the step value"); + } + + return value; + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderBase.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderBase.java new file mode 100644 index 00000000000..c1f6892875e --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderBase.java @@ -0,0 +1,209 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +import java.util.HashSet; +import java.util.Set; + +import com.vaadin.experimental.FeatureFlags; +import com.vaadin.flow.component.AbstractSinglePropertyField; +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.Focusable; +import com.vaadin.flow.component.HasHelper; +import com.vaadin.flow.component.HasLabel; +import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.KeyNotifier; +import com.vaadin.flow.component.UI; +import com.vaadin.flow.component.shared.HasValidationProperties; +import com.vaadin.flow.function.SerializableBiFunction; +import com.vaadin.flow.function.SerializableRunnable; + +/** + * Abstract base class for slider components. + * + * @param + * the component type + * @param + * the value type + * + * @author Vaadin Ltd + */ +public abstract class SliderBase, TValue> + extends AbstractSinglePropertyField + implements HasLabel, HasHelper, HasValidationProperties, HasSize, + Focusable, KeyNotifier { + private Set pendingBeforeClientResponseActions = new HashSet<>(); + + /** + * Constructs a slider with the given min, max, step, initial value, and + * custom converters for the value property. + * + * @param + * the presentation type used by the element property + * @param min + * the minimum value + * @param max + * the maximum value + * @param step + * the step value + * @param value + * the initial value + * @param presentationType + * the class of the presentation type + * @param presentationToModel + * a function to convert from presentation to model + * @param modelToPresentation + * a function to convert from model to presentation + */ + SliderBase(double min, double max, double step, + TValue value, Class presentationType, + SerializableBiFunction presentationToModel, + SerializableBiFunction modelToPresentation) { + super("value", null, presentationType, presentationToModel, + modelToPresentation); + + getElement().setProperty("manualValidation", true); + + setMinDouble(min); + setMaxDouble(max); + setStepDouble(step); + setValue(value); + + // workaround for // https://github.com/vaadin/flow/issues/3496 + setInvalid(false); + } + + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + checkFeatureFlag(attachEvent.getUI()); + } + + private void checkFeatureFlag(UI ui) { + FeatureFlags featureFlags = FeatureFlags + .get(ui.getSession().getService().getContext()); + boolean enabled = featureFlags + .isEnabled(SliderFeatureFlagProvider.SLIDER_COMPONENT); + + if (!enabled) { + throw new ExperimentalFeatureException(); + } + } + + /** + * Sets the minimum value of the slider. + * + * @param min + * the minimum value + * @throws IllegalArgumentException + * if the min is greater than the max value + */ + void setMinDouble(double min) { + if (min > getMaxDouble()) { + throw new IllegalArgumentException( + "The min value cannot be greater than the max value"); + } + + getElement().setProperty("min", min); + } + + /** + * Gets the minimum value of the slider. + * + * @return the minimum value + */ + double getMinDouble() { + return getElement().getProperty("min", 0); + } + + /** + * Sets the maximum value of the slider. + * + * @param max + * the maximum value + * @throws IllegalArgumentException + * if the max is less than the min value + */ + void setMaxDouble(double max) { + if (max < getMinDouble()) { + throw new IllegalArgumentException( + "The max value cannot be less than the min value"); + } + + getElement().setProperty("max", max); + } + + /** + * Gets the maximum value of the slider. + * + * @return the maximum value + */ + double getMaxDouble() { + return getElement().getProperty("max", 100); + } + + /** + * Sets the step value of the slider. The step is the amount the value + * changes when the user moves the handle. + * + * @param step + * the step value + * @throws IllegalArgumentException + * if the step is less than or equal to zero + */ + void setStepDouble(double step) { + if (step <= 0) { + throw new IllegalArgumentException( + "The step value must be a positive number"); + } + + getElement().setProperty("step", step); + } + + /** + * Gets the step value of the slider. + * + * @return the step value + */ + double getStepDouble() { + return getElement().getProperty("step", 1); + } + + /** + * Schedules the given action to be executed before the client response, + * identified by the given key. If an action with the same key is already + * scheduled, it will not be added again. + * + * @param key + * the unique key identifying the action + * @param action + * the action to be executed + */ + void scheduleBeforeClientResponse(String key, SerializableRunnable action) { + if (pendingBeforeClientResponseActions.contains(key)) { + return; + } + + getElement().getNode().runWhenAttached(ui -> { + ui.beforeClientResponse(this, context -> { + pendingBeforeClientResponseActions.remove(key); + action.run(); + }); + }); + + pendingBeforeClientResponseActions.add(key); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderFeatureFlagProvider.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderFeatureFlagProvider.java new file mode 100644 index 00000000000..16e922e0545 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/java/com/vaadin/flow/component/slider/SliderFeatureFlagProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider; + +import java.util.List; + +import com.vaadin.experimental.Feature; +import com.vaadin.experimental.FeatureFlagProvider; + +public class SliderFeatureFlagProvider implements FeatureFlagProvider { + + public static final Feature SLIDER_COMPONENT = new Feature( + "Slider component", "sliderComponent", + "https://github.com/vaadin/platform/issues/8397", true, + "com.vaadin.flow.component.slider.Slider"); + + @Override + public List getFeatures() { + return List.of(SLIDER_COMPONENT); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/resources/META-INF/services/com.vaadin.experimental.FeatureFlagProvider b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/resources/META-INF/services/com.vaadin.experimental.FeatureFlagProvider new file mode 100644 index 00000000000..809a40f2baf --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/main/resources/META-INF/services/com.vaadin.experimental.FeatureFlagProvider @@ -0,0 +1 @@ +com.vaadin.flow.component.slider.SliderFeatureFlagProvider diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderSerializableTest.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderSerializableTest.java new file mode 100644 index 00000000000..303fd71c45b --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderSerializableTest.java @@ -0,0 +1,21 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import com.vaadin.flow.testutil.ClassesSerializableTest; + +public class RangeSliderSerializableTest extends ClassesSerializableTest { +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderTest.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderTest.java new file mode 100644 index 00000000000..29ee039aaf6 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/RangeSliderTest.java @@ -0,0 +1,299 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.flow.component.Focusable; +import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.KeyNotifier; +import com.vaadin.flow.component.slider.RangeSlider; +import com.vaadin.flow.component.slider.RangeSliderValue; + +public class RangeSliderTest { + + @Test + public void defaultConstructor() { + RangeSlider slider = new RangeSlider(); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(0.0, 100.0), + slider.getValue()); + } + + @Test + public void listenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider(e -> listenerInvoked.set(true)); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(0.0, 100.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(25.0, 75.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void minMaxValueConstructor() { + RangeSlider slider = new RangeSlider(10.0, 50.0, + new RangeSliderValue(15.0, 45.0)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + } + + @Test + public void minMaxValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider(10.0, 50.0, + new RangeSliderValue(15.0, 45.0), + e -> listenerInvoked.set(true)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(20.0, 40.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void minMaxStepValueConstructor() { + RangeSlider slider = new RangeSlider(10.0, 50.0, 5.0, + new RangeSliderValue(15.0, 45.0)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + } + + @Test + public void minMaxStepValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider(10.0, 50.0, 5.0, + new RangeSliderValue(15.0, 45.0), + e -> listenerInvoked.set(true)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(20.0, 40.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelConstructor() { + RangeSlider slider = new RangeSlider("Label"); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(0.0, 100.0), + slider.getValue()); + } + + @Test + public void labelListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider("Label", + e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(0.0, 100.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(25.0, 75.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelMinMaxValueConstructor() { + RangeSlider slider = new RangeSlider("Label", 10.0, 50.0, + new RangeSliderValue(15.0, 45.0)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + } + + @Test + public void labelMinMaxValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider("Label", 10.0, 50.0, + new RangeSliderValue(15.0, 45.0), + e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(20.0, 40.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelMinMaxStepValueConstructor() { + RangeSlider slider = new RangeSlider("Label", 10.0, 50.0, 5.0, + new RangeSliderValue(15.0, 45.0)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + } + + @Test + public void labelMinMaxStepValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + RangeSlider slider = new RangeSlider("Label", 10.0, 50.0, 5.0, + new RangeSliderValue(15.0, 45.0), + e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(new RangeSliderValue(15.0, 45.0), + slider.getValue()); + + slider.setValue(new RangeSliderValue(20.0, 40.0)); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test(expected = IllegalArgumentException.class) + public void setValue_startLessThanMin_throws() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + slider.setValue(new RangeSliderValue(-10.0, 50.0)); + } + + @Test(expected = IllegalArgumentException.class) + public void setValue_endGreaterThanMax_throws() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + slider.setValue(new RangeSliderValue(50.0, 150.0)); + } + + @Test(expected = IllegalArgumentException.class) + public void setValue_startGreaterThanEnd_throws() { + new RangeSliderValue(75.0, 25.0); + } + + @Test(expected = NullPointerException.class) + public void setValue_null_throws() { + RangeSlider slider = new RangeSlider(); + slider.setValue(null); + } + + @Test + public void implementsHasSizeInterface() { + RangeSlider slider = new RangeSlider(); + Assert.assertTrue(slider instanceof HasSize); + } + + @Test + public void implementsFocusableInterface() { + RangeSlider slider = new RangeSlider(); + Assert.assertTrue(slider instanceof Focusable); + } + + @Test + public void implementsKeyNotifierInterface() { + RangeSlider slider = new RangeSlider(); + Assert.assertTrue(slider instanceof KeyNotifier); + } + + @Test + public void setMin_getMin() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(0.0, slider.getElement().getProperty("min", 0.0), + 0.0); + + slider.setMin(-10.0); + Assert.assertEquals(-10.0, slider.getMin(), 0.0); + Assert.assertEquals(-10.0, slider.getElement().getProperty("min", 0.0), + 0.0); + } + + @Test + public void setMax_getMax() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(100.0, slider.getElement().getProperty("max", 0.0), + 0.0); + + slider.setMax(200.0); + Assert.assertEquals(200.0, slider.getMax(), 0.0); + Assert.assertEquals(200.0, slider.getElement().getProperty("max", 0.0), + 0.0); + } + + @Test + public void setStep_getStep() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(1.0, slider.getElement().getProperty("step", 1.0), + 0.0); + + slider.setStep(5.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(5.0, slider.getElement().getProperty("step", 1.0), + 0.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setMin_greaterThanMax_throws() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + slider.setMin(150.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setMax_lessThanMin_throws() { + RangeSlider slider = new RangeSlider(50.0, 100.0, 10.0, + new RangeSliderValue(50.0, 100.0)); + slider.setMax(25.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setStep_notPositive_throws() { + RangeSlider slider = new RangeSlider(0.0, 100.0, 1.0, + new RangeSliderValue(0.0, 100.0)); + slider.setStep(0.0); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderSerializableTest.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderSerializableTest.java new file mode 100644 index 00000000000..0e628b3d9a4 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderSerializableTest.java @@ -0,0 +1,21 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import com.vaadin.flow.testutil.ClassesSerializableTest; + +public class SliderSerializableTest extends ClassesSerializableTest { +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderTest.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderTest.java new file mode 100644 index 00000000000..96d74c7cede --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/tests/SliderTest.java @@ -0,0 +1,250 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.tests; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.flow.component.Focusable; +import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.KeyNotifier; +import com.vaadin.flow.component.slider.Slider; + +public class SliderTest { + @Test + public void defaultConstructor() { + Slider slider = new Slider(); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(0.0, slider.getValue(), 0.0); + } + + @Test + public void listenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider(e -> listenerInvoked.set(true)); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(0.0, slider.getValue(), 0.0); + + slider.setValue(50.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void minMaxValueConstructor() { + Slider slider = new Slider(10.0, 50.0, 25.0); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + } + + @Test + public void minMaxValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider(10.0, 50.0, 25.0, + e -> listenerInvoked.set(true)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + + slider.setValue(30.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void minMaxStepValueConstructor() { + Slider slider = new Slider(10.0, 50.0, 5.0, 25.0); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + } + + @Test + public void minMaxStepValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider(10.0, 50.0, 5.0, 25.0, + e -> listenerInvoked.set(true)); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + + slider.setValue(30.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelConstructor() { + Slider slider = new Slider("Label"); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(0.0, slider.getValue(), 0.0); + } + + @Test + public void labelListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider("Label", e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(0.0, slider.getValue(), 0.0); + + slider.setValue(50.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelMinMaxValueConstructor() { + Slider slider = new Slider("Label", 10.0, 50.0, 25.0); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + } + + @Test + public void labelMinMaxValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider("Label", 10.0, 50.0, 25.0, + e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + + slider.setValue(30.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test + public void labelMinMaxStepValueConstructor() { + Slider slider = new Slider("Label", 10.0, 50.0, 5.0, 25.0); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + } + + @Test + public void labelMinMaxStepValueListenerConstructor() { + AtomicBoolean listenerInvoked = new AtomicBoolean(false); + Slider slider = new Slider("Label", 10.0, 50.0, 5.0, 25.0, + e -> listenerInvoked.set(true)); + Assert.assertEquals("Label", slider.getLabel()); + Assert.assertEquals(10.0, slider.getMin(), 0.0); + Assert.assertEquals(50.0, slider.getMax(), 0.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(25.0, slider.getValue(), 0.0); + + slider.setValue(30.0); + Assert.assertTrue(listenerInvoked.get()); + } + + @Test(expected = IllegalArgumentException.class) + public void setValue_lessThanMin_throws() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + slider.setValue(-150.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setValue_greaterThanMax_throws() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + slider.setValue(150.0); + } + + public void implementsHasSizeInterface() { + Slider slider = new Slider(); + Assert.assertTrue(slider instanceof HasSize); + } + + public void implementsFocusableInterface() { + Slider slider = new Slider(); + Assert.assertTrue(slider instanceof Focusable); + } + + public void implementsKeyNotifierInterface() { + Slider slider = new Slider(); + Assert.assertTrue(slider instanceof KeyNotifier); + } + + @Test + public void setMin_getMin() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + Assert.assertEquals(0.0, slider.getMin(), 0.0); + Assert.assertEquals(0.0, slider.getElement().getProperty("min", 0.0), + 0.0); + + slider.setMin(-10.0); + Assert.assertEquals(-10.0, slider.getMin(), 0.0); + Assert.assertEquals(-10.0, slider.getElement().getProperty("min", 0.0), + 0.0); + } + + @Test + public void setMax_getMax() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + Assert.assertEquals(100.0, slider.getMax(), 0.0); + Assert.assertEquals(100.0, slider.getElement().getProperty("max", 0.0), + 0.0); + + slider.setMax(200.0); + Assert.assertEquals(200.0, slider.getMax(), 0.0); + Assert.assertEquals(200.0, slider.getElement().getProperty("max", 0.0), + 0.0); + } + + @Test + public void setStep_getStep() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + Assert.assertEquals(1.0, slider.getStep(), 0.0); + Assert.assertEquals(1.0, slider.getElement().getProperty("step", 1.0), + 0.0); + + slider.setStep(5.0); + Assert.assertEquals(5.0, slider.getStep(), 0.0); + Assert.assertEquals(5.0, slider.getElement().getProperty("step", 1.0), + 0.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setMin_greaterThanMax_throws() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + slider.setMin(150.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setMax_lessThanMin_throws() { + Slider slider = new Slider(50.0, 100.0, 10.0, 50.0); + slider.setMax(25.0); + } + + @Test(expected = IllegalArgumentException.class) + public void setStep_notPositive_throws() { + Slider slider = new Slider(0.0, 100.0, 1.0, 0.0); + slider.setStep(0.0); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/validation/SliderBasicValidationTest.java b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/validation/SliderBasicValidationTest.java new file mode 100644 index 00000000000..8d507cfa22a --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-flow/src/test/java/com/vaadin/flow/component/slider/validation/SliderBasicValidationTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.validation; + +import com.vaadin.flow.component.slider.Slider; +import com.vaadin.tests.validation.AbstractBasicValidationTest; + +public class SliderBasicValidationTest + extends AbstractBasicValidationTest { + + @Override + protected Slider createTestField() { + return new Slider(); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-testbench/pom.xml b/vaadin-slider-flow-parent/vaadin-slider-testbench/pom.xml new file mode 100644 index 00000000000..03f35c68820 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-testbench/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.vaadin + vaadin-slider-flow-parent + 25.1-SNAPSHOT + + vaadin-slider-testbench + jar + Vaadin Slider Testbench API + Vaadin Slider Testbench API + + + com.vaadin + vaadin-testbench-shared + provided + + + + + + + + attach-docs + + + with-docs + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + + + diff --git a/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/RangeSliderElement.java b/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/RangeSliderElement.java new file mode 100644 index 00000000000..441eea2c1e2 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/RangeSliderElement.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.testbench; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elementsbase.Element; + +/** + * A TestBench element representing a <vaadin-range-slider> + * element. + */ +@Element("vaadin-range-slider") +public class RangeSliderElement extends TestBenchElement { + + /** + * Gets the start value of the range slider. + * + * @return the start value + */ + public double getStartValue() { + return getPropertyDouble("value", "0"); + } + + /** + * Gets the end value of the range slider. + * + * @return the end value + */ + public double getEndValue() { + return getPropertyDouble("value", "1"); + } + + /** + * Gets the minimum value of the range slider. + * + * @return the minimum value + */ + public double getMin() { + return getPropertyDouble("min"); + } + + /** + * Gets the maximum value of the range slider. + * + * @return the maximum value + */ + public double getMax() { + return getPropertyDouble("max"); + } + + /** + * Gets the step value of the range slider. + * + * @return the step value + */ + public double getStep() { + return getPropertyDouble("step"); + } +} diff --git a/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/SliderElement.java b/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/SliderElement.java new file mode 100644 index 00000000000..9b36c1111c8 --- /dev/null +++ b/vaadin-slider-flow-parent/vaadin-slider-testbench/src/main/java/com/vaadin/flow/component/slider/testbench/SliderElement.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.component.slider.testbench; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elementsbase.Element; + +/** + * A TestBench element representing a <vaadin-slider> + * element. + */ +@Element("vaadin-slider") +public class SliderElement extends TestBenchElement { + + /** + * Gets the current value of the slider. + * + * @return the current value + */ + public double getValue() { + return getPropertyDouble("value"); + } + + /** + * Gets the minimum value of the slider. + * + * @return the minimum value + */ + public double getMin() { + return getPropertyDouble("min"); + } + + /** + * Gets the maximum value of the slider. + * + * @return the maximum value + */ + public double getMax() { + return getPropertyDouble("max"); + } + + /** + * Gets the step value of the slider. + * + * @return the step value + */ + public double getStep() { + return getPropertyDouble("step"); + } +}