Skip to content

Commit

Permalink
feat: focus state
Browse files Browse the repository at this point in the history
  • Loading branch information
dineug committed Dec 1, 2023
1 parent 640f132 commit a96c8a9
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 28 deletions.
10 changes: 10 additions & 0 deletions packages/erd-editor/src/components/erd-editor/ErdEditor.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ export const root = css`
${container};
background-color: var(--canvas-boundary-background);
outline: none;
&.none-focus {
div[data-focus-border] {
border-color: var(--placeholder) !important;
}
div[data-focus-border-bottom],
input[data-focus-border-bottom] {
border-bottom-color: var(--placeholder) !important;
}
}
`;

export const main = css`
Expand Down
32 changes: 26 additions & 6 deletions packages/erd-editor/src/components/erd-editor/ErdEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
defineCustomElement,
FC,
html,
observable,
onMounted,
ref,
useProvider,
Expand Down Expand Up @@ -86,24 +87,36 @@ const ErdEditor: FC<ErdEditorProps, ErdEditorElement> = (props, ctx) => {
const { store, keydown$ } = appContextValue;
const { addUnsubscribe } = useUnmounted();

const handleKeydown = (event: KeyboardEvent) => {
keydown$.next(event);
};
const state = observable({
isFocus: false,
});

const handleFocus = () => {
const checkAndFocus = () => {
window.setTimeout(() => {
if (document.activeElement !== ctx) {
ctx.focus();
}
}, 1);
};

const handleKeydown = (event: KeyboardEvent) => {
keydown$.next(event);
};

const handleFocus = () => {
state.isFocus = true;
};

const handleFocusout = (event: FocusEvent) => {
state.isFocus = false;
};

onMounted(() => {
ctx.focus();
addUnsubscribe(
fromEvent(ctx, focusEvent.type)
.pipe(throttleTime(50))
.subscribe(handleFocus),
.subscribe(checkAndFocus),
fromEvent(ctx, forceFocusEvent.type).subscribe(ctx.focus)
);
});
Expand Down Expand Up @@ -134,9 +147,16 @@ const ErdEditor: FC<ErdEditorProps, ErdEditorElement> = (props, ctx) => {
<${Theme} .theme=${theme} />
<div
${ref(root)}
class=${['root', styles.root, { dark: isDarkMode() }]}
class=${[
'root',
styles.root,
{ dark: isDarkMode(), 'none-focus': !state.isFocus },
]}
tabindex="-1"
@keydown=${handleKeydown}
@focus=${handleFocus}
@focusin=${handleFocus}
@focusout=${handleFocusout}
>
<${Toolbar} />
<div class=${styles.main}>
Expand Down
1 change: 1 addition & 0 deletions packages/erd-editor/src/components/erd/canvas/memo/Memo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const Memo: FC<MemoProps> = (props, ctx) => {
height: `${height}px`,
}}
?data-selected=${selected}
?data-focus-border=${selected}
@mousedown=${handleMoveStart}
@touchstart=${handleMoveStart}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const Table: FC<TableProps> = (props, ctx) => {
height: `${height}px`,
}}
?data-selected=${selected}
?data-focus-border=${selected}
data-id=${table.id}
@mousedown=${onMoveStart}
@touchstart=${onMoveStart}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,30 @@ export const hint = css`
border: 1px solid var(--table-border);
white-space: nowrap;
${typography.paragraph};
`;

& > div {
display: flex;
align-items: center;
padding: 0 4px;
height: 20px;
cursor: pointer;
}
export const hintItem = css`
display: flex;
align-items: center;
padding: 0 4px;
height: 20px;
cursor: pointer;
& > div:hover {
&:hover {
background-color: var(--column-hover);
}
& > div.selected {
&.selected {
background-color: var(--column-select);
.kbd {
visibility: visible;
}
}
& > .kbd {
margin-left: auto;
padding-left: 6px;
visibility: hidden;
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { isEmpty } from 'lodash-es';
import { useAppContext } from '@/components/appContext';
import EditInput from '@/components/primitives/edit-input/EditInput';
import HighlightedText from '@/components/primitives/highlighted-text/HighlightedText';
import Kbd from '@/components/primitives/kbd/Kbd';
import { DatabaseHintMap, DataTypeHint } from '@/constants/sql/dataType';
import { changeColumnDataTypeAction$ } from '@/engine/modules/tableColumn/generator.actions';
import { useUnmounted } from '@/hooks/useUnmounted';
Expand Down Expand Up @@ -212,13 +213,17 @@ const ColumnDataType: FC<ColumnDataTypeProps> = (props, ctx) => {
(hint, index) =>
html`
<div
class=${{ selected: index === state.index }}
class=${[
styles.hintItem,
{ selected: index === state.index },
]}
@click=${() => handleSelectHint(index)}
>
<${HighlightedText}
searchWords=${[props.value]}
textToHighlight=${hint.name}
/>
<${Kbd} mini=${true} shortcut="Tab" />
</div>
`
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ColumnNotNull: FC<ColumnNotNullProps> = (props, ctx) => {
'min-width': `${COLUMN_NOT_NULL_WIDTH}px`,
}}
title="Not Null"
?data-focus-border-bottom=${props.focus}
>
${bHas(props.options, ColumnOption.notNull) ? 'N-N' : 'NULL'}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const ColumnOption: FC<ColumnOptionProps> = (props, ctx) => {
'min-width': `${props.width}px`,
}}
title=${props.title}
?data-focus-border-bottom=${props.focus}
>
${props.text}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const Viewport: FC<ViewportProps> = (props, ctx) => {
{ selected: state.selected || props.selected },
]}
style=${styleMap()}
data-focus-border
@mousedown=${onScrollStart}
@touchstart=${onScrollStart}
></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ const EditInput: FC<EditInputProps> = (props, ctx) => {
lastCursorFocus($input);
});

return () =>
props.edit
return () => {
const isFocus = props.focus || props.edit;

return props.edit
? html`
<input
${ref(input)}
Expand All @@ -92,6 +94,7 @@ const EditInput: FC<EditInputProps> = (props, ctx) => {
})}
type="text"
spellcheck="false"
?data-focus-border-bottom=${isFocus}
.value=${props.value ?? ''}
@input=${props.onInput}
@blur=${handleBlur}
Expand All @@ -113,10 +116,12 @@ const EditInput: FC<EditInputProps> = (props, ctx) => {
'min-width': `${props.width}px`,
}}
...${restAttrs({ title: props.title })}
?data-focus-border-bottom=${isFocus}
>
${props.value.trim() ? props.value : props.placeholder}
</div>
`;
};
};

export default EditInput;
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const meta = {
shortcut: {
control: 'text',
},
mini: {
control: 'boolean',
},
},
} satisfies Meta<KbdProps>;

Expand All @@ -23,5 +26,6 @@ type Story = StoryObj<KbdProps>;
export const Normal: Story = {
args: {
shortcut: '$mod+Alt+KeyA',
mini: false,
},
};
17 changes: 17 additions & 0 deletions packages/erd-editor/src/components/primitives/kbd/Kbd.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,20 @@ export const kbd = css`
margin-right: 0;
}
`;

export const mini = css`
padding-left: 0.25em;
padding-right: 0.25em;
padding-bottom: 0.05em;
margin-right: 2px;
font-size: 10px;
white-space: nowrap;
color: var(--placeholder);
border: 1px solid var(--placeholder);
border-radius: 3px;
&:last-child {
margin-right: 0;
}
`;
8 changes: 6 additions & 2 deletions packages/erd-editor/src/components/primitives/kbd/Kbd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as styles from './Kbd.styles';

export type KbdProps = {
shortcut?: string;
mini?: boolean;
};

const Kbd: FC<KbdProps> = (props, ctx) => {
Expand All @@ -14,9 +15,12 @@ const Kbd: FC<KbdProps> = (props, ctx) => {
const shortcuts = keys.map(([mods, key]) => [...mods, key].join(' + '));

return html`
<div class=${styles.root}>
<div class=${['kbd', styles.root]}>
${shortcuts.map(
shortcut => html`<div class=${styles.kbd}>${shortcut}</div>`
shortcut =>
html`<div class=${props.mini ? styles.mini : styles.kbd}>
${shortcut}
</div>`
)}
</div>
`;
Expand Down
1 change: 1 addition & 0 deletions packages/erd-editor/src/engine/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const ChangeActionTypes: ReadonlyArray<ActionType> = [
// table
'table.add',
'table.move',
'table.moveTo',
'table.remove',
'table.changeName',
'table.changeComment',
Expand Down
24 changes: 16 additions & 8 deletions packages/erd-editor/src/utils/file/importFile.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { html } from '@dineug/r-html';
import { isString } from '@dineug/shared';

import { AppContext } from '@/components/appContext';
import Toast from '@/components/primitives/toast/Toast';
import { loadJsonAction$ } from '@/engine/modules/editor/generator.actions';

import { openToastAction } from '../emitter';

type ImportOptions = {
type: 'json' | 'sql';
accept: string;
Expand All @@ -19,7 +23,7 @@ export function setImportFileCallback(callback: ImportFileCallback | null) {
performImportFileExtra = callback;
}

export function importJSON({ store }: AppContext) {
export function importJSON({ store, emitter }: AppContext) {
if (performImportFileExtra) {
performImportFileExtra({ accept: '.json', type: 'json' });
return;
Expand All @@ -33,9 +37,11 @@ export function importJSON({ store }: AppContext) {
if (!file) return;

if (!JSON_EXTENSION.test(file.name)) {
// eventBus.emit(Bus.ToastBar.add, {
// bodyTpl: html`Just import the json file`,
// });
emitter.emit(
openToastAction({
message: html`<${Toast} description="Just import the json file" />`,
})
);
return;
}

Expand All @@ -53,7 +59,7 @@ export function importJSON({ store }: AppContext) {
input.click();
}

export function importSchemaSQL({ store }: AppContext) {
export function importSchemaSQL({ store, emitter }: AppContext) {
if (performImportFileExtra) {
performImportFileExtra({ accept: '.sql', type: 'sql' });
return;
Expand All @@ -67,9 +73,11 @@ export function importSchemaSQL({ store }: AppContext) {
if (!file) return;

if (!SQL_EXTENSION.test(file.name)) {
// eventBus.emit(Bus.ToastBar.add, {
// bodyTpl: html`Just import the sql file`,
// });
emitter.emit(
openToastAction({
message: html`<${Toast} description="Just import the sql file" />`,
})
);
return;
}

Expand Down

0 comments on commit a96c8a9

Please sign in to comment.