Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32teeth/feature/scrollable placeholder #129

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions example/dev.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
import open from 'open';
await open('./dist/index.html');
const openFile = async () => {
try {
// Use dynamic import to load the ES module
const open = (await import('open')).default;
await open('./dist/index.html');
} catch (err) {
console.error('Error opening file:', err);
}
};

openFile();
15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@
"clean:dist": "find . -name 'dist' -type d -prune -exec rm -rf '{}' +",
"clean:node": "find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +",
"build": "webpack --config webpack.config.js --mode production",
"packdemo": "cd ./example && npm run pack",
"packdemo": "npm run --prefix ./example pack",
"watch": "webpack --config webpack.config.js --mode development --watch",
"watch:example": "cd ./example && npm run watch",
"start:example": "cd ./example && npm install && npm run build && npm run dev",
"watch:example": "npm run --prefix ./example watch",
"start:example": "npm install --prefix ./example && npm run build --prefix ./example",
"watch:web": "run-p watch watch:example serve:example",
"serve:example": "live-server --port=9000 example/dist",
"dev": "npm run clean && npm install && npm run build && npm run start:example",
"lint-fix": "npx eslint \"./**\" --fix",
"lint": "npx eslint \"./**\"",
"dev:watch": "npm run dev && npm run watch:web",
"lint-fix": "npx eslint './**' --fix",
"lint": "npx eslint './**'",
"format:check": "npx prettier --check .",
"format:write": "npx prettier --write .",
"tests:unit": "jest",
"tests:e2e": "cd ./ui-tests && npm install && npm run prepare && npm run e2e",
"tests:e2e": "npm install --prefix ./ui-tests && npm run --prefix ./ui-tests prepare && npm run --prefix ./ui-tests e2e",
"api-docs": "npx typedoc src/main.ts --out ./api-docs",
"api-doc-deploy": "npx typedoc src/main.ts --out ./example/dist/api-doc",
"postinstall": "node postinstall.js",
Expand Down
23 changes: 22 additions & 1 deletion src/components/chat-item/prompt-input/prompt-text-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class PromptTextInput {
maxlength: MAX_USER_INPUT().toString(),
type: 'text',
placeholder: MynahUITabsStore.getInstance().getTabDataStore(this.props.tabId).getValue('promptInputPlaceholder'),
style: this.getPlaceholderWidth(),
value: '',
...(Config.getInstance().config.autoFocus ? { autofocus: 'autofocus' } : {})
},
Expand Down Expand Up @@ -87,7 +88,6 @@ export class PromptTextInput {
}
},
focus: () => {
this.render.addClass('input-has-focus');
if (typeof this.props.onFocus !== 'undefined') {
this.props.onFocus();
}
Expand Down Expand Up @@ -142,6 +142,27 @@ export class PromptTextInput {
this.clear();
}

private readonly getPlaceholderWidth = (): string => {
const span = document.createElement('span');
span.style.visibility = 'hidden';
span.setAttribute('class', 'mynah-chat-prompt-input-scroll-measure');
document.body.appendChild(span);

const inputStyles = window.getComputedStyle(span);
span.style.font = inputStyles.getPropertyValue('font');
span.style.fontSize = inputStyles.getPropertyValue('font-size');
span.style.fontFamily = inputStyles.getPropertyValue('font-family');
span.style.fontWeight = inputStyles.getPropertyValue('font-weight');
span.style.letterSpacing = inputStyles.getPropertyValue('letter-spacing');
span.style.whiteSpace = 'nowrap';
span.textContent = MynahUITabsStore.getInstance().getTabDataStore(this.props.tabId).getValue('promptInputPlaceholder');

const textWidth = span.offsetWidth;
document.body.removeChild(span);

return `--mynah-placeholder-width: ${textWidth * 1.125}px`; //
};

private readonly updatePromptTextInputSizer = (placeHolder?: {
index?: number;
text?: string;
Expand Down
31 changes: 25 additions & 6 deletions src/styles/components/chat/_chat-prompt-wrapper.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,19 @@
width: 100%;
position: relative;
align-self: center;
overflow: hidden;
overflow-x: scroll;

> .mynah-chat-prompt-input {
&.no-text {
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none;
scrollbar-width: none;
}

> .mynah-chat-prompt-input,
> .mynah-chat-prompt-input-scroll-measure {
--mynah-placeholder-width: 100%;
font-family: var(--mynah-font-family);
border: none;
resize: none;
Expand All @@ -74,6 +84,7 @@
overflow-wrap: break-word;

&:placeholder-shown {
width: var(--mynah-placeholder-width) !important;
text-overflow: ellipsis;
}

Expand Down Expand Up @@ -106,6 +117,7 @@
color: rgba(0, 0, 0, 0);
position: relative;
z-index: 150;

> span.context {
position: relative;
color: var(--mynah-color-button-reverse);
Expand Down Expand Up @@ -268,6 +280,17 @@
border: var(--mynah-border-width) solid var(--mynah-color-button);
}

> .mynah-chat-prompt-chars-indicator {
width: 100%;
font-size: var(--mynah-font-size-xsmall);
padding-top: var(--mynah-sizing-2);
opacity: 0.5;
display: flex;
align-items: center;
justify-content: flex-end;
font-style: italic;
}

& + .mynah-chat-prompt-input-info {
padding-top: 0;
margin-top: calc(-1 * var(--mynah-sizing-2));
Expand All @@ -292,11 +315,9 @@
> .mynah-chat-prompt-input-info {
display: flex;
flex-flow: row nowrap;
justify-content: center;
box-sizing: border-box;
overflow: hidden;
padding: var(--mynah-sizing-4);
text-align: center;

&,
& * {
Expand All @@ -313,7 +334,5 @@
margin-block-end: 0;
margin-top: 0;
margin-bottom: 0;
max-width: 100%;
box-sizing: border-box;
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ui-tests/__test__/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Open MynahUI', () => {
allowSizeMismatch: true,
failureThresholdType: 'percent',
storeReceivedOnFailure: true,
customSnapshotsDir: `./__test__/__image_snapshots__/${browserName}`
customSnapshotsDir: `./__test__/__image_snapshots__/${String(browserName)}`
});

expect.extend({ toMatchImageSnapshot });
Expand Down
4 changes: 2 additions & 2 deletions ui-tests/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const createMynahUI = (): MynahUI => {
onChatPrompt: (tabId: string, prompt: ChatPrompt) => {
if (tabId === 'tab-1') {
mynahUI.updateStore(tabId, {
tabCloseConfirmationMessage: `Working on "${prompt.prompt != null ? (prompt.prompt) : ''}"`,
tabCloseConfirmationMessage: `Working on "${prompt.prompt != null ? String(prompt.prompt) : ''}"`,
});
}
onChatPrompt(tabId, prompt);
Expand Down Expand Up @@ -142,7 +142,7 @@ export const createMynahUI = (): MynahUI => {
mynahUI.addChatItem(tabId, {
type: ChatItemType.PROMPT,
messageId: generateUID(),
body: `**${(prompt.command != null ? prompt.command : '').replace('/', '')}**\n${(prompt.escapedPrompt != null ? prompt.escapedPrompt : '')}`,
body: `**${String(prompt.command != null ? prompt.command.replace('/', '') : '')}**\n${String(prompt.escapedPrompt != null ? prompt.escapedPrompt : '')}`,
});
getGenerativeAIAnswer(tabId);
break;
Expand Down
Loading