diff --git a/README.md b/README.md index 8c27df8..95eb15a 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ The canvas has no additional attributes. however, canvases take an atypical chil - `valign` - `VerticalAlignment`: Equivalent to calling `layoutBox.setVerticalAlignment(...)`. - `halign` - `HorizontalAlignment`: Equivalent to calling `layoutBox.setHorizontalAlignment(...)`. -- `padding` - `{ left?: number, right?: number, top?: number, bottom?: number }`: Equivalent to calling `layoutBox.setPadding(...)`. +- `padding` - `number | { left?: number, right?: number, top?: number, bottom?: number }`: Equivalent to calling `layoutBox.setPadding(...)` if a single number is used, it is applied to all four directions. - `maxHeight` - `number`: Equivalent to calling `layoutBox.setMaximumHeight(...)`. - `minHeight` - `number`: Equivalent to calling `layoutBox.setMinimumHeight(...)`. - `height` - `number`: Equivalent to calling `layoutBox.setOverrideHeight(...)`. @@ -340,7 +340,8 @@ VerticalBox (as well as the HorizontalBox) can take a special function child, mu - `italic` - `boolean`: Equivalent to calling `checkbox.setItalic(...)`. - `size` - `number`: Equivalent to calling `checkbox.setFontSize(...)`. - `color` - `[number, number, number, number]` or `Color`: Equivalent to calling `checkbox.setTextColor(...)`. -- `onChange` - `(checkbox: CheckBox, player: Player | undefined, state: boolean) => void`: Equivalent to adding a change event handler using `onCheckStateChanged.add(...)`. +- `onChange` - `(checkbox: CheckBox, player: Player, state: boolean) => void`: Equivalent to adding a change event handler using `onCheckStateChanged.add(...)` but will only trigger on user input, not on programmatic input. +- `onChangeActual` - `(checkbox: CheckBox, player: Player | undefined, state: boolean) => void`: Equivalent to adding a change event handler using `onCheckStateChanged.add(...)`. - `checked` - `boolean`: Equivalent to calling `checkbox.setIsChecked(...)`. - `label` - `string` or `string[]`: Equivalent to setting the checkbox label using `setText(...)`. - `font` - `string`: Equivalent to setting the font using `setFont(...)`. @@ -374,8 +375,10 @@ VerticalBox (as well as the HorizontalBox) can take a special function child, mu - `italic` - `boolean`: Equivalent to calling `multilineTextBox.setItalic(...)`. - `size` - `number`: Equivalent to calling `multilineTextBox.setFontSize(...)`. - `color` - `[number, number, number, number]` or `Color`: Equivalent to calling `multilineTextBox.setTextColor(...)`. -- `onChange` - `(element: MultilineTextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)`. -- `onCommit` - `(element: MultilineTextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)`. +- `onChange` - `(element: MultilineTextBox, player: Player, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onChangeActual` - `(element: MultilineTextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)`. +- `onCommit` - `(element: MultilineTextBox, player: Player, text: string) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onCommitActual` - `(element: MultilineTextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)`. - `maxLength` - `number`: Equivalent to setting the maximum length of the text using `setMaxLength(...)`. - `transparent` - `boolean`: Equivalent to calling `multilineTextBox.setTransparent(...)`. - `font` - `string`: Equivalent to setting the font using `setFont(...)`. @@ -443,7 +446,8 @@ VerticalBox (as well as the HorizontalBox) can take a special function child, mu - `italic` - `boolean`: Equivalent to calling `selectionBox.setItalic(...)`. - `size` - `number`: Equivalent to calling `selectionBox.setFontSize(...)`. - `color` - `[number, number, number, number]` or `Color`: Equivalent to calling `selectionBox.setTextColor(...)`. -- `onChange` - `(element: SelectionBox, player: Player | undefined, index: number, option: string) => void`: Equivalent to adding a change event handler using `onSelectionChanged.add(...)`. +- `onChange` - `(element: SelectionBox, player: Player, index: number, option: string) => void`: Equivalent to adding a change event handler using `onSelectionChanged.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onChangeActual` - `(element: SelectionBox, player: Player | undefined, index: number, option: string) => void`: Equivalent to adding a change event handler using `onSelectionChanged.add(...)`. - `value` - `string`: Equivalent to setting the selected option using `setSelectedOption(...)`. - `options` - `string[]`: An array of available options for the selection box. - `font` - `string`: Equivalent to setting the font using `setFont(...)`. @@ -483,7 +487,8 @@ VerticalBox (as well as the HorizontalBox) can take a special function child, mu - `value` - `number`: Equivalent to setting the current value using `setValue(...)`. - `max` - `number`: Equivalent to setting the maximum value using `setMaxValue(...)`. - `step` - `number`: Equivalent to setting the step size using `setStepSize(...)`. -- `onChange` - `(element: Slider, player: Player | undefined, value: number) => void`: Equivalent to adding a change event handler using `onValueChanged.add(...)`. +- `onChange` - `(element: Slider, player: Player, value: number) => void`: Equivalent to adding a change event handler using `onValueChanged.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onChangeActual` - `(element: Slider, player: Player | undefined, value: number) => void`: Equivalent to adding a change event handler using `onValueChanged.add(...)`. - `inputWidth` - `number`: Equivalent to setting the width of the input box using `setTextBoxWidth(...)`. - `font` - `string`: Equivalent to setting the font using `setFont(...)`. - `fontPackage` - `string`: Equivalent to setting the font package using `setFont(...)` with a package specifier. @@ -516,8 +521,10 @@ VerticalBox (as well as the HorizontalBox) can take a special function child, mu - `italic` - `boolean`: Equivalent to calling `textBox.setItalic(...)`. - `size` - `number`: Equivalent to calling `textBox.setFontSize(...)`. - `color` - `[number, number, number, number]` or `Color`: Equivalent to calling `textBox.setTextColor(...)`. -- `onChange` - `(element: TextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)`. -- `onCommit` - `(element: TextBox, player: Player | undefined, text: string, hardCommit: boolean) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)`. +- `onChange` - `(element: TextBox, player: Player, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onChangeActual` - `(element: TextBox, player: Player | undefined, text: string) => void`: Equivalent to adding a change event handler using `onTextChanged.add(...)`. +- `onCommit` - `(element: TextBox, player: Player, text: string, hardCommit: boolean) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)` but will only trigger on user interaction, not programatic interaction. +- `onCommitActual` - `(element: TextBox, player: Player | undefined, text: string, hardCommit: boolean) => void`: Equivalent to adding a commit event handler using `onTextCommitted.add(...)`. - `maxLength` - `number`: Equivalent to setting the maximum length of the text using `setMaxLength(...)`. - `transparent` - `boolean`: Equivalent to calling `textBox.setBackgroundTransparent(...)`. - `selectOnFocus` - `boolean`: Equivalent to calling `textBox.setSelectTextOnFocus(...)`. @@ -582,7 +589,7 @@ const checkRef = () => { element.widget = render( - + @@ -610,7 +617,7 @@ const checkRef = () => { element.widget = render( - + {imageElement} diff --git a/package.json b/package.json index 9b16e88..1a49c01 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jsx-in-ttpg", "license": "UNLICENSE", - "version": "1.1.4", + "version": "1.2.0", "scripts": { "build": "tsup src/index.ts --format cjs,esm --dts --no-splitting", "clean": "rm -rf ./dist", diff --git a/src/index.ts b/src/index.ts index a87ada3..386af33 100644 --- a/src/index.ts +++ b/src/index.ts @@ -301,13 +301,17 @@ const doImagelike = (element: T, attrs: Ima if (attrs.color) { element.setTintColor(attrs.color); } - if ("url" in attrs) { + if ("url" in attrs && attrs.url) { element.setImageURL(attrs.url); } - if ("src" in attrs) { - element.setImage(attrs.src, attrs.srcPackage); + if ("src" in attrs && attrs.src) { + if ("srcPackage" in attrs && attrs.srcPackage) { + element.setImage(attrs.src, attrs.srcPackage); + } else { + element.setImage(attrs.src); + } } - if ("card" in attrs) { + if ("card" in attrs && attrs.card) { element.setSourceCard(attrs.card); } element.setImageSize(attrs?.width ?? 0, attrs?.height ?? 0); @@ -326,9 +330,7 @@ type TextlikeObject = CommonElement & { size?: number; color?: Color | [number, number, number, number]; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -340,10 +342,9 @@ type ImagelikeObject = CommonElement & { width?: number; height?: number; } & ( - | { url: string } - | { - card: Card; - } + | { url?: string } + | { card?: Card } + | { src?: string } | { src: string; srcPackage?: string; @@ -449,7 +450,11 @@ const layoutElement = (attrs: JSX.IntrinsicElements["layout"], child?: Widget) = element.setChild(child); } if (attrs.padding) { - element.setPadding(attrs.padding.left, attrs.padding.right, attrs.padding.top, attrs.padding.bottom); + if (typeof attrs.padding === "number") { + element.setPadding(attrs.padding, attrs.padding, attrs.padding, attrs.padding); + } else { + element.setPadding(attrs.padding.left, attrs.padding.right, attrs.padding.top, attrs.padding.bottom); + } } if (attrs.halign) { element.setHorizontalAlignment(attrs.halign); @@ -522,7 +527,14 @@ const checkboxElement = (attrs: JSX.IntrinsicElements["checkbox"]) => { element.setText(Array.isArray(attrs.label) ? attrs.label.join("") : attrs.label); } if (attrs.onChange) { - element.onCheckStateChanged.add(attrs.onChange); + element.onCheckStateChanged.add((s, p, v) => { + if (p !== undefined) { + attrs.onChange?.(s, p, v); + } + }); + } + if (attrs.onChangeActual) { + element.onCheckStateChanged.add(attrs.onChangeActual); } element.setIsChecked(!!attrs.checked); return element; @@ -535,10 +547,24 @@ const textareaElement = (attrs: JSX.IntrinsicElements["textarea"], children?: st element.setText(children?.join("")); } if (attrs.onChange) { - element.onTextChanged.add(attrs.onChange); + element.onTextChanged.add((s, p, v) => { + if (p !== undefined) { + attrs.onChange?.(s, p, v); + } + }); + } + if (attrs.onChangeActual) { + element.onTextChanged.add(attrs.onChangeActual); } if (attrs.onCommit) { - element.onTextCommitted.add(attrs.onCommit); + element.onTextCommitted.add((s, p, v) => { + if (p !== undefined) { + attrs.onCommit?.(s, p, v); + } + }); + } + if (attrs.onCommitActual) { + element.onTextCommitted.add(attrs.onCommitActual); } return element; }; @@ -576,7 +602,14 @@ const selectElement = (attrs: JSX.IntrinsicElements["select"]) => { element.setSelectedOption(attrs.value); } if (attrs.onChange) { - element.onSelectionChanged.add(attrs.onChange); + element.onSelectionChanged.add((s, p, i, v) => { + if (p !== undefined) { + attrs.onChange?.(s, p, i, v); + } + }); + } + if (attrs.onChangeActual) { + element.onSelectionChanged.add(attrs.onChangeActual); } return element; }; @@ -585,7 +618,14 @@ const sliderElement = (attrs: JSX.IntrinsicElements["slider"]) => { const element = new Slider(); doTextlike(element, attrs); if (attrs.onChange) { - element.onValueChanged.add(attrs.onChange); + element.onValueChanged.add((s, p, v) => { + if (p !== undefined) { + attrs.onChange?.(s, p, v); + } + }); + } + if (attrs.onChangeActual) { + element.onValueChanged.add(attrs.onChangeActual); } if (attrs.min) { element.setMinValue(attrs.min); @@ -608,11 +648,26 @@ const sliderElement = (attrs: JSX.IntrinsicElements["slider"]) => { const inputElement = (attrs: JSX.IntrinsicElements["input"]) => { const element = new TextBox(); doTextlike(element, attrs); + if (attrs.onChange) { - element.onTextChanged.add(attrs.onChange); + element.onTextChanged.add((s, p, v) => { + if (p !== undefined) { + attrs.onChange?.(s, p, v); + } + }); + } + if (attrs.onChangeActual) { + element.onTextChanged.add(attrs.onChangeActual); } if (attrs.onCommit) { - element.onTextCommitted.add(attrs.onCommit); + element.onTextCommitted.add((s, p, v, h) => { + if (p !== undefined) { + attrs.onCommit?.(s, p, v, h); + } + }); + } + if (attrs.onCommitActual) { + element.onTextCommitted.add(attrs.onCommitActual); } if (attrs.selectOnFocus) { element.setSelectTextOnFocus(attrs.selectOnFocus); @@ -693,9 +748,7 @@ declare global { children?: never; } & ( | { url: string } - | { - card: Card; - } + | { card: Card } | { src: string; srcPackage?: string; @@ -713,9 +766,7 @@ declare global { children?: never; } & ( | { url: string } - | { - card: Card; - } + | { card: Card } | { src: string; srcPackage?: string; @@ -765,12 +816,14 @@ declare global { hidden?: boolean; valign?: VerticalAlignment; halign?: HorizontalAlignment; - padding?: { - left?: number; - right?: number; - top?: number; - bottom?: number; - }; + padding?: + | number + | { + left?: number; + right?: number; + top?: number; + bottom?: number; + }; maxHeight?: number; minHeight?: number; height?: number; @@ -791,9 +844,7 @@ declare global { justify?: TextJustification; children?: TextNode; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -810,9 +861,7 @@ declare global { onClick?: (button: Button, player: Player) => void; children?: TextNode; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -826,14 +875,13 @@ declare global { italic?: boolean; size?: number; color?: Color | [number, number, number, number]; - onChange?: (checkbox: CheckBox, player: Player | undefined, state: boolean) => void; + onChange?: (checkbox: CheckBox, player: Player, state: boolean) => void; + onChangeActual?: (checkbox: CheckBox, player: Player | undefined, state: boolean) => void; checked?: boolean; label?: string | string[]; children?: never; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -847,15 +895,15 @@ declare global { italic?: boolean; size?: number; color?: Color | [number, number, number, number]; - onChange?: (element: MultilineTextBox, player: Player | undefined, text: string) => void; - onCommit?: (element: MultilineTextBox, player: Player | undefined, text: string) => void; + onChange?: (element: MultilineTextBox, player: Player, text: string) => void; + onChangeActual?: (element: MultilineTextBox, player: Player | undefined, text: string) => void; + onCommit?: (element: MultilineTextBox, player: Player, text: string) => void; + onCommitActual?: (element: MultilineTextBox, player: Player | undefined, text: string) => void; maxLength?: number; transparent?: boolean; children?: TextNode; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -874,9 +922,7 @@ declare global { label?: string | string[]; children?: never; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -894,9 +940,7 @@ declare global { justify?: TextJustification; children?: TextNode; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -910,14 +954,13 @@ declare global { italic?: boolean; size?: number; color?: Color | [number, number, number, number]; - onChange?: (element: SelectionBox, player: Player | undefined, index: number, option: string) => void; + onChange?: (element: SelectionBox, player: Player, index: number, option: string) => void; + onChangeActual?: (element: SelectionBox, player: Player | undefined, index: number, option: string) => void; value?: string; options: string[]; children?: never; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -935,13 +978,12 @@ declare global { value?: number; max?: number; step?: number; - onChange?: (element: Slider, player: Player | undefined, value: number) => void; + onChange?: (element: Slider, player: Player, value: number) => void; + onChangeActual?: (element: Slider, player: Player | undefined, value: number) => void; inputWidth?: number; children?: never; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string; @@ -955,8 +997,10 @@ declare global { italic?: boolean; size?: number; color?: Color | [number, number, number, number]; - onChange?: (element: TextBox, player: Player | undefined, text: string) => void; - onCommit?: (element: TextBox, player: Player | undefined, text: string, hardCommit: boolean) => void; + onChange?: (element: TextBox, player: Player, text: string) => void; + onChangeActual?: (element: TextBox, player: Player | undefined, text: string) => void; + onCommit?: (element: TextBox, player: Player, text: string, hardCommit: boolean) => void; + onCommitActual?: (element: TextBox, player: Player | undefined, text: string, hardCommit: boolean) => void; maxLength?: number; transparent?: boolean; selectOnFocus?: boolean; @@ -964,9 +1008,7 @@ declare global { type?: "string" | "float" | "positive-float" | "integer" | "positive-integer"; children?: never; } & ( - | { - font?: string; - } + | { font?: string } | { font: string; fontPackage?: string;