add word wrap for label

This commit is contained in:
2025-10-14 12:41:32 +08:00
parent 0ccafa2e2e
commit 7f2a51c5aa
5 changed files with 43 additions and 23 deletions

View File

@@ -538,9 +538,9 @@ const AccessControlTUI = () => {
return Show( return Show(
{ when: () => errorState().show }, { when: () => errorState().show },
div( div(
{ class: "flex flex-col bg-red " }, { class: "flex flex-col" },
label( label(
{ class: "w-25 text-white", wordWrap: true }, { class: "w-50 text-white bg-red", wordWrap: true },
() => errorState().message, () => errorState().message,
), ),
button( button(

View File

@@ -4,16 +4,10 @@
*/ */
import { UIObject, BaseProps, createTextNode } from "./UIObject"; import { UIObject, BaseProps, createTextNode } from "./UIObject";
import { import { Accessor, createMemo, Setter, Signal } from "./reactivity";
Accessor,
createEffect,
createMemo,
createSignal,
Setter,
Signal,
} from "./reactivity";
import { For } from "./controlFlow"; import { For } from "./controlFlow";
import { logger } from "./context"; import { context } from "./context";
import { concatSentence } from "../common";
/** /**
* Props for div component * Props for div component
@@ -114,6 +108,7 @@ export function div(
* @returns An array of words and whitespace. * @returns An array of words and whitespace.
*/ */
function splitByWhitespace(text: string): string[] { function splitByWhitespace(text: string): string[] {
if (!text) return [];
const parts: string[] = []; const parts: string[] = [];
let currentWord = ""; let currentWord = "";
let currentWhitespace = ""; let currentWhitespace = "";
@@ -148,13 +143,16 @@ export function label(
props: LabelProps, props: LabelProps,
text: string | Accessor<string>, text: string | Accessor<string>,
): UIObject { ): UIObject {
context.logger?.debug(`label : ${textutils.serialiseJSON(props)}`);
context.logger?.debug(
`label text: ${typeof text == "string" ? text : text()}`,
);
if (props.wordWrap === true) { if (props.wordWrap === true) {
logger?.debug(`label : ${textutils.serialiseJSON(props)}`);
const p = { ...props }; const p = { ...props };
delete p.wordWrap; delete p.wordWrap;
const containerProps: DivProps = { const containerProps: DivProps = {
...p, ...p,
class: `${p.class ?? ""} flex flex-row flex-wrap`, class: `${p.class ?? ""} flex flex-col`,
}; };
if (typeof text === "string") { if (typeof text === "string") {
@@ -166,16 +164,18 @@ export function label(
return node; return node;
} else { } else {
// Handle reactive strings (Accessor<string>) // Handle reactive strings (Accessor<string>)
const words = createMemo(() => splitByWhitespace(text())); const sentences = createMemo(() => {
const words = splitByWhitespace(text());
const ret = concatSentence(words, 40);
context.logger?.debug(`label words changed : [ ${ret.join(",")} ]`);
return ret;
});
const forNode = For( const forNode = For({ class: `flex flex-col`, each: sentences }, (word) =>
{ class: `${p.class ?? ""} flex flex-row flex-wrap`, each: words }, label({ class: p.class }, word),
(word) => createTextNode(word),
); );
const node = new UIObject("div", containerProps, [forNode]); return forNode;
forNode.parent = node;
return node;
} }
} }

View File

@@ -7,15 +7,17 @@
import type { CCLog } from "../ccLog"; import type { CCLog } from "../ccLog";
/** /**
* The global logger instance for the TUI application. * The global context object for the TUI application.
* This will be set by the Application instance on creation. * This will be set by the Application instance on creation.
*/ */
export let logger: CCLog | undefined; export const context: { logger: CCLog | undefined } = {
logger: undefined,
};
/** /**
* Sets the global logger instance. * Sets the global logger instance.
* @param l The logger instance. * @param l The logger instance.
*/ */
export function setLogger(l: CCLog): void { export function setLogger(l: CCLog): void {
logger = l; context.logger = l;
} }

0
src/lib/ccTUI/utils.ts Normal file
View File

View File

@@ -4,3 +4,21 @@ export function parseBoolean(obj: string): boolean | undefined {
else if (str === "false") return false; else if (str === "false") return false;
else return undefined; else return undefined;
} }
export function concatSentence(words: string[], length: number): string[] {
let i = 0,
j = 1;
const ret: string[] = [];
while (i < words.length) {
let sentence = words[i];
while (j < words.length && sentence.length + words[j].length < length) {
sentence += words[j];
j++;
}
ret.push(sentence);
i = j;
j++;
}
return ret;
}