diff --git a/apps/client/src/widgets/react/FormSelect.tsx b/apps/client/src/widgets/react/FormSelect.tsx index cd003c6ae..dc8916255 100644 --- a/apps/client/src/widgets/react/FormSelect.tsx +++ b/apps/client/src/widgets/react/FormSelect.tsx @@ -1,4 +1,5 @@ import type { ComponentChildren } from "preact"; +import { CSSProperties } from "preact/compat"; type OnChangeListener = (newValue: string) => void; @@ -19,15 +20,16 @@ interface ValueConfig { interface FormSelectProps extends ValueConfig { onChange: OnChangeListener; + style?: CSSProperties; } /** * Combobox component that takes in any object array as data. Each item of the array is rendered as an item, and the key and values are obtained by looking into the object by a specified key. */ -export default function FormSelect(props: FormSelectProps) { +export default function FormSelect({ onChange, style, ...restProps }: FormSelectProps) { return ( - - + + ); } @@ -49,11 +51,12 @@ export function FormSelectWithGroups({ values, keyProperty, titleProperty, cu ) } -function FormSelectBody({ children, onChange }: { children: ComponentChildren, onChange: OnChangeListener }) { +function FormSelectBody({ children, onChange, style }: { children: ComponentChildren, onChange: OnChangeListener, style?: CSSProperties }) { return ( diff --git a/apps/client/src/widgets/react/FormTextBox.tsx b/apps/client/src/widgets/react/FormTextBox.tsx index 01b7b56c2..99697d11f 100644 --- a/apps/client/src/widgets/react/FormTextBox.tsx +++ b/apps/client/src/widgets/react/FormTextBox.tsx @@ -3,14 +3,13 @@ import type { InputHTMLAttributes, RefObject } from "preact/compat"; interface FormTextBoxProps extends Omit, "onChange" | "value"> { id?: string; currentValue?: string; - onChange?(newValue: string): void; + onChange?(newValue: string, validity: ValidityState): void | false; inputRef?: RefObject; } export default function FormTextBox({ inputRef, className, type, currentValue, onChange, ...rest}: FormTextBoxProps) { if (type === "number" && currentValue) { const { min, max } = rest; - console.log(currentValue , min, max); const currentValueNum = parseInt(currentValue, 10); if (min && currentValueNum < parseInt(String(min), 10)) { currentValue = String(min); @@ -25,7 +24,10 @@ export default function FormTextBox({ inputRef, className, type, currentValue, o className={`form-control ${className ?? ""}`} type={type ?? "text"} value={currentValue} - onInput={e => onChange?.(e.currentTarget.value)} + onInput={e => { + const target = e.currentTarget; + onChange?.(target.value, target.validity); + }} {...rest} /> ); diff --git a/apps/client/src/widgets/type_widgets/content_widget.tsx b/apps/client/src/widgets/type_widgets/content_widget.tsx index 62dd7b2aa..ba5150c76 100644 --- a/apps/client/src/widgets/type_widgets/content_widget.tsx +++ b/apps/client/src/widgets/type_widgets/content_widget.tsx @@ -29,6 +29,7 @@ import PasswordSettings from "./options/password.jsx"; import ShortcutSettings from "./options/shortcuts.js"; import TextNoteSettings from "./options/text_notes.jsx"; import CodeNoteSettings from "./options/code_notes.jsx"; +import OtherSettings from "./options/other.jsx"; const TPL = /*html*/`
`; - -export default class TimeSelector extends OptionsWidget { - private $timeValueInput!: JQuery; - private $timeScaleSelect!: JQuery; - private internalTimeInSeconds!: string | number; - private widgetId: string; - private widgetLabelId: string; - private optionValueId: keyof OptionDefinitions; - private optionTimeScaleId: keyof OptionDefinitions; - private includedTimeScales: Set; - private minimumSeconds: number; - - constructor(options: TimeSelectorConstructor) { - super(); - this.widgetId = options.widgetId; - this.widgetLabelId = options.widgetLabelId; - this.optionValueId = options.optionValueId; - this.optionTimeScaleId = options.optionTimeScaleId; - this.includedTimeScales = options.includedTimeScales || new Set(["seconds", "minutes", "hours", "days"]); - this.minimumSeconds = options.minimumSeconds || 0; - } - - doRender() { - this.$widget = $( - TPL({ - widgetId: this.widgetId, - widgetLabelId: this.widgetLabelId, - includedTimeScales: this.includedTimeScales - }) - ); - - this.$timeValueInput = this.$widget.find(`#${this.widgetId}`); - this.$timeScaleSelect = this.$widget.find(`#${this.widgetId}-time-scale`); - - this.$timeValueInput.on("change", () => { - const time = this.$timeValueInput.val(); - const timeScale = this.$timeScaleSelect.val(); - - if (!this.handleTimeValidation() || typeof timeScale !== "string" || !time) return; - - this.setInternalTimeInSeconds(this.convertTime(time, timeScale).toOption()); - - this.updateOption(this.optionValueId, this.internalTimeInSeconds); - }); - - this.$timeScaleSelect.on("change", () => { - const timeScale = this.$timeScaleSelect.val(); - - if (!this.handleTimeValidation() || typeof timeScale !== "string") return; - - //calculate the new displayed value - const displayedTime = this.convertTime(this.internalTimeInSeconds, timeScale).toDisplay(); - - this.updateOption(this.optionTimeScaleId, timeScale); - this.$timeValueInput.val(displayedTime).trigger("change"); - }); - } - - async optionsLoaded(options: OptionMap) { - const optionValue = optionsService.getInt(this.optionValueId) || 0; - const optionTimeScale = optionsService.getInt(this.optionTimeScaleId) || 1; - - this.setInternalTimeInSeconds(optionValue); - - const displayedTime = this.convertTime(optionValue, optionTimeScale).toDisplay(); - this.$timeValueInput.val(displayedTime); - this.$timeScaleSelect.val(optionTimeScale); - } - - private convertTime(time: string | number, timeScale: string | number) { - const value = typeof time === "number" ? time : parseInt(time); - if (Number.isNaN(value)) { - throw new Error(`Time needs to be a valid integer, but received: ${time}`); - } - - const operand = typeof timeScale === "number" ? timeScale : parseInt(timeScale); - if (Number.isNaN(operand) || operand < 1) { - throw new Error(`TimeScale needs to be a valid integer >= 1, but received: ${timeScale}`); - } - - return { - toOption: () => Math.ceil(value * operand), - toDisplay: () => Math.ceil(value / operand) - }; - } - - private handleTimeValidation() { - if (this.$timeValueInput.is(":invalid")) { - toastService.showError(t("time_selector.invalid_input")); - return false; - } - return true; - } - - private setInternalTimeInSeconds(time: number) { - if (time < this.minimumSeconds) { - toastService.showError(t("time_selector.minimum_input", { minimumSeconds: this.minimumSeconds })); - return (this.internalTimeInSeconds = this.minimumSeconds); - } - return (this.internalTimeInSeconds = time); - } - -}