mirror of
https://github.com/SikongJueluo/cc-utils.git
synced 2025-11-04 19:27:50 +08:00
feature: tui onFocusChanged event
feature: add focus event for tui reconstruct: tui props and accesscontrol parse logic
This commit is contained in:
@@ -243,6 +243,18 @@ const AccessControlTUI = () => {
|
||||
/**
|
||||
* Basic Configuration Tab
|
||||
*/
|
||||
const [getDetectInterval, setDetectInterval] = createSignal(
|
||||
config().detectInterval.toString(),
|
||||
);
|
||||
const [getWatchInterval, setWatchInterval] = createSignal(
|
||||
config().watchInterval.toString(),
|
||||
);
|
||||
const [getNoticeTimes, setNoticeTimes] = createSignal(
|
||||
config().noticeTimes.toString(),
|
||||
);
|
||||
const [getDetectRange, setDetectRange] = createSignal(
|
||||
config().detectRange.toString(),
|
||||
);
|
||||
const BasicTab = () => {
|
||||
return div(
|
||||
{ class: "flex flex-col" },
|
||||
@@ -251,10 +263,12 @@ const AccessControlTUI = () => {
|
||||
label({}, "Detect Interval (ms):"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => config().detectInterval?.toString() ?? "",
|
||||
onInput: (value) => {
|
||||
const num = validateNumber(value);
|
||||
value: () => getDetectInterval(),
|
||||
onInput: (value) => setDetectInterval(value),
|
||||
onFocusChanged: () => {
|
||||
const num = validateNumber(getDetectInterval());
|
||||
if (num !== null) setConfig("detectInterval", num);
|
||||
else setDetectInterval(config().detectInterval.toString());
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -263,10 +277,12 @@ const AccessControlTUI = () => {
|
||||
label({}, "Watch Interval (ms):"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => config().watchInterval?.toString() ?? "",
|
||||
onInput: (value) => {
|
||||
const num = validateNumber(value);
|
||||
value: () => getWatchInterval(),
|
||||
onInput: (value) => setWatchInterval(value),
|
||||
onFocusChanged: () => {
|
||||
const num = validateNumber(getWatchInterval());
|
||||
if (num !== null) setConfig("watchInterval", num);
|
||||
else setWatchInterval(config().watchInterval.toString());
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -275,10 +291,12 @@ const AccessControlTUI = () => {
|
||||
label({}, "Notice Times:"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => config().noticeTimes?.toString() ?? "",
|
||||
onInput: (value) => {
|
||||
const num = validateNumber(value);
|
||||
value: () => getNoticeTimes(),
|
||||
onInput: (value) => setNoticeTimes(value),
|
||||
onFocusChanged: () => {
|
||||
const num = validateNumber(getNoticeTimes());
|
||||
if (num !== null) setConfig("noticeTimes", num);
|
||||
else setNoticeTimes(config().noticeTimes.toString());
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -287,10 +305,12 @@ const AccessControlTUI = () => {
|
||||
label({}, "Detect Range:"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => config().detectRange?.toString() ?? "",
|
||||
onInput: (value) => {
|
||||
const num = validateNumber(value);
|
||||
value: () => getDetectRange(),
|
||||
onInput: (value) => setDetectRange(value),
|
||||
onFocusChanged: () => {
|
||||
const num = validateNumber(getDetectRange());
|
||||
if (num !== null) setConfig("detectRange", num);
|
||||
else setDetectRange(config().detectRange.toString());
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -436,6 +456,13 @@ const AccessControlTUI = () => {
|
||||
) => {
|
||||
return () => {
|
||||
const toastConfig = config()[toastType];
|
||||
const [getTempToastConfig, setTempToastConfig] = createSignal({
|
||||
title: textutils.serialiseJSON(toastConfig.title),
|
||||
msg: textutils.serialiseJSON(toastConfig.msg),
|
||||
prefix: toastConfig.prefix ?? "",
|
||||
brackets: toastConfig.brackets ?? "",
|
||||
bracketColor: toastConfig.bracketColor ?? "",
|
||||
});
|
||||
|
||||
return div(
|
||||
{ class: "flex flex-col w-full" },
|
||||
@@ -443,20 +470,34 @@ const AccessControlTUI = () => {
|
||||
input({
|
||||
class: "w-full",
|
||||
type: "text",
|
||||
value: () => textutils.serialiseJSON(toastConfig?.title) ?? "",
|
||||
onInput: (value) => {
|
||||
value: () => getTempToastConfig().title,
|
||||
onInput: (value) =>
|
||||
setTempToastConfig({
|
||||
...getTempToastConfig(),
|
||||
title: value,
|
||||
}),
|
||||
onFocusChanged: () => {
|
||||
const currentToastConfig = config()[toastType];
|
||||
|
||||
try {
|
||||
const parsed = textutils.unserialiseJSON(value);
|
||||
if (parsed != undefined && typeof parsed === "object") {
|
||||
const currentConfig = config();
|
||||
const currentToast = currentConfig[toastType];
|
||||
const parsed = textutils.unserialiseJSON(
|
||||
getTempToastConfig().title,
|
||||
) as MinecraftTextComponent;
|
||||
if (
|
||||
typeof parsed === "object" &&
|
||||
parsed.text !== undefined &&
|
||||
parsed.color !== undefined
|
||||
) {
|
||||
setConfig(toastType, {
|
||||
...currentToast,
|
||||
title: parsed as MinecraftTextComponent,
|
||||
...currentToastConfig,
|
||||
title: parsed,
|
||||
});
|
||||
}
|
||||
} else throw new Error("Invalid JSON");
|
||||
} catch {
|
||||
// Invalid JSON, ignore
|
||||
setTempToastConfig({
|
||||
...getTempToastConfig(),
|
||||
title: textutils.serialiseJSON(currentToastConfig.title),
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
@@ -465,19 +506,31 @@ const AccessControlTUI = () => {
|
||||
input({
|
||||
class: "w-full",
|
||||
type: "text",
|
||||
value: () => textutils.serialiseJSON(toastConfig?.msg) ?? "",
|
||||
onInput: (value) => {
|
||||
value: () => getTempToastConfig().msg,
|
||||
onInput: (value) =>
|
||||
setTempToastConfig({ ...getTempToastConfig(), msg: value }),
|
||||
onFocusChanged: () => {
|
||||
const currentToastConfig = config()[toastType];
|
||||
|
||||
try {
|
||||
const parsed = textutils.unserialiseJSON(value);
|
||||
if (parsed != undefined && typeof parsed === "object") {
|
||||
const currentConfig = config();
|
||||
const currentToast = currentConfig[toastType];
|
||||
const parsed = textutils.unserialiseJSON(
|
||||
getTempToastConfig().msg,
|
||||
) as MinecraftTextComponent;
|
||||
if (
|
||||
typeof parsed === "object" &&
|
||||
parsed.text !== undefined &&
|
||||
parsed.color !== undefined
|
||||
) {
|
||||
setConfig(toastType, {
|
||||
...currentToast,
|
||||
msg: parsed as MinecraftTextComponent,
|
||||
...currentToastConfig,
|
||||
msg: parsed,
|
||||
});
|
||||
}
|
||||
} else throw new Error("Invalid JSON");
|
||||
} catch {
|
||||
setTempToastConfig({
|
||||
...getTempToastConfig(),
|
||||
msg: textutils.serialiseJSON(currentToastConfig.msg),
|
||||
});
|
||||
// Invalid JSON, ignore
|
||||
}
|
||||
},
|
||||
@@ -488,11 +541,15 @@ const AccessControlTUI = () => {
|
||||
label({}, "Prefix:"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => toastConfig?.prefix ?? "",
|
||||
onInput: (value) => {
|
||||
const currentConfig = config();
|
||||
const currentToast = currentConfig[toastType];
|
||||
setConfig(toastType, { ...currentToast, prefix: value });
|
||||
value: () => getTempToastConfig().prefix,
|
||||
onInput: (value) =>
|
||||
setTempToastConfig({ ...getTempToastConfig(), prefix: value }),
|
||||
onFocusChanged: () => {
|
||||
const currentToastConfig = config()[toastType];
|
||||
setConfig(toastType, {
|
||||
...currentToastConfig,
|
||||
prefix: getTempToastConfig().prefix,
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -502,11 +559,15 @@ const AccessControlTUI = () => {
|
||||
label({}, "Brackets:"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => toastConfig?.brackets ?? "",
|
||||
onInput: (value) => {
|
||||
const currentConfig = config();
|
||||
const currentToast = currentConfig[toastType];
|
||||
setConfig(toastType, { ...currentToast, brackets: value });
|
||||
value: () => getTempToastConfig().brackets,
|
||||
onInput: (value) =>
|
||||
setTempToastConfig({ ...getTempToastConfig(), brackets: value }),
|
||||
onFocusChanged: () => {
|
||||
const currentToastConfig = config()[toastType];
|
||||
setConfig(toastType, {
|
||||
...currentToastConfig,
|
||||
brackets: getTempToastConfig().brackets,
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
@@ -516,11 +577,18 @@ const AccessControlTUI = () => {
|
||||
label({}, "Bracket Color:"),
|
||||
input({
|
||||
type: "text",
|
||||
value: () => toastConfig?.bracketColor ?? "",
|
||||
onInput: (value) => {
|
||||
const currentConfig = config();
|
||||
const currentToast = currentConfig[toastType];
|
||||
setConfig(toastType, { ...currentToast, bracketColor: value });
|
||||
value: () => getTempToastConfig().bracketColor,
|
||||
onInput: (value) =>
|
||||
setTempToastConfig({
|
||||
...getTempToastConfig(),
|
||||
bracketColor: value,
|
||||
}),
|
||||
onFocusChanged: () => {
|
||||
const currentToastConfig = config()[toastType];
|
||||
setConfig(toastType, {
|
||||
...currentToastConfig,
|
||||
bracketColor: getTempToastConfig().bracketColor,
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* Represents a node in the UI tree
|
||||
*/
|
||||
|
||||
import { Accessor } from "./reactivity";
|
||||
import { ButtonProps, DivProps, InputProps, LabelProps } from "./components";
|
||||
import { Accessor, Setter } from "./reactivity";
|
||||
import { ScrollContainerProps } from "./scrollContainer";
|
||||
|
||||
/**
|
||||
* Layout properties for flexbox layout
|
||||
@@ -34,7 +36,7 @@ export interface StyleProps {
|
||||
/**
|
||||
* Scroll properties for scroll containers
|
||||
*/
|
||||
export interface ScrollProps {
|
||||
export interface ScrollProps extends BaseProps {
|
||||
/** Current horizontal scroll position */
|
||||
scrollX: number;
|
||||
/** Current vertical scroll position */
|
||||
@@ -69,6 +71,9 @@ export interface ComputedLayout {
|
||||
export interface BaseProps {
|
||||
/** CSS-like class names for layout (e.g., "flex flex-col") */
|
||||
class?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
onFocusChanged?: Setter<boolean> | ((value: boolean) => void);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +95,14 @@ export type UIObjectType =
|
||||
| "fragment"
|
||||
| "scroll-container";
|
||||
|
||||
export type UIObjectProps =
|
||||
| DivProps
|
||||
| LabelProps
|
||||
| InputProps
|
||||
| ButtonProps
|
||||
| ScrollProps
|
||||
| ScrollContainerProps;
|
||||
|
||||
/**
|
||||
* UIObject represents a node in the UI tree
|
||||
* It can be a component, text, or a control flow element
|
||||
@@ -99,7 +112,7 @@ export class UIObject {
|
||||
type: UIObjectType;
|
||||
|
||||
/** Props passed to the component */
|
||||
props: Record<string, unknown>;
|
||||
props: UIObjectProps;
|
||||
|
||||
/** Children UI objects */
|
||||
children: UIObject[];
|
||||
@@ -136,7 +149,7 @@ export class UIObject {
|
||||
|
||||
constructor(
|
||||
type: UIObjectType,
|
||||
props: Record<string, unknown> = {},
|
||||
props: UIObjectProps = {},
|
||||
children: UIObject[] = [],
|
||||
) {
|
||||
this.type = type;
|
||||
@@ -155,7 +168,7 @@ export class UIObject {
|
||||
this.extractHandlers();
|
||||
|
||||
// Initialize cursor position for text inputs
|
||||
if (type === "input" && props.type !== "checkbox") {
|
||||
if (type === "input" && (props as InputProps).type !== "checkbox") {
|
||||
this.cursorPos = 0;
|
||||
}
|
||||
|
||||
@@ -168,9 +181,9 @@ export class UIObject {
|
||||
maxScrollY: 0,
|
||||
contentWidth: 0,
|
||||
contentHeight: 0,
|
||||
showScrollbar: props.showScrollbar !== false,
|
||||
viewportWidth: (props.width as number) ?? 10,
|
||||
viewportHeight: (props.height as number) ?? 10,
|
||||
showScrollbar: (props as ScrollProps).showScrollbar !== false,
|
||||
viewportWidth: props.width ?? 10,
|
||||
viewportHeight: props.height ?? 10,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -208,7 +221,7 @@ export class UIObject {
|
||||
* Parse CSS-like class string into layout and style properties
|
||||
*/
|
||||
private parseClassNames(): void {
|
||||
const className = this.props.class as string | undefined;
|
||||
const className = this.props.class;
|
||||
if (className === undefined) return;
|
||||
|
||||
const classes = className.split(" ").filter((c) => c.length > 0);
|
||||
|
||||
@@ -7,6 +7,8 @@ import { calculateLayout } from "./layout";
|
||||
import { render as renderTree, clearScreen } from "./renderer";
|
||||
import { CCLog, HOUR } from "../ccLog";
|
||||
import { setLogger } from "./context";
|
||||
import { InputProps } from "./components";
|
||||
import { Setter } from "./reactivity";
|
||||
|
||||
/**
|
||||
* Main application class
|
||||
@@ -145,7 +147,7 @@ export class Application {
|
||||
if (
|
||||
this.focusedNode !== undefined &&
|
||||
this.focusedNode.type === "input" &&
|
||||
this.focusedNode.props.type !== "checkbox"
|
||||
(this.focusedNode.props as InputProps).type !== "checkbox"
|
||||
) {
|
||||
this.needsRender = true;
|
||||
}
|
||||
@@ -213,11 +215,13 @@ export class Application {
|
||||
this.needsRender = true;
|
||||
}
|
||||
} else if (this.focusedNode.type === "input") {
|
||||
const type = this.focusedNode.props.type as string | undefined;
|
||||
const type = (this.focusedNode.props as InputProps).type as
|
||||
| string
|
||||
| undefined;
|
||||
if (type === "checkbox") {
|
||||
// Toggle checkbox
|
||||
const onChangeProp = this.focusedNode.props.onChange;
|
||||
const checkedProp = this.focusedNode.props.checked;
|
||||
const onChangeProp = (this.focusedNode.props as InputProps).onChange;
|
||||
const checkedProp = (this.focusedNode.props as InputProps).checked;
|
||||
|
||||
if (
|
||||
typeof onChangeProp === "function" &&
|
||||
@@ -234,7 +238,9 @@ export class Application {
|
||||
this.focusedNode.type === "input"
|
||||
) {
|
||||
// Handle text input key events
|
||||
const type = this.focusedNode.props.type as string | undefined;
|
||||
const type = (this.focusedNode.props as InputProps).type as
|
||||
| string
|
||||
| undefined;
|
||||
if (type !== "checkbox") {
|
||||
this.handleTextInputKey(key);
|
||||
}
|
||||
@@ -247,8 +253,8 @@ export class Application {
|
||||
private handleTextInputKey(key: number): void {
|
||||
if (this.focusedNode === undefined) return;
|
||||
|
||||
const valueProp = this.focusedNode.props.value;
|
||||
const onInputProp = this.focusedNode.props.onInput;
|
||||
const valueProp = (this.focusedNode.props as InputProps).value;
|
||||
const onInputProp = (this.focusedNode.props as InputProps).onInput;
|
||||
|
||||
if (typeof valueProp !== "function" || typeof onInputProp !== "function") {
|
||||
return;
|
||||
@@ -292,11 +298,11 @@ export class Application {
|
||||
*/
|
||||
private handleCharEvent(char: string): void {
|
||||
if (this.focusedNode !== undefined && this.focusedNode.type === "input") {
|
||||
const type = this.focusedNode.props.type as string | undefined;
|
||||
const type = (this.focusedNode.props as InputProps).type;
|
||||
if (type !== "checkbox") {
|
||||
// Insert character at cursor position
|
||||
const onInputProp = this.focusedNode.props.onInput;
|
||||
const valueProp = this.focusedNode.props.value;
|
||||
const onInputProp = (this.focusedNode.props as InputProps).onInput;
|
||||
const valueProp = (this.focusedNode.props as InputProps).value;
|
||||
|
||||
if (
|
||||
typeof onInputProp === "function" &&
|
||||
@@ -331,11 +337,26 @@ export class Application {
|
||||
string.format("handleMouseClick: Found node of type %s.", clicked.type),
|
||||
);
|
||||
// Set focus
|
||||
if (
|
||||
this.focusedNode !== undefined &&
|
||||
typeof this.focusedNode.props.onFocusChanged === "function"
|
||||
) {
|
||||
const onFocusChanged = this.focusedNode.props
|
||||
.onFocusChanged as Setter<boolean>;
|
||||
onFocusChanged(false);
|
||||
}
|
||||
this.focusedNode = clicked;
|
||||
if (typeof clicked.props.onFocusChanged === "function") {
|
||||
const onFocusChanged = clicked.props.onFocusChanged as Setter<boolean>;
|
||||
onFocusChanged(true);
|
||||
}
|
||||
|
||||
// Initialize cursor position for text inputs on focus
|
||||
if (clicked.type === "input" && clicked.props.type !== "checkbox") {
|
||||
const valueProp = clicked.props.value;
|
||||
if (
|
||||
clicked.type === "input" &&
|
||||
(clicked.props as InputProps).type !== "checkbox"
|
||||
) {
|
||||
const valueProp = (clicked.props as InputProps).value;
|
||||
if (typeof valueProp === "function") {
|
||||
const currentValue = (valueProp as () => string)();
|
||||
clicked.cursorPos = currentValue.length;
|
||||
@@ -354,10 +375,10 @@ export class Application {
|
||||
this.needsRender = true;
|
||||
}
|
||||
} else if (clicked.type === "input") {
|
||||
const type = clicked.props.type as string | undefined;
|
||||
const type = (clicked.props as InputProps).type as string | undefined;
|
||||
if (type === "checkbox") {
|
||||
const onChangeProp = clicked.props.onChange;
|
||||
const checkedProp = clicked.props.checked;
|
||||
const onChangeProp = (clicked.props as InputProps).onChange;
|
||||
const checkedProp = (clicked.props as InputProps).checked;
|
||||
|
||||
if (
|
||||
typeof onChangeProp === "function" &&
|
||||
@@ -424,6 +445,14 @@ export class Application {
|
||||
|
||||
const interactive = this.collectInteractive(this.root);
|
||||
|
||||
if (
|
||||
this.focusedNode !== undefined &&
|
||||
typeof this.focusedNode.props.onFocusChanged === "function"
|
||||
) {
|
||||
const onFocusChanged = this.focusedNode.props
|
||||
.onFocusChanged as Setter<boolean>;
|
||||
onFocusChanged(false);
|
||||
}
|
||||
if (interactive.length === 0) {
|
||||
this.focusedNode = undefined;
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { concatSentence } from "../common";
|
||||
/**
|
||||
* Props for div component
|
||||
*/
|
||||
export type DivProps = BaseProps & Record<string, unknown>;
|
||||
export type DivProps = BaseProps;
|
||||
|
||||
/**
|
||||
* Props for label component
|
||||
@@ -20,7 +20,7 @@ export type DivProps = BaseProps & Record<string, unknown>;
|
||||
export type LabelProps = BaseProps & {
|
||||
/** Whether to automatically wrap long text. Defaults to false. */
|
||||
wordWrap?: boolean;
|
||||
} & Record<string, unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for button component
|
||||
@@ -28,7 +28,7 @@ export type LabelProps = BaseProps & {
|
||||
export type ButtonProps = BaseProps & {
|
||||
/** Click handler */
|
||||
onClick?: () => void;
|
||||
} & Record<string, unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for input component
|
||||
@@ -46,7 +46,7 @@ export type InputProps = BaseProps & {
|
||||
onChange?: Setter<boolean> | ((checked: boolean) => void);
|
||||
/** Placeholder text */
|
||||
placeholder?: string;
|
||||
} & Record<string, unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for form component
|
||||
@@ -54,7 +54,7 @@ export type InputProps = BaseProps & {
|
||||
export type FormProps = BaseProps & {
|
||||
/** Submit handler */
|
||||
onSubmit?: () => void;
|
||||
} & Record<string, unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic container component for layout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Calculates positions and sizes for UI elements based on flexbox rules
|
||||
*/
|
||||
|
||||
import { InputProps } from "./components";
|
||||
import { UIObject } from "./UIObject";
|
||||
|
||||
/**
|
||||
@@ -109,7 +110,7 @@ function measureNode(
|
||||
}
|
||||
|
||||
case "input": {
|
||||
const type = node.props.type as string | undefined;
|
||||
const type = (node.props as InputProps).type as string | undefined;
|
||||
if (type === "checkbox") {
|
||||
const naturalWidth = 3; // [X] or [ ]
|
||||
const naturalHeight = 1;
|
||||
@@ -119,7 +120,7 @@ function measureNode(
|
||||
};
|
||||
}
|
||||
// Text input - use a default width or from props
|
||||
const defaultWidth = (node.props.width as number | undefined) ?? 20;
|
||||
const defaultWidth = node.props.width ?? 20;
|
||||
const naturalHeight = 1;
|
||||
return {
|
||||
width: measuredWidth ?? defaultWidth,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { UIObject } from "./UIObject";
|
||||
import { Accessor } from "./reactivity";
|
||||
import { InputProps } from "./components";
|
||||
import { isScrollContainer } from "./scrollContainer";
|
||||
|
||||
/**
|
||||
@@ -189,14 +189,14 @@ function drawNode(
|
||||
}
|
||||
|
||||
case "input": {
|
||||
const type = node.props.type as string | undefined;
|
||||
const type = (node.props as InputProps).type as string | undefined;
|
||||
|
||||
if (type === "checkbox") {
|
||||
// Draw checkbox
|
||||
let isChecked = false;
|
||||
const checkedProp = node.props.checked;
|
||||
const checkedProp = (node.props as InputProps).checked;
|
||||
if (typeof checkedProp === "function") {
|
||||
isChecked = (checkedProp as Accessor<boolean>)();
|
||||
isChecked = checkedProp();
|
||||
}
|
||||
|
||||
if (focused) {
|
||||
@@ -212,12 +212,11 @@ function drawNode(
|
||||
} else {
|
||||
// Draw text input
|
||||
let displayText = "";
|
||||
const valueProp = node.props.value;
|
||||
const valueProp = (node.props as InputProps).value;
|
||||
if (typeof valueProp === "function") {
|
||||
displayText = (valueProp as Accessor<string>)();
|
||||
displayText = valueProp();
|
||||
}
|
||||
|
||||
const placeholder = node.props.placeholder as string | undefined;
|
||||
const placeholder = (node.props as InputProps).placeholder;
|
||||
const cursorPos = node.cursorPos ?? 0;
|
||||
let currentTextColor = textColor;
|
||||
let showPlaceholder = false;
|
||||
|
||||
@@ -31,7 +31,10 @@ const Counter = () => {
|
||||
div(
|
||||
{ class: "flex flex-row" },
|
||||
button({ onClick: () => setCount(count() - 1), class: "text-red" }, "-"),
|
||||
button({ onClick: () => setCount(count() + 1), class: "text-green" }, "+"),
|
||||
button(
|
||||
{ onClick: () => setCount(count() + 1), class: "text-green" },
|
||||
"+",
|
||||
),
|
||||
),
|
||||
);
|
||||
};
|
||||
@@ -81,10 +84,10 @@ const TodosApp = () => {
|
||||
},
|
||||
}),
|
||||
label(
|
||||
{
|
||||
class: todo.completed ? "ml-1 text-gray" : "ml-1 text-white"
|
||||
},
|
||||
() => todo.title
|
||||
{
|
||||
class: todo.completed ? "ml-1 text-gray" : "ml-1 text-white",
|
||||
},
|
||||
() => todo.title,
|
||||
),
|
||||
button(
|
||||
{
|
||||
@@ -308,7 +311,7 @@ const App = () => {
|
||||
{
|
||||
when: () => tabIndex() === 0,
|
||||
fallback: Show(
|
||||
{
|
||||
{
|
||||
when: () => tabIndex() === 1,
|
||||
fallback: Show(
|
||||
{
|
||||
@@ -318,13 +321,13 @@ const App = () => {
|
||||
when: () => tabIndex() === 3,
|
||||
fallback: MultiScrollExample(),
|
||||
},
|
||||
StaticScrollExample()
|
||||
)
|
||||
StaticScrollExample(),
|
||||
),
|
||||
},
|
||||
SimpleScrollExample()
|
||||
)
|
||||
},
|
||||
TodosApp()
|
||||
SimpleScrollExample(),
|
||||
),
|
||||
},
|
||||
TodosApp(),
|
||||
),
|
||||
},
|
||||
Counter(),
|
||||
@@ -347,4 +350,4 @@ try {
|
||||
print("Error running application:");
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user