-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* ✨ feat: toobox custom * 🔨 refactor: svg path 객체 파일 분리 * 🐛 fix: merge 오류 수정 * 🐛 fix: css layer 배치 수정 * ✨ feat: 탭 버튼 추가 * 🔨 refactor: type 없어서 build 안되는 오류 해결 * 💄 design: 워크스페이스 반응형으로 변경 * 🐛 fix: border box 잘못 넣은 것 빼기 * 🐛 fix: html 탭과 첫 번째 카테고리 선택되도록 수정 * 🐛 fix: 탭 한 번 선택되면 다시 눌렀을 때 안 꺼지게 * ✨ feat: 탭 선택 시 선택 해제되지 않도록 수정 * 🔨 refactor: tabbed Toolbox 커스텀 클래스로 분리 * 🔨 refactor: 불필요한 코드 정리 * ✨ feat: flyout 위치 고정 * ✨ feat: div로 변경하는 클래스 생성 * 🐛 fix: null로수정 * 🐛 fix: build 되도록 코드 수정 * 🐛 fix: contentarea로 수정 * ✨ feat: div 안에 svg 넣기 * 🐛 fix: flyout 사이즈 조절 * 🔨 refactor: 인터페이스 이름 변경 * ✨ feat: custom flyout register에 등록해서 가져다 사용하기 * 🐛 fix: 뒤에 요소 여러 개 렌더링 되는 거 해결 * ✨ feat: CSS스타일툴박스에 요소 추가 (input, button) * 🎨 style: 클래스 내 멤버 변수, 메서드 생성 및 TODO 표시 * 💄 design: 스타일 toolbox의 text, input, button 디자인 * ✨ feat: 스타일 추가시 input 값 초기화 + alert->toast 변경 * 🔨 refactor: 가독성 개선 * 🐛 fix: flyout 스크롤바 생기는 에러 수정 * 🙀 chore: 오타 수정 * 🙀 chore: 테스트 코드 삭제 * ✨ feat: 블록 삭제 기능 추가 * 🎨 style: 로직 순서 변경(블록 생성) 및 타입 추가 * 🎨 style: 스타일 형식 변경 (인라인 -> 클래스에 지정) * 🔨 refactor: svg 경로 변경 + 코드 가독성 개선 * 🎨 style: 태그 변경(p>label) & DOM 요소명 통일 & 로직 순서 변경(전역상태 예외처리 후 불러오도록 수정) * 💄 design: 디자인 디테일 수정 (px->rem, 기존 설정 활용, placeholder와 입력값/button hover시 색상차이) * 🔨 refactor: css스타일블록 삭제 기능 개선 * 🐛 fix: 수정 전 코드 삭제 * 🐛 fix: conflict 재해결 * 🐛 fix: 타입 에러 재수정 * 🚚 rename: 명칭 수정 (스타일>클래스) * 🚚 rename: 툴박스 명칭 수정 (스타일>클래스) --------- Co-authored-by: Yujin <[email protected]> Co-authored-by: Yujin Lee <[email protected]> Co-authored-by: leeyeongjae <[email protected]> Co-authored-by: chichoc <[email protected]> Co-authored-by: chichoc <[email protected]>
- Loading branch information
1 parent
2ba08f0
commit 60da41a
Showing
11 changed files
with
196 additions
and
58 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1 @@ | ||
chore/* @boostcampwm-2024/Web31 | ||
hotfix/* @boostcampwm-2024/Web31 | ||
|
||
* @boostcampwm-2024/Web31 | ||
* @boostcampwm-2024/Web31 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as Blockly from 'blockly/core'; | ||
|
||
export default class FieldClickableImage extends Blockly.FieldImage { | ||
private clickHandler_: (() => void) | null; | ||
|
||
constructor(src: string, width: number, height: number, alt: string, clickHandler: () => void) { | ||
super(src, width, height, alt); | ||
this.clickHandler_ = clickHandler; | ||
} | ||
|
||
showEditor_() { | ||
if (this.clickHandler_) { | ||
this.clickHandler_(); | ||
} | ||
} | ||
|
||
onMouseDown_(e: MouseEvent) { | ||
e.stopPropagation(); | ||
e.preventDefault(); | ||
this.showEditor_(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,141 @@ | ||
import * as Blockly from 'blockly/core'; | ||
import toast from 'react-hot-toast'; | ||
import TabbedToolbox from './tabbedToolbox'; | ||
import FixedFlyout from './fixedFlyout'; | ||
import Dom from './dom'; | ||
import { cssStyleToolboxConfig } from '@/widgets'; | ||
//import { useClassBlockStore } from '@/shared/store'; | ||
//import toast from 'react-hot-toast'; | ||
import { useClassBlockStore } from '@/shared/store'; | ||
import FieldClickableImage from './fieldClickableImage'; | ||
import cssClassDeleteIcon from '@/shared/assets/css_class_delete_icon.svg'; | ||
import { Tblock } from '@/shared/types'; | ||
|
||
export default class StyleFlyout extends FixedFlyout { | ||
static registryName = 'StyleFlyout'; | ||
|
||
pElement: HTMLDivElement | null = null; | ||
inputElement: HTMLInputElement | null = null; | ||
buttonElement: HTMLButtonElement | null = null; | ||
|
||
// flyout 위치 오버라이딩 | ||
position(): void { | ||
super.position(); // FixedFlyout의 기본 배치 호출 | ||
const toolbox = this.targetWorkspace!.getToolbox(); | ||
|
||
if (!toolbox) { | ||
throw new Error('no toolbox'); | ||
} | ||
|
||
const metrics = (toolbox as TabbedToolbox).getContentAreaMetrics(); | ||
this.positionAt_(metrics.width - 10, metrics.height - 150, 10, 150); | ||
} | ||
|
||
init(targetWorkspace: Blockly.WorkspaceSvg): void { | ||
super.init(targetWorkspace); | ||
const toolbox = this.targetWorkspace.getToolbox() as TabbedToolbox; | ||
|
||
const styleTop = Dom.createElement<HTMLDivElement>('div', { | ||
const cssStyleToolboxDivElement = Dom.createElement<HTMLDivElement>('div', { | ||
class: 'contentCreatingBlock', | ||
}); | ||
|
||
const inputElement = Dom.createElement<HTMLInputElement>('input', { | ||
const labelElement = Dom.createElement<HTMLLabelElement>('label', { | ||
for: 'creatingBlockInput', | ||
class: 'creatingBlockLabel', | ||
}); | ||
labelElement.textContent = '클래스명'; | ||
|
||
this.inputElement = Dom.createElement<HTMLInputElement>('input', { | ||
type: 'text', | ||
placeholder: '스타일명을 정해주세요', | ||
class: 'flyout-input', | ||
placeholder: '클래스명을 정해주세요', | ||
class: 'creatingBlockInput', | ||
id: 'creatingBlockInput', | ||
}); | ||
inputElement.style.zIndex = '99999'; | ||
|
||
const buttonElement = Dom.createElement<HTMLButtonElement>('button', { | ||
class: 'flyout-button', | ||
class: 'creatingBlockButton', | ||
}); | ||
buttonElement.textContent = '+'; | ||
buttonElement.addEventListener('click', () => this.createStyleBlock()); | ||
// TODO: input 입력값 존재 && focus된 경우 Enter 클릭하면 CSS 클래스명 블록 생성 | ||
|
||
buttonElement.addEventListener('click', () => { | ||
const inputValue = inputElement.value.trim(); | ||
// const { addClassBlock } = useClassBlockStore.getState(); | ||
[labelElement, this.inputElement, buttonElement].forEach((element) => | ||
cssStyleToolboxDivElement.appendChild(element) | ||
); | ||
|
||
if (inputValue === null) { | ||
return; | ||
} | ||
toolbox.addElementToContentArea(cssStyleToolboxDivElement); | ||
// TODO: toolbox 중복 호출 논의 | ||
this.show(cssStyleToolboxConfig.contents); | ||
} | ||
|
||
if (inputValue?.trim() === '') { | ||
return alert('블록 이름을 입력해주세요.'); | ||
} | ||
createStyleBlock() { | ||
const inputValue = this.inputElement?.value; | ||
if (!inputValue) { | ||
return toast.error('클래스명을 입력해주세요.'); | ||
} | ||
|
||
if (!Blockly.Blocks[inputValue!]) { | ||
Blockly.Blocks[inputValue!] = { | ||
init: function () { | ||
this.appendDummyInput().appendField( | ||
new Blockly.FieldLabelSerializable(inputValue!), | ||
'CLASS' | ||
); // 입력된 이름 반영 | ||
this.setOutput(true); | ||
this.setColour('#02D085'); | ||
}, | ||
}; | ||
} | ||
const existingBlocks: Tblock[] = cssStyleToolboxConfig!.contents || []; | ||
const isBlockAlreadyAdded = existingBlocks.some((block) => block.type === inputValue); | ||
if (isBlockAlreadyAdded) { | ||
return toast.error(`"${inputValue}" 입력한 클래스명 블록은 이미 존재합니다.`); | ||
} | ||
|
||
// 기존 블록 유지 및 새 블록 추가 | ||
// const existingBlocks = cssStyleToolboxConfig!.contents || []; | ||
// const isBlockAlreadyAdded = existingBlocks.some((block) => block.type === inputValue); | ||
|
||
// if (isBlockAlreadyAdded) { | ||
// toast.error(`"${inputValue}" 스타일 블록은 이미 존재합니다.`); | ||
// return; | ||
// } | ||
|
||
// if (inputValue) { | ||
// cssStyleToolboxConfig!.contents = [...existingBlocks, { kind: 'block', type: inputValue }]; | ||
// addClassBlock(inputValue); | ||
// } | ||
// this.show(cssStyleToolboxConfig.contents); | ||
// toast.success(`새 스타일 블록 "${inputValue}"이(가) 추가되었습니다.`); | ||
}); | ||
if (!Blockly.Blocks[inputValue!]) { | ||
const flyoutInstance = this; | ||
Blockly.Blocks[inputValue!] = { | ||
init: function () { | ||
const input = this.appendDummyInput(); | ||
input.appendField(new Blockly.FieldLabelSerializable(inputValue!), 'CLASS'); | ||
|
||
// TODO: CSS 클래스명 블록 색상 변경 | ||
input.appendField( | ||
new FieldClickableImage( | ||
cssClassDeleteIcon, | ||
12, | ||
12, | ||
'삭제', | ||
flyoutInstance.deleteStyleBlock.bind(flyoutInstance, inputValue!) | ||
) | ||
); | ||
|
||
this.setOutput(true); | ||
this.setColour('#02D085'); | ||
// this.setColour('#F4F8FA'); | ||
}, | ||
}; | ||
} | ||
|
||
styleTop.appendChild(inputElement); | ||
styleTop.appendChild(buttonElement); | ||
// 기존 블록에 새 블록 추가 | ||
cssStyleToolboxConfig!.contents = [...existingBlocks, { kind: 'block', type: inputValue }]; | ||
const { addClassBlock } = useClassBlockStore.getState(); | ||
addClassBlock(inputValue); | ||
|
||
toolbox.addElementToContentArea(styleTop); | ||
this.show(cssStyleToolboxConfig.contents); | ||
toast.success(`입력한 클래스명 블록 "${inputValue}"이(가) 추가되었습니다.`); | ||
|
||
if (this.inputElement) { | ||
this.inputElement.value = ''; | ||
} | ||
} | ||
|
||
createStyleBlock() {} | ||
// TODO: 워크스페이스에 존재하는 CSS 클래스명 블록 삭제 논의 필요 | ||
deleteStyleBlock(blockType: string) { | ||
const blocks = this.workspace_.getAllBlocks(); | ||
|
||
// CSS 클래스명 블록 삭제 | ||
for (let i = 0; i < blocks.length; i++) { | ||
if (blocks[i].type === blockType) { | ||
blocks[i].dispose(false, true); | ||
break; | ||
} | ||
} | ||
|
||
cssStyleToolboxConfig.contents = cssStyleToolboxConfig.contents.filter( | ||
(block) => block.type !== blockType | ||
); | ||
|
||
const { removeClassBlock } = useClassBlockStore.getState(); | ||
removeClassBlock(blockType); | ||
|
||
this.show(cssStyleToolboxConfig.contents); | ||
toast.success(`"${blockType}" 클래스명 블록이 삭제되었습니다.`); | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type Tblock = { kind: string; type: string }; | ||
|
||
export type TtoolboxConfig = { | ||
kind: string; | ||
contents: Tblock[]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
apps/client/src/widgets/workspace/blockly/cssStyleToolboxConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
export const cssStyleToolboxConfig = { | ||
import { TtoolboxConfig } from '@/shared/types'; | ||
|
||
export const cssStyleToolboxConfig: TtoolboxConfig = { | ||
kind: 'categoryToolbox', | ||
contents: [], | ||
}; | ||
|
||
// type: addPreviousTypeName('css_style') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters