diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts index 74e3c855ae41..a78e7ef5d47e 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Button Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts index d2113759c835..66b66d583e7f 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Checkbox Group Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxWidgetSnapshot_spec.ts index fe143dcab129..5ad568bf5a20 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Checkbox Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilHeadingWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilHeadingWidgetSnapshot_spec.ts index c58a6eff6cd3..82ae69d9a07b 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilHeadingWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilHeadingWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Heading Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts index 9c0b7ec75524..5adb9bde9366 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Icon Button Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts index 67015f2c3e28..9899b8ce2f79 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Inline Button Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts index 81cbbbac8790..eac9c2178efb 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Paragraph Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilRadioGroupWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilRadioGroupWidgetSnapshot_spec.ts index 1634c2ae7e80..7b90dbce28ab 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilRadioGroupWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilRadioGroupWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Radio Group Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts index 0449dc62d6f5..51da8ac23959 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Stats Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts index a36b4d2c0b12..2ffed43ba435 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Switch Group Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts index a6eb434fe48a..aec145739a22 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Switch Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts index 1ed021c81277..ef99aeab2938 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts @@ -5,7 +5,7 @@ import { } from "../../../../../support/Objects/ObjectsCore"; // TODO: Enable when issue(github.com/appsmithorg/appsmith/issues/36419) is solved. -describe( +describe.skip( `${ANVIL_EDITOR_TEST}: Anvil tests for Toolbar Button Widget`, { tags: ["@tag.Anvil", "@tag.Visual"] }, () => { diff --git a/app/client/cypress/limited-tests.txt b/app/client/cypress/limited-tests.txt index 3a997515912b..00e32a4629d0 100644 --- a/app/client/cypress/limited-tests.txt +++ b/app/client/cypress/limited-tests.txt @@ -1,6 +1,7 @@ # To run only limited tests - give the spec names in below format: -cypress/e2e/Regression/ClientSide/VisualTests/JSEditorIndent_spec.js +#cypress/e2e/Regression/ClientSide/VisualTests/JSEditorIndent_spec.js # For running all specs - uncomment below: #cypress/e2e/**/**/* +cypress/e2e/Regression/ClientSide/Anvil/Widgets/* #ci-test-limit uses this file to run minimum of specs. Do not run entire suite with this command. diff --git a/app/client/cypress/support/Pages/Anvil/AnvilSnapshot.ts b/app/client/cypress/support/Pages/Anvil/AnvilSnapshot.ts index 356e16994c36..a7da8faebe2a 100644 --- a/app/client/cypress/support/Pages/Anvil/AnvilSnapshot.ts +++ b/app/client/cypress/support/Pages/Anvil/AnvilSnapshot.ts @@ -173,8 +173,8 @@ export class AnvilSnapshot { public triggerInputInvalidState = () => { this.enterPreviewMode(); - cy.get("input[aria-required=true]").first().type("123"); - cy.get("input[aria-required=true]").first().clear(); + cy.get("input[required]").first().type("123"); + cy.get("input[required]").first().clear(); this.exitPreviewMode(); this.agHelper.GetNClick(this.locators.propertyPaneSidebar); }; diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx index ed931b848db9..160265802dff 100644 --- a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx +++ b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx @@ -1,18 +1,27 @@ -import { Text, type TextProps } from "@appsmith/wds"; -import React, { forwardRef, type ForwardedRef } from "react"; -import { HeadingContext, useContextProps } from "react-aria-components"; +import { type TextProps } from "@appsmith/wds"; +import { + CalendarStateContext, + HeadingContext, + useContextProps, +} from "react-aria-components"; +import React, { forwardRef, useContext, type ForwardedRef } from "react"; + +import styles from "./styles.module.css"; +import { CalendarMonthDropdown } from "./CalendarMonthDropdown"; +import { CalendarYearDropdown } from "./CalendarYearDropdown"; function CalendarHeading( props: TextProps, ref: ForwardedRef, ) { [props, ref] = useContextProps(props, ref, HeadingContext); - const { children, ...domProps } = props; + const state = useContext(CalendarStateContext); return ( - - {children} - +
+ + +
); } diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarMonthDropdown.tsx b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarMonthDropdown.tsx new file mode 100644 index 000000000000..3f37d5647f8d --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarMonthDropdown.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import type { Key } from "react"; +import { useDateFormatter } from "@react-aria/i18n"; +import { ListBoxItem, Select } from "@appsmith/wds"; +import type { CalendarState } from "@react-stately/calendar"; + +import styles from "./styles.module.css"; +import { useValidMonths } from "../utils/calendar"; + +export function CalendarMonthDropdown({ state }: { state: CalendarState }) { + const formatter = useDateFormatter({ + month: "long", + timeZone: state.timeZone, + }); + + const months = useValidMonths(state, formatter); + + const onChange = (value: Key | null) => { + const date = state.focusedDate.set({ month: Number(value) }); + + state.setFocusedDate(date); + }; + + return ( + + ); +} diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarYearDropdown.tsx b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarYearDropdown.tsx new file mode 100644 index 000000000000..289f974099d6 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarYearDropdown.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import type { Key } from "react"; +import { ListBoxItem, Select } from "@appsmith/wds"; +import type { CalendarState } from "@react-stately/calendar"; + +import { useYearOptions } from "../utils/calendar"; + +export function CalendarYearDropdown({ state }: { state: CalendarState }) { + const years = useYearOptions(state); + + const onChange = (value: Key | null) => { + const index = Number(value); + const date = years[index].value; + + state.setFocusedDate(date); + }; + + return ( + + ); +} diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Calendar/src/styles.module.css index 216afe61510f..950964ce3e46 100644 --- a/app/client/packages/design-system/widgets/src/components/Calendar/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Calendar/src/styles.module.css @@ -68,3 +68,12 @@ 0 0 0 calc(var(--box-shadow-offset) + var(--border-width-2)) var(--color-bd-focus); } + +.monthYearDropdown { + display: flex; + gap: var(--inner-spacing-1); +} + +.monthDropdown button { + width: 14ch; +} diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/utils/calendar.ts b/app/client/packages/design-system/widgets/src/components/Calendar/utils/calendar.ts new file mode 100644 index 000000000000..cf1b356de043 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/Calendar/utils/calendar.ts @@ -0,0 +1,52 @@ +import { useDateFormatter } from "@react-aria/i18n"; +import type { CalendarState } from "@react-stately/calendar"; + +export function useYearOptions(state: CalendarState) { + const formatter = useDateFormatter({ + year: "numeric", + timeZone: state.timeZone, + }); + + const years: { value: CalendarState["focusedDate"]; formatted: string }[] = + []; + + const YEAR_RANGE = 20; + + for (let i = -YEAR_RANGE; i <= YEAR_RANGE; i++) { + const date = state.focusedDate.add({ years: i }); + + years.push({ + value: date, + formatted: formatter.format(date.toDate(state.timeZone)), + }); + } + + return years; +} + +export function useValidMonths( + state: CalendarState, + formatter: Intl.DateTimeFormat, +) { + const months = []; + const numMonths = state.focusedDate.calendar.getMonthsInYear( + state.focusedDate, + ); + + for (let i = 1; i <= numMonths; i++) { + const date = state.focusedDate.set({ month: i }); + + // Skip months outside valid range + if (state.minValue && date.compare(state.minValue) < 0) { + continue; + } + + if (state.maxValue && date.compare(state.maxValue) > 0) { + continue; + } + + months.push(formatter.format(date.toDate(state.timeZone))); + } + + return months; +} diff --git a/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx b/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx index f62f5dd69fb7..f57803332474 100644 --- a/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx +++ b/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx @@ -79,7 +79,6 @@ export const DatePicker = (props: DatePickerProps) => { isLoading={isLoading} size={size} /> - {errorMessage} (props: DatePickerProps) => { )} + {errorMessage} ); }} diff --git a/app/client/packages/design-system/widgets/src/components/FieldLabel/src/FieldLabel.tsx b/app/client/packages/design-system/widgets/src/components/FieldLabel/src/FieldLabel.tsx index 85126a123b94..6287bcc5c88e 100644 --- a/app/client/packages/design-system/widgets/src/components/FieldLabel/src/FieldLabel.tsx +++ b/app/client/packages/design-system/widgets/src/components/FieldLabel/src/FieldLabel.tsx @@ -22,7 +22,12 @@ export function FieldLabel(props: LabelProps) { className={clsx(styles.label)} elementType="label" > - + {children} {Boolean(isRequired) && ( diff --git a/app/client/packages/design-system/widgets/src/components/Input/src/Input.tsx b/app/client/packages/design-system/widgets/src/components/Input/src/Input.tsx index 64e03bc95d66..f52a38a27093 100644 --- a/app/client/packages/design-system/widgets/src/components/Input/src/Input.tsx +++ b/app/client/packages/design-system/widgets/src/components/Input/src/Input.tsx @@ -3,7 +3,7 @@ import { mergeRefs } from "@react-aria/utils"; import React, { forwardRef, useRef, useState } from "react"; import { getTypographyClassName } from "@appsmith/wds-theming"; import { IconButton, Spinner, type IconProps } from "@appsmith/wds"; -import { Group, Input as HeadlessInput } from "react-aria-components"; +import { Input as HeadlessInput } from "react-aria-components"; import styles from "./styles.module.css"; import type { InputProps } from "./types"; @@ -49,7 +49,7 @@ function _Input(props: InputProps, ref: React.Ref) { })(); return ( - +
{Boolean(prefix) && ( localRef.current?.focus()}> {prefix} @@ -74,7 +74,7 @@ function _Input(props: InputProps, ref: React.Ref) { {suffix} )} - +
); } diff --git a/app/client/packages/design-system/widgets/src/components/Input/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Input/src/styles.module.css index 63a0d04a895c..821e337af7bf 100644 --- a/app/client/packages/design-system/widgets/src/components/Input/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Input/src/styles.module.css @@ -27,6 +27,7 @@ padding-block: var(--inner-spacing-1); padding-inline: var(--inner-spacing-2); box-sizing: content-box; + cursor: inherit; } .inputGroup:has([data-input-prefix]) .input { @@ -63,10 +64,18 @@ margin-inline-start: var(--inner-spacing-2); } +.inputGroup:has(.input[data-size="small"]) [data-input-prefix] { + margin-inline-start: 0; +} + .inputGroup [data-input-suffix] { margin-inline-end: var(--inner-spacing-2); } +.inputGroup:has(.input[data-size="small"]) [data-input-suffix] { + margin-inline-end: 0; +} + .inputGroup :is([data-input-suffix], [data-input-prefix]) button { border-radius: calc( var(--border-radius-elevation-3) - var(--inner-spacing-1) @@ -84,7 +93,7 @@ * HOVERED * ---------------------------------------------------------------------------- */ -.inputGroup[data-hovered]:has( +.inputGroup:is([data-hovered], :has([data-hovered])):has( > .input:not( :is( [data-focused], @@ -111,6 +120,9 @@ .inputGroup input[data-readonly] { padding-inline: 0; + text-overflow: ellipsis; + white-space: nowrap; + cursor: text; } /** Reason for doing this is because for readonly inputs, we want focus state to be wider than the component width */ @@ -143,8 +155,9 @@ * DISABLED * ---------------------------------------------------------------------------- */ -.inputGroup:has(> .input[data-disabled]), -.inputGroup:has(> .input:has(~ input[data-disabled])) { +.inputGroup:has( + :is(.input[data-disabled], .input:has(~ input[data-disabled])) + ) { cursor: not-allowed; box-shadow: none; } diff --git a/app/client/packages/design-system/widgets/src/components/Select/src/SelectTrigger.tsx b/app/client/packages/design-system/widgets/src/components/Select/src/SelectTrigger.tsx index 0458df47bacd..91fe6f1c1567 100644 --- a/app/client/packages/design-system/widgets/src/components/Select/src/SelectTrigger.tsx +++ b/app/client/packages/design-system/widgets/src/components/Select/src/SelectTrigger.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import React from "react"; import { Icon, Spinner, textInputStyles } from "@appsmith/wds"; import { getTypographyClassName } from "@appsmith/wds-theming"; -import { Button, Group, SelectValue } from "react-aria-components"; +import { Button, SelectValue } from "react-aria-components"; import styles from "./styles.module.css"; import type { SelectProps } from "./types"; @@ -19,9 +19,7 @@ export const SelectTrigger: React.FC = (props) => { const { isDisabled, isInvalid, isLoading, placeholder, size } = props; return ( - +
- +
); }; diff --git a/app/client/packages/design-system/widgets/src/components/Text/src/Text.tsx b/app/client/packages/design-system/widgets/src/components/Text/src/Text.tsx index b3366bf915bc..63a72cf5d329 100644 --- a/app/client/packages/design-system/widgets/src/components/Text/src/Text.tsx +++ b/app/client/packages/design-system/widgets/src/components/Text/src/Text.tsx @@ -45,6 +45,7 @@ const _Text = (props: TextProps, ref: Ref) => { fontStyle: isItalic ? "italic" : "normal", wordBreak, textAlign, + whiteSpace: "pre-wrap", ...style, }} {...rest} diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSBaseInputWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSBaseInputWidget/widget/index.tsx index bc8b78063693..0a2e6fa0bc1a 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSBaseInputWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSBaseInputWidget/widget/index.tsx @@ -56,7 +56,7 @@ class WDSBaseInputWidget< static getMetaPropertiesMap(): Record { return { rawText: undefined, - parsedText: undefined, + text: undefined, isFocused: false, isDirty: false, }; diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/config/autocompleteConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/config/autocompleteConfig.ts index 8796f4c1dc14..15174f781cdb 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/config/autocompleteConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/config/autocompleteConfig.ts @@ -4,14 +4,14 @@ export const autocompleteConfig = { "!doc": "An input text field is used to capture a currency value. Inputs are used in forms and can have custom validations.", "!url": "https://docs.appsmith.com/widget-reference/currency-input", - parsedText: { + text: { "!type": "string", "!doc": "The formatted text value of the input", "!url": "https://docs.appsmith.com/widget-reference/currency-input", }, rawText: { "!type": "number", - "!doc": "The value of the input", + "!doc": "The raw text value of the input", "!url": "https://docs.appsmith.com/widget-reference/currency-input", }, isValid: "bool", diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/widget/index.tsx index f9087571fc14..fa71e227f114 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSCurrencyInputWidget/widget/index.tsx @@ -130,7 +130,7 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< static getMetaPropertiesMap(): Record { return _.merge(super.getMetaPropertiesMap(), { rawText: "", - parsedText: "", + text: "", currencyCode: undefined, }); } @@ -139,7 +139,7 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< return _.merge(super.getDefaultPropertiesMap(), { currencyCode: "defaultCurrencyCode", rawText: "defaultText", - parsedText: "defaultText", + text: "defaultText", }); } @@ -153,9 +153,9 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< componentDidUpdate(prevProps: CurrencyInputWidgetProps) { if ( - prevProps.text !== this.props.parsedText && + prevProps.text !== this.props.text && !this.props.isFocused && - this.props.parsedText === String(this.props.defaultText) + this.props.text === String(this.props.defaultText) ) { this.formatText(); } @@ -192,7 +192,7 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< Sentry.captureException(e); } - this.props.updateWidgetMetaProperty("parsedText", String(formattedValue)); + this.props.updateWidgetMetaProperty("text", String(formattedValue)); this.props.updateWidgetMetaProperty("rawText", value, { triggerPropertyName: "onTextChanged", @@ -214,13 +214,13 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< try { if (isFocused) { - const text = this.props.parsedText || ""; + const text = this.props.text || ""; const deFormattedValue = text.replace( new RegExp("\\" + getLocaleThousandSeparator(), "g"), "", ); - this.props.updateWidgetMetaProperty("parsedText", deFormattedValue); + this.props.updateWidgetMetaProperty("text", deFormattedValue); this.props.updateWidgetMetaProperty("isFocused", isFocused, { triggerPropertyName: "onFocus", dynamicString: this.props.onFocus, @@ -229,13 +229,13 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< }, }); } else { - if (this.props.parsedText) { + if (this.props.text) { const formattedValue = formatCurrencyNumber( this.props.decimals, - this.props.parsedText, + this.props.text, ); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } this.props.updateWidgetMetaProperty("isFocused", isFocused, { @@ -249,7 +249,7 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< } catch (e) { log.error(e); Sentry.captureException(e); - this.props.updateWidgetMetaProperty("parsedText", this.props.parsedText); + this.props.updateWidgetMetaProperty("text", this.props.text); } super.onFocusChange(!!isFocused); @@ -294,13 +294,13 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< }; isTextFormatted = () => { - return this.props.parsedText.includes(getLocaleThousandSeparator()); + return this.props.text.includes(getLocaleThousandSeparator()); }; formatText() { - if (!!this.props.parsedText && !this.isTextFormatted()) { + if (!!this.props.text && !this.isTextFormatted()) { try { - const floatVal = parseFloat(this.props.parsedText); + const floatVal = parseFloat(this.props.text); const formattedValue = Intl.NumberFormat(getLocale(), { style: "decimal", @@ -308,7 +308,7 @@ class WDSCurrencyInputWidget extends WDSBaseInputWidget< maximumFractionDigits: this.props.decimals, }).format(floatVal); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } catch (e) { log.error(e); Sentry.captureException(e); diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/autocompleteConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/autocompleteConfig.ts index 95fa1b3db712..0bebc6f411a4 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/autocompleteConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/autocompleteConfig.ts @@ -4,9 +4,14 @@ export const autocompleteConfig = { "!doc": "An input text field is used to capture a users textual input such as their names, numbers, emails etc. Inputs are used in forms and can have custom validations.", "!url": "https://docs.appsmith.com/widget-reference/input", - parsedText: { + text: { "!type": "string", - "!doc": "The text value of the input", + "!doc": "The parsed text value of the input", + "!url": "https://docs.appsmith.com/widget-reference/input", + }, + rawText: { + "!type": "string", + "!doc": "The raw text value of the input", "!url": "https://docs.appsmith.com/widget-reference/input", }, isValid: "bool", diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/settersConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/settersConfig.ts index 42ad0ccb6ad5..ed0afd5a385b 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/settersConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/config/settersConfig.ts @@ -19,7 +19,7 @@ export const settersConfig = { setValue: { path: "defaultText", type: "string", - accessor: "parsedText", + accessor: "text", }, }, }; diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/helper.ts b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/helper.ts index 6d4e6cd3b3a3..2d56ecbf943a 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/helper.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/helper.ts @@ -69,11 +69,11 @@ export const validateInput = (props: InputWidgetProps): Validation => { maxChars, maxNum, minNum, - parsedText, rawText, + text, } = props; - if (isDirty && isRequired && !isNil(parsedText) && parsedText.length === 0) { + if (isDirty && isRequired && !isNil(text) && text.length === 0) { return { validationStatus: "invalid", errorMessage: createMessage(FIELD_REQUIRED_ERROR), @@ -81,7 +81,7 @@ export const validateInput = (props: InputWidgetProps): Validation => { } if (isInputTypeSingleLineOrMultiLine(inputType) && maxChars) { - if (parsedText && parsedText.toString().length > maxChars) { + if (text && text.toString().length > maxChars) { return { validationStatus: "invalid", errorMessage: createMessage(INPUT_TEXT_MAX_CHAR_ERROR, maxChars), @@ -97,16 +97,16 @@ export const validateInput = (props: InputWidgetProps): Validation => { }; } - if (rawText !== "" && isNumber(parsedText)) { + if (rawText !== "" && isNumber(text)) { // check the default text is neither greater than max nor less than min value. - if (!isNil(minNum) && minNum > parsedText) { + if (!isNil(minNum) && minNum > text) { return { validationStatus: "invalid", errorMessage: createMessage(INPUT_DEFAULT_TEXT_MIN_NUM_ERROR), }; } - if (!isNil(maxNum) && maxNum < parsedText) { + if (!isNil(maxNum) && maxNum < text) { return { validationStatus: "invalid", errorMessage: createMessage(INPUT_DEFAULT_TEXT_MAX_NUM_ERROR), diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/index.tsx index 5eec9a47efe9..216fe6299996 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSInputWidget/widget/index.tsx @@ -62,14 +62,14 @@ class WDSInputWidget extends WDSBaseInputWidget { static getMetaPropertiesMap(): Record { return merge(super.getMetaPropertiesMap(), { rawText: "", - parsedText: "", + text: "", }); } static getDefaultPropertiesMap(): Record { return { rawText: "defaultText", - parsedText: "defaultText", + text: "defaultText", }; } @@ -157,17 +157,17 @@ class WDSInputWidget extends WDSBaseInputWidget { if ( prevProps.rawText !== this.props.rawText && - this.props.rawText !== toString(this.props.parsedText) + this.props.rawText !== toString(this.props.text) ) { pushBatchMetaUpdates( - "parsedText", + "text", parseText(this.props.rawText, this.props.inputType), ); } if (prevProps.inputType !== this.props.inputType) { pushBatchMetaUpdates( - "parsedText", + "text", parseText(this.props.rawText, this.props.inputType), ); } @@ -190,7 +190,7 @@ class WDSInputWidget extends WDSBaseInputWidget { // derived properties won't work as expected inside a List widget. // TODO(Balaji): Once we refactor the List widget, need to conver // text to a derived property. - pushBatchMetaUpdates("parsedText", parseText(value, this.props.inputType)); + pushBatchMetaUpdates("text", parseText(value, this.props.inputType)); pushBatchMetaUpdates("rawText", value, { triggerPropertyName: "onTextChanged", @@ -211,7 +211,7 @@ class WDSInputWidget extends WDSBaseInputWidget { const { commitBatchMetaUpdates, pushBatchMetaUpdates } = this.props; pushBatchMetaUpdates("rawText", ""); - pushBatchMetaUpdates("parsedText", parseText("", this.props.inputType)); + pushBatchMetaUpdates("text", parseText("", this.props.inputType)); commitBatchMetaUpdates(); }; diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/config/autocompleteConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/config/autocompleteConfig.ts index b7fb65a6fcff..6882f5daff98 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/config/autocompleteConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/config/autocompleteConfig.ts @@ -4,7 +4,7 @@ export const autocompleteConfig = { "!doc": "An input text field is used to capture a phone number. Inputs are used in forms and can have custom validations.", "!url": "https://docs.appsmith.com/widget-reference/phone-input", - parsedText: { + text: { "!type": "string", "!doc": "The formatted text value of the input", "!url": "https://docs.appsmith.com/widget-reference/phone-input", diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/helpers.ts b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/helpers.ts index bb68dac08912..63d2a51dfc9f 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/helpers.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/helpers.ts @@ -5,7 +5,7 @@ import { ISDCodeOptions } from "constants/ISDCodes_v2"; // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any export function validateInput(props: any) { - const value = props.parsedText ?? ""; + const value = props.text ?? ""; const isInvalid = "isValid" in props && !props.isValid && !!props.isDirty; // TODO: Fix this the next time the file is edited diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/index.tsx index dc39829aee09..b6d73f339e1e 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSPhoneInputWidget/widget/index.tsx @@ -117,7 +117,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< static getMetaPropertiesMap(): Record { return merge(super.getMetaPropertiesMap(), { rawText: "", - parsedText: "", + text: "", dialCode: undefined, }); } @@ -126,7 +126,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< return merge(super.getDefaultPropertiesMap(), { dialCode: "defaultDialCode", rawText: "defaultText", - parsedText: "defaultText", + text: "defaultText", }); } @@ -160,7 +160,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< const formattedValue = this.getFormattedPhoneNumber(this.props.rawText); this.props.updateWidgetMetaProperty("rawText", this.props.rawText); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } catch (e) { log.error(e); Sentry.captureException(e); @@ -176,24 +176,22 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< if (prevProps.allowFormatting !== this.props.allowFormatting) { const formattedValue = this.getFormattedPhoneNumber(this.props.rawText); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } // When the default text changes if ( - prevProps.parsedText !== this.props.parsedText && - this.props.parsedText === this.props.defaultText + prevProps.text !== this.props.text && + this.props.text === this.props.defaultText ) { - const formattedValue = this.getFormattedPhoneNumber( - this.props.parsedText, - ); + const formattedValue = this.getFormattedPhoneNumber(this.props.text); if (formattedValue) { this.props.updateWidgetMetaProperty( "rawText", parseIncompletePhoneNumber(formattedValue), ); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } } @@ -214,7 +212,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< if (this.props.rawText && this.props.allowFormatting) { const formattedValue = this.getFormattedPhoneNumber(this.props.rawText); - this.props.updateWidgetMetaProperty("parsedText", formattedValue); + this.props.updateWidgetMetaProperty("text", formattedValue); } }; @@ -222,7 +220,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< let formattedValue; // Don't format, as value is typed, when user is deleting - if (value && value.length > this.props.parsedText?.length) { + if (value && value.length > this.props.text?.length) { formattedValue = this.getFormattedPhoneNumber(value); } else { formattedValue = value; @@ -232,7 +230,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< "rawText", parseIncompletePhoneNumber(formattedValue), ); - this.props.updateWidgetMetaProperty("parsedText", formattedValue, { + this.props.updateWidgetMetaProperty("text", formattedValue, { triggerPropertyName: "onTextChanged", dynamicString: this.props.onTextChanged, event: { @@ -300,7 +298,7 @@ class WDSPhoneInputWidget extends WDSBaseInputWidget< }; getWidgetView() { - const rawText = this.props.parsedText ?? ""; + const rawText = this.props.text ?? ""; const validation = validateInput(this.props);