diff --git a/client/packages/lowcoder/src/comps/comps/autoCompleteComp/autoCompleteComp.tsx b/client/packages/lowcoder/src/comps/comps/autoCompleteComp/autoCompleteComp.tsx
index 54a269812..f7107f039 100644
--- a/client/packages/lowcoder/src/comps/comps/autoCompleteComp/autoCompleteComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/autoCompleteComp/autoCompleteComp.tsx
@@ -20,7 +20,7 @@ import {
import styled, { css } from "styled-components";
import { UICompBuilder } from "../../generators";
import { FormDataPropertyView } from "../formComp/formDataConstants";
-import { jsonControl } from "comps/controls/codeControl";
+import { jsonControl, NumberControl } from "comps/controls/codeControl";
import { dropdownControl } from "comps/controls/dropdownControl";
import {
getStyle,
@@ -92,6 +92,7 @@ const childrenMap = {
inputFieldStyle: styleControl(InputLikeStyle , 'inputFieldStyle'),
childrenInputFieldStyle: styleControl(ChildrenMultiSelectStyle, 'childrenInputFieldStyle'),
animationStyle: styleControl(AnimationStyle , 'animationStyle'),
+ tabIndex: NumberControl,
};
const getValidate = (value: any): "" | "warning" | "error" | undefined => {
@@ -271,6 +272,7 @@ let AutoCompleteCompBase = (function () {
suffix={hasIcon(props.suffixIcon) && props.suffixIcon}
status={getValidate(validateState)}
onPressEnter={undefined}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
>
@@ -354,6 +356,9 @@ let AutoCompleteCompBase = (function () {
>
{children.animationStyle.getPropertyView()}
+
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
+
>
);
})
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/dateComp.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/dateComp.tsx
index fd2add150..96de04abe 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/dateComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/dateComp.tsx
@@ -4,6 +4,7 @@ import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core"
import {
BoolCodeControl,
CustomRuleControl,
+ NumberControl,
RangeControl,
StringControl,
} from "../../controls/codeControl";
@@ -99,6 +100,7 @@ const commonChildren = {
childrenInputFieldStyle: styleControl(ChildrenMultiSelectStyle, 'childrenInputFieldStyle'),
timeZone: dropdownControl(timeZoneOptions, Intl.DateTimeFormat().resolvedOptions().timeZone),
pickerMode: dropdownControl(PickerModeOptions, 'date'),
+ tabIndex: NumberControl,
};
type CommonChildrenType = RecordConstructorToComp;
@@ -185,6 +187,7 @@ export type DateCompViewProps = Pick<
disabledTime: () => ReturnType;
suffixIcon: ReactNode;
placeholder?: string | [string, string];
+ tabIndex?: number;
};
const getFormattedDate = (
@@ -281,6 +284,7 @@ const DatePickerTmpCmp = new UICompBuilder(childrenMap, (props) => {
onFocus={() => props.onEvent("focus")}
onBlur={() => props.onEvent("blur")}
suffixIcon={hasIcon(props.suffixIcon) && props.suffixIcon}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
),
showValidationWhenEmpty: props.showValidationWhenEmpty,
@@ -340,6 +344,7 @@ const DatePickerTmpCmp = new UICompBuilder(childrenMap, (props) => {
<>
{timeFields(children, isMobile)}
{children.suffixIcon.propertyView({ label: trans("button.suffixIcon") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
>
)}
{(useContext(EditorContext).editorModeStatus === "logic" || useContext(EditorContext).editorModeStatus === "both") && !isMobile && commonAdvanceSection(children)}
@@ -475,7 +480,9 @@ let DateRangeTmpCmp = (function () {
}}
onFocus={() => props.onEvent("focus")}
onBlur={() => props.onEvent("blur")}
- suffixIcon={hasIcon(props.suffixIcon) && props.suffixIcon} />
+ suffixIcon={hasIcon(props.suffixIcon) && props.suffixIcon}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
+ />
);
const startResult = validate({ ...props, value: props.start });
@@ -553,6 +560,7 @@ let DateRangeTmpCmp = (function () {
<>
{timeFields(children, isMobile)}
{children.suffixIcon.propertyView({ label: trans("button.suffixIcon") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
>
)}
{(useContext(EditorContext).editorModeStatus === "logic" || useContext(EditorContext).editorModeStatus === "both") && commonAdvanceSection(children)}
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/dateRangeUIView.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/dateRangeUIView.tsx
index a2c7ba56d..c56ddecb6 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/dateRangeUIView.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/dateRangeUIView.tsx
@@ -44,7 +44,8 @@ export interface DateRangeUIViewProps extends DateCompViewProps {
placeholder?: string | [string, string];
onChange: (start?: dayjs.Dayjs | null, end?: dayjs.Dayjs | null) => void;
onPanelChange: (value: any, mode: [string, string]) => void;
- onClickDateRangeTimeZone:(value:any)=>void
+ onClickDateRangeTimeZone:(value:any)=>void;
+ tabIndex?: number;
}
export const DateRangeUIView = (props: DateRangeUIViewProps) => {
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/dateUIView.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/dateUIView.tsx
index a5bdea97a..a98a1eaa5 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/dateUIView.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/dateUIView.tsx
@@ -39,7 +39,7 @@ export interface DataUIViewProps extends DateCompViewProps {
onChange: DatePickerProps['onChange'];
onPanelChange: () => void;
onClickDateTimeZone:(value:any)=>void;
-
+ tabIndex?: number;
}
const DateMobileUIView = React.lazy(() =>
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/timeComp.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/timeComp.tsx
index 10dc2dc90..101299d23 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/timeComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/timeComp.tsx
@@ -4,6 +4,7 @@ import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core"
import {
BoolCodeControl,
CustomRuleControl,
+ NumberControl,
RangeControl,
StringControl,
} from "../../controls/codeControl";
@@ -92,6 +93,7 @@ const commonChildren = {
suffixIcon: withDefault(IconControl, "/icon:regular/clock"),
timeZone: dropdownControl(timeZoneOptions, Intl.DateTimeFormat().resolvedOptions().timeZone),
viewRef: RefControl,
+ tabIndex: NumberControl,
...validationChildren,
};
@@ -212,6 +214,7 @@ const TimePickerTmpCmp = new UICompBuilder(childrenMap, (props) => {
onFocus={() => props.onEvent("focus")}
onBlur={() => props.onEvent("blur")}
suffixIcon={hasIcon(props.suffixIcon) && props.suffixIcon}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
),
showValidationWhenEmpty: props.showValidationWhenEmpty,
@@ -263,6 +266,7 @@ const TimePickerTmpCmp = new UICompBuilder(childrenMap, (props) => {
{commonAdvanceSection(children)}
{children.use12Hours.propertyView({ label: trans("prop.use12Hours") })}
{children.suffixIcon.propertyView({ label: trans("button.suffixIcon") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
)}
@@ -368,6 +372,7 @@ const TimeRangeTmpCmp = (function () {
onFocus={() => props.onEvent("focus")}
onBlur={() => props.onEvent("blur")}
suffixIcon={hasIcon(props.suffixIcon) && props.suffixIcon}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
);
@@ -439,6 +444,7 @@ const TimeRangeTmpCmp = (function () {
{commonAdvanceSection(children)}
{children.use12Hours.propertyView({ label: trans("prop.use12Hours") })}
{children.suffixIcon.propertyView({ label: trans("button.suffixIcon") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
)}
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/timeRangeUIView.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/timeRangeUIView.tsx
index 44afcc7b3..940a37266 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/timeRangeUIView.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/timeRangeUIView.tsx
@@ -39,6 +39,7 @@ export interface TimeRangeUIViewProps extends TimeCompViewProps {
placeholder?: string | [string, string];
onChange: (start?: dayjs.Dayjs | null, end?: dayjs.Dayjs | null) => void;
handleTimeRangeZoneChange: (value:any) => void;
+ tabIndex?: number;
}
export const TimeRangeUIView = (props: TimeRangeUIViewProps) => {
diff --git a/client/packages/lowcoder/src/comps/comps/dateComp/timeUIView.tsx b/client/packages/lowcoder/src/comps/comps/dateComp/timeUIView.tsx
index a04b117e2..891dfc1a4 100644
--- a/client/packages/lowcoder/src/comps/comps/dateComp/timeUIView.tsx
+++ b/client/packages/lowcoder/src/comps/comps/dateComp/timeUIView.tsx
@@ -34,6 +34,7 @@ export interface TimeUIViewProps extends TimeCompViewProps {
value: dayjs.Dayjs | null;
onChange: (value: dayjs.Dayjs | null) => void;
handleTimeZoneChange: (value:any) => void;
+ tabIndex?: number;
}
export const TimeUIView = (props: TimeUIViewProps) => {
diff --git a/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx b/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx
index 4f8ad6bce..68ca7d370 100644
--- a/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx
@@ -272,6 +272,7 @@ const childrenMap = {
min: UndefinedNumberControl,
max: UndefinedNumberControl,
customRule: CustomRuleControl,
+ tabIndex: NumberControl,
...formDataChildren,
};
@@ -330,6 +331,7 @@ const CustomInputNumber = (props: RecordConstructorToView) =
precision={props.precision}
$style={props.inputFieldStyle}
prefix={hasIcon(props.prefixIcon) ? props.prefixIcon : props.prefixText.value}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
onPressEnter={() => {
handleFinish();
props.onEvent("submit");
@@ -436,6 +438,7 @@ let NumberInputTmpComp = (function () {
})}
{children.controls.propertyView({ label: trans("numberInput.controls") })}
{readOnlyPropertyView(children)}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
)}
diff --git a/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx b/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx
index 0c17a5a7f..cbc921508 100644
--- a/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/numberInputComp/rangeSliderComp.tsx
@@ -6,6 +6,7 @@ import { CommonNameConfig, NameConfig, withExposingConfigs } from "../../generat
import { SliderChildren, SliderPropertyView, SliderStyled, SliderWrapper } from "./sliderCompConstants";
import { hasIcon } from "comps/utils";
import { BoolControl } from "comps/controls/boolControl";
+import { NumberControl } from "comps/controls/codeControl";
const RangeSliderBasicComp = (function () {
const childrenMap = {
@@ -13,6 +14,7 @@ const RangeSliderBasicComp = (function () {
start: numberExposingStateControl("start", 10),
end: numberExposingStateControl("end", 60),
vertical: BoolControl,
+ tabIndex: NumberControl,
};
return new UICompBuilder(childrenMap, (props, dispatch) => {
return props.label({
@@ -36,6 +38,7 @@ const RangeSliderBasicComp = (function () {
$style={props.inputFieldStyle}
style={{ margin: 0 }}
$vertical={Boolean(props.vertical) || false}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
onChange={([start, end]) => {
props.start.onChange(start);
props.end.onChange(end);
@@ -60,6 +63,7 @@ const RangeSliderBasicComp = (function () {
tooltip: trans("rangeSlider.stepTooltip"),
})}
{children.vertical.propertyView({ label: trans("slider.vertical") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
diff --git a/client/packages/lowcoder/src/comps/comps/numberInputComp/sliderComp.tsx b/client/packages/lowcoder/src/comps/comps/numberInputComp/sliderComp.tsx
index cabda6634..acadbb733 100644
--- a/client/packages/lowcoder/src/comps/comps/numberInputComp/sliderComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/numberInputComp/sliderComp.tsx
@@ -7,6 +7,7 @@ import { formDataChildren, FormDataPropertyView } from "../formComp/formDataCons
import { SliderChildren, SliderPropertyView, SliderStyled, SliderWrapper } from "./sliderCompConstants";
import { hasIcon } from "comps/utils";
import { BoolControl } from "comps/controls/boolControl";
+import { NumberControl } from "comps/controls/codeControl";
const SliderBasicComp = (function () {
/**
@@ -16,6 +17,7 @@ const SliderBasicComp = (function () {
...SliderChildren,
value: numberExposingStateControl("value", 60),
vertical: BoolControl,
+ tabIndex: NumberControl,
...formDataChildren,
};
return new UICompBuilder(childrenMap, (props) => {
@@ -39,6 +41,7 @@ const SliderBasicComp = (function () {
$style={props.inputFieldStyle}
style={{margin: 0}}
$vertical={Boolean(props.vertical) || false}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
onChange={(e) => {
props.value.onChange(e);
props.onEvent("change");
@@ -61,6 +64,7 @@ const SliderBasicComp = (function () {
tooltip: trans("slider.stepTooltip"),
})}
{children.vertical.propertyView({ label: trans("slider.vertical") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
diff --git a/client/packages/lowcoder/src/comps/comps/richTextEditorComp.tsx b/client/packages/lowcoder/src/comps/comps/richTextEditorComp.tsx
index ed96c3a28..f549dadf3 100644
--- a/client/packages/lowcoder/src/comps/comps/richTextEditorComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/richTextEditorComp.tsx
@@ -1,4 +1,4 @@
-import { StringControl } from "comps/controls/codeControl";
+import { StringControl, NumberControl } from "comps/controls/codeControl";
import { BoolControl } from "comps/controls/boolControl";
import { BoolCodeControl } from "../controls/codeControl";
import { stringExposingStateControl } from "comps/controls/codeStateControl";
@@ -180,6 +180,7 @@ const childrenMap = {
toolbar: withDefault(StringControl, JSON.stringify(toolbarOptions)),
onEvent: ChangeEventHandlerControl,
style: styleControl(RichTextEditorStyle , 'style'),
+ tabIndex: NumberControl,
...formDataChildren,
};
@@ -196,6 +197,7 @@ interface IProps {
onChange: (value: string) => void;
$style: RichTextEditorStyleType;
contentScrollBar: boolean;
+ tabIndex?: number;
}
const ReactQuillEditor = React.lazy(() => import("react-quill"));
@@ -226,6 +228,15 @@ function RichTextEditor(props: IProps) {
[props.placeholder]
);
+ useEffect(() => {
+ if (editorRef.current && props.tabIndex !== undefined) {
+ const editor = editorRef.current.getEditor();
+ if (editor && editor.scroll && editor.scroll.domNode) {
+ (editor.scroll.domNode as HTMLElement).tabIndex = props.tabIndex;
+ }
+ }
+ }, [props.tabIndex, key]); // Also re-run when key changes due to placeholder update
+
const contains = (parent: HTMLElement, descendant: HTMLElement) => {
try {
// Firefox inserts inaccessible nodes around video elements
@@ -316,6 +327,7 @@ const RichTextEditorCompBase = new UICompBuilder(childrenMap, (props) => {
onChange={handleChange}
$style={props.style}
contentScrollBar={props.contentScrollBar}
+ tabIndex={props.tabIndex}
/>
);
})
@@ -334,6 +346,7 @@ const RichTextEditorCompBase = new UICompBuilder(childrenMap, (props) => {
{children.onEvent.getPropertyView()}
{hiddenPropertyView(children)}
{readOnlyPropertyView(children)}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
{showDataLoadingIndicatorsPropertyView(children)}
)}
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx
index f69b69453..d6eb38737 100644
--- a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx
@@ -1,6 +1,6 @@
import { default as AntdCheckboxGroup } from "antd/es/checkbox/Group";
import { SelectInputOptionControl } from "comps/controls/optionsControl";
-import { BoolCodeControl } from "../../controls/codeControl";
+import { BoolCodeControl, NumberControl } from "../../controls/codeControl";
import { arrayStringExposingStateControl } from "../../controls/codeStateControl";
import { LabelControl } from "../../controls/labelControl";
import { ChangeEventHandlerControl } from "../../controls/eventHandlerControl";
@@ -115,6 +115,7 @@ export const getStyle = (style: CheckboxStyleType) => {
const CheckboxGroup = styled(AntdCheckboxGroup) <{
$style: CheckboxStyleType;
$layout: ValueFromOption;
+ tabIndex?: number;
}>`
min-height: 32px;
${(props) => props.$style && getStyle(props.$style)}
@@ -156,6 +157,7 @@ let CheckboxBasicComp = (function () {
viewRef: RefControl,
inputFieldStyle: styleControl(CheckboxStyle , 'inputFieldStyle'),
animationStyle: styleControl(AnimationStyle , 'animationStyle'),
+ tabIndex: NumberControl,
...SelectInputValidationChildren,
...formDataChildren,
};
@@ -184,6 +186,7 @@ let CheckboxBasicComp = (function () {
value: option.value,
disabled: option.disabled,
}))}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
onChange={(values) => {
handleChange(values as string[]);
}}
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx
index 6bc4805cd..742dedb35 100644
--- a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx
@@ -13,6 +13,7 @@ import { EllipsisTextCss, ValueFromOption } from "lowcoder-design";
import { trans } from "i18n";
import { fixOldInputCompData } from "../textInputComp/textInputConstants";
import { migrateOldData } from "comps/generators/simpleGenerators";
+import { useEffect, useRef } from "react";
const getStyle = (style: RadioStyleType, inputFieldStyle?:RadioStyleType ) => {
return css`
@@ -102,6 +103,18 @@ let RadioBasicComp = (function () {
validateState,
handleChange,
] = useSelectInputValidate(props);
+
+ const radioRef = useRef(null);
+
+ useEffect(() => {
+ if (radioRef.current && typeof props.tabIndex === 'number') {
+ const firstRadioInput = radioRef.current.querySelector('input[type="radio"]');
+ if (firstRadioInput) {
+ firstRadioInput.setAttribute('tabindex', props.tabIndex.toString());
+ }
+ }
+ }, [props.tabIndex, props.options]);
+
return props.label({
required: props.required,
style: props.style,
@@ -110,7 +123,12 @@ let RadioBasicComp = (function () {
animationStyle:props.animationStyle,
children: (
{
+ if (el) {
+ props.viewRef(el);
+ radioRef.current = el;
+ }
+ }}
disabled={props.disabled}
value={props.value.value}
$style={props.style}
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx
index 2945fec1f..ff2e2893f 100644
--- a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx
+++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx
@@ -1,5 +1,5 @@
import { RecordConstructorToComp } from "lowcoder-core";
-import { BoolCodeControl } from "../../controls/codeControl";
+import { BoolCodeControl, NumberControl } from "../../controls/codeControl";
import { LabelControl } from "../../controls/labelControl";
import {
arrayStringExposingStateControl,
@@ -43,6 +43,7 @@ export const RadioChildrenMap = {
viewRef: RefControl,
inputFieldStyle:styleControl(RadioStyle ,'inputFieldStyle' ),
animationStyle: styleControl(AnimationStyle , 'animationStyle'),
+ tabIndex: NumberControl,
...SelectInputValidationChildren,
...formDataChildren,
};
@@ -73,6 +74,9 @@ export const RadioPropertyView = (
{disabledPropertyView(children)}
{hiddenPropertyView(children)}
{showDataLoadingIndicatorsPropertyView(children as any)}
+
+
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
>
)}
diff --git a/client/packages/lowcoder/src/comps/comps/switchComp.tsx b/client/packages/lowcoder/src/comps/comps/switchComp.tsx
index 730f521df..c4745cc48 100644
--- a/client/packages/lowcoder/src/comps/comps/switchComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/switchComp.tsx
@@ -1,5 +1,5 @@
import { default as Switch } from "antd/es/switch";
-import { BoolCodeControl } from "comps/controls/codeControl";
+import { BoolCodeControl, NumberControl } from "comps/controls/codeControl";
import { booleanExposingStateControl } from "comps/controls/codeStateControl";
import { changeEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
import { LabelControl } from "comps/controls/labelControl";
@@ -104,6 +104,7 @@ let SwitchTmpComp = (function () {
),
viewRef: RefControl,
inputFieldStyle: migrateOldData(styleControl(SwitchStyle, 'inputFieldStyle'), fixOldData),
+ tabIndex: NumberControl,
...formDataChildren,
};
return new UICompBuilder(childrenMap, (props) => {
@@ -125,6 +126,7 @@ let SwitchTmpComp = (function () {
checked={value}
disabled={props.disabled}
ref={props.viewRef}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
onChange={(checked) => {
props.value.onChange(checked);
props.onEvent("change");
@@ -149,6 +151,7 @@ let SwitchTmpComp = (function () {
{children.onEvent.getPropertyView()}
{disabledPropertyView(children)}
{hiddenPropertyView(children)}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
{showDataLoadingIndicatorsPropertyView(children)}
)}
diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx
index 6222fb6de..28626079c 100644
--- a/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/textInputComp/inputComp.tsx
@@ -32,6 +32,8 @@ import { hasIcon } from "comps/utils";
import { InputRef } from "antd/es/input";
import { RefControl } from "comps/controls/refControl";
import { migrateOldData, withDefault } from "comps/generators/simpleGenerators";
+import { numberSimpleControl } from "comps/controls/numberSimpleControl";
+import { NumberControl } from "comps/controls/codeControl";
import React, { useContext, useEffect } from "react";
import { EditorContext } from "comps/editorState";
@@ -55,8 +57,9 @@ const childrenMap = {
labelStyle:styleControl(LabelStyle, 'labelStyle'),
prefixIcon: IconControl,
suffixIcon: IconControl,
- inputFieldStyle: styleControl(InputLikeStyle, 'inputFieldStyle') ,
+ inputFieldStyle: styleControl(InputLikeStyle, 'inputFieldStyle'),
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
+ tabIndex: NumberControl,
};
let InputBasicComp = new UICompBuilder(childrenMap, (props) => {
@@ -72,6 +75,7 @@ let InputBasicComp = new UICompBuilder(childrenMap, (props) => {
$style={props.inputFieldStyle}
prefix={hasIcon(props.prefixIcon) && props.prefixIcon}
suffix={hasIcon(props.suffixIcon) && props.suffixIcon}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
),
style: props.style,
@@ -99,6 +103,7 @@ let InputBasicComp = new UICompBuilder(childrenMap, (props) => {
{children.prefixIcon.propertyView({ label: trans("button.prefixIcon") })}
{children.suffixIcon.propertyView({ label: trans("button.suffixIcon") })}
{children.showCount.propertyView({ label: trans("prop.showCount") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
{allowClearPropertyView(children)}
{readOnlyPropertyView(children)}
diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx
index 846a81a7d..434704387 100644
--- a/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/textInputComp/passwordComp.tsx
@@ -42,6 +42,7 @@ import { RefControl } from "comps/controls/refControl";
import React, { useContext, useEffect } from "react";
import { EditorContext } from "comps/editorState";
import { migrateOldData } from "comps/generators/simpleGenerators";
+import { NumberControl } from "comps/controls/codeControl";
const PasswordStyle = styled(InputPassword)<{
$style: InputLikeStyleType;
@@ -63,6 +64,7 @@ let PasswordTmpComp = (function () {
labelStyle: styleControl(LabelStyle,'labelStyle'),
inputFieldStyle: styleControl(InputLikeStyle , 'inputFieldStyle'),
animationStyle: styleControl(AnimationStyle , 'animationStyle'),
+ tabIndex: NumberControl,
};
return new UICompBuilder(childrenMap, (props, dispatch) => {
const [inputProps, validateState] = useTextInputProps(props);
@@ -76,6 +78,7 @@ let PasswordTmpComp = (function () {
ref={props.viewRef}
visibilityToggle={props.visibilityToggle}
$style={props.inputFieldStyle}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
),
style: props.style,
@@ -105,6 +108,7 @@ let PasswordTmpComp = (function () {
})}
{readOnlyPropertyView(children)}
{children.prefixIcon.propertyView({ label: trans("button.prefixIcon") })}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
{requiredPropertyView(children)}
{children.showValidationWhenEmpty.propertyView({label: trans("prop.showEmptyValidation")})}
diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
index b631d65fb..c8a7582eb 100644
--- a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
@@ -33,6 +33,7 @@ import { trans } from "i18n";
import { RefControl } from "comps/controls/refControl";
import { TextAreaRef } from "antd/es/input/TextArea";
import { blurMethod, focusWithOptions } from "comps/utils/methodUtils";
+import { NumberControl } from "comps/controls/codeControl";
import React, { useContext, useEffect } from "react";
import { EditorContext } from "comps/editorState";
@@ -80,7 +81,8 @@ let TextAreaTmpComp = (function () {
labelStyle: styleControl(LabelStyle ,'labelStyle' ),
textAreaScrollBar: withDefault(BoolControl, false),
inputFieldStyle: styleControl(InputLikeStyle , 'inputFieldStyle'),
- animationStyle: styleControl(AnimationStyle, 'animationStyle')
+ animationStyle: styleControl(AnimationStyle, 'animationStyle'),
+ tabIndex: NumberControl
};
return new UICompBuilder(childrenMap, (props) => {
const [inputProps, validateState] = useTextInputProps(props);
@@ -96,6 +98,7 @@ let TextAreaTmpComp = (function () {
allowClear={props.allowClear}
style={{ height: "100% !important", resize: "vertical" }}
$style={props.inputFieldStyle}
+ tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
/>
),
@@ -128,6 +131,7 @@ let TextAreaTmpComp = (function () {
{allowClearPropertyView(children)}
{readOnlyPropertyView(children)}
+ {children.tabIndex.propertyView({ label: trans("prop.tabIndex") })}
>
)}
diff --git a/client/packages/lowcoder/src/comps/utils/propertyUtils.tsx b/client/packages/lowcoder/src/comps/utils/propertyUtils.tsx
index e361a64cc..5f65242cb 100644
--- a/client/packages/lowcoder/src/comps/utils/propertyUtils.tsx
+++ b/client/packages/lowcoder/src/comps/utils/propertyUtils.tsx
@@ -40,6 +40,7 @@ export const allowClearPropertyView = (children: {
allowClear: InstanceType;
}) => children.allowClear.propertyView({ label: trans("prop.showClear") });
+
export const showSearchPropertyView = (children: {
showSearch: InstanceType;
}) => children.showSearch.propertyView({ label: trans("prop.showSearch") });
diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts
index d1eff10d7..50a912523 100644
--- a/client/packages/lowcoder/src/i18n/locales/en.ts
+++ b/client/packages/lowcoder/src/i18n/locales/en.ts
@@ -176,6 +176,7 @@ export const en = {
"width": "Width",
"selectApp": "Select App",
"showCount": "Show Count",
+ "tabIndex": "Tab Index",
"textType": "Text Type",
"customRule": "Custom Rule",
"customRuleTooltip": "Non-empty string indicates an error; empty or null means validation passed. Example: ",