Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
a491182
chore: eslint-config package.json 으로 의존성 통일
namdaeun Mar 6, 2026
47bd2e0
feat: prettier-config package.json 추가
namdaeun Mar 6, 2026
d82607b
refactor: 워크스페이스 패키지 참조
namdaeun Mar 6, 2026
250711b
refactor: root prettier rule 추가
namdaeun Mar 6, 2026
c36537d
refactor: root eslint rule 정의
namdaeun Mar 6, 2026
b56de7d
chore: update turbo.json
namdaeun Mar 6, 2026
a4ac3a1
refactor: 공용 config로 변경
namdaeun Mar 6, 2026
e9a728e
chore: yarn install
namdaeun Mar 6, 2026
505bbc4
chore: lint fix script 추가
namdaeun Mar 6, 2026
166e1bd
fix: fix lint errors
namdaeun Mar 6, 2026
3748b55
chore: add prettier scripts
namdaeun Mar 6, 2026
ef2e36b
chore: disable react/jsx-key rule
namdaeun Mar 6, 2026
f23daaa
chore: yarn install
namdaeun Mar 6, 2026
7c93a78
chore: add eslint and prettier ignore files
namdaeun Mar 6, 2026
537f792
chore: add prettier scripts
namdaeun Mar 6, 2026
647fbad
chore: ignore path 옵션 추가
namdaeun Mar 6, 2026
fb9ad57
refactor: 공유 config rules 적용
namdaeun Mar 6, 2026
caf99f6
chore: root ignore file로 통일
namdaeun Mar 6, 2026
a80b6c8
chore: solve console warnings
namdaeun Mar 6, 2026
961464a
chore: stylelint script 추가
namdaeun Mar 7, 2026
c6f2234
chore: update gitignore
namdaeun Mar 7, 2026
cba980b
chore: update env
namdaeun Mar 7, 2026
94214a9
chore: dotfile 패턴 추가
namdaeun Mar 7, 2026
9c254cb
chore: trigger workflow
namdaeun Mar 7, 2026
c8fe521
chore: remove paths from pull request triggers
namdaeun Mar 7, 2026
b1be091
chore: prettier -> format으로 변경
namdaeun Mar 7, 2026
160aa04
feat: lint-staged 추가
namdaeun Mar 7, 2026
a7aa96e
chore: modify deprecated rule
namdaeun Mar 7, 2026
29c1fda
refactor: gitignore 루트로 통일
namdaeun Mar 7, 2026
48f8e3a
chore: 불필요한 코드 제거
namdaeun Mar 7, 2026
e41a8c9
chore: jsx-key rule 활성화
namdaeun Mar 7, 2026
4eb63ca
chore: 안 쓰이는 트리거 제거
namdaeun Mar 8, 2026
2fb2b4a
chore: 명령어 수정
namdaeun Mar 8, 2026
7cd8def
chore: add check script
namdaeun Mar 8, 2026
e43c761
chore: base no-unused-vars 옵션 꺼둠
namdaeun Mar 8, 2026
fae0485
chore: type import/export rule 추가
namdaeun Mar 8, 2026
2314587
docs: prettier 패키지로 분리하지 않음
namdaeun Mar 8, 2026
8d9ba0e
chore: yarn install
namdaeun Mar 8, 2026
a47fbde
chore: autofix 옵션 추가
namdaeun Mar 8, 2026
eb2c899
chore: update scripts
namdaeun Mar 8, 2026
f173307
fix: lint-staged에서 Export검사 제외
namdaeun Mar 8, 2026
2123941
chore: import type rule 적용
namdaeun Mar 8, 2026
3e1714c
chore: lint-staged 규칙 정의
namdaeun Mar 8, 2026
1feea94
chore: pull request trigger 추가
namdaeun Mar 8, 2026
fcfeb5b
chore: update workflows
namdaeun Mar 8, 2026
470dc6f
chore: merge
namdaeun Mar 9, 2026
8194895
chore: label workflow에서 파일 목록 paginate 처리
namdaeun Mar 11, 2026
dde4939
chore: typecheck 명령어 추가
namdaeun Mar 11, 2026
7220188
chore: 앱별 스크립트 삭제
namdaeun Mar 11, 2026
781b6d8
docs: 파일명 변경
namdaeun Mar 11, 2026
8777806
chore: 버전 변경
namdaeun Mar 11, 2026
14027ba
chore: ignorePatterns 추가 및 ignore 파일 삭제
namdaeun Mar 11, 2026
20d36be
chore: 안쓰는 script 삭제
namdaeun Mar 11, 2026
a30bc16
chore: 안 쓰이는 script 삭제
namdaeun Mar 11, 2026
97f3e10
chore: sort 명령어 추가
namdaeun Mar 11, 2026
c5678a9
chore: update scripts
namdaeun Mar 11, 2026
ac809ed
chore: update scripts
namdaeun Mar 11, 2026
992cc34
fix: 버그 우회를 위해 ignore 빈 파일 추가
namdaeun Mar 11, 2026
480110f
chore: 주석 추가
namdaeun Mar 11, 2026
33aad0f
chore: 안 쓰는 워크플로우 제거
namdaeun Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 13 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# dependencies
node_modules

# build outputs
.next
out
dist

# generated files
**/__generated__

# storybook
storybook-static
10 changes: 10 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# dependencies
node_modules

# build outputs
.next
out
dist

# docs
**/*.md
36 changes: 1 addition & 35 deletions apps/crew/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,4 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": {
"es6": true,
"node": true,
"browser": true
},
"plugins": ["@typescript-eslint", "prettier", "import"],
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"plugin:storybook/recommended"
],
"rules": {
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-empty-function": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react-hooks/set-state-in-effect": "warn",
"react-hooks/static-components": "warn",
"react-hooks/immutability": "warn",
"react-hooks/refs": "warn",
"react-hooks/incompatible-library": "warn",
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
],
"import/no-unused-modules": [1, { "unusedExports": true }],
"react/no-unstable-nested-components": "off"
}
"extends": ["@sopt-makers/eslint-config/next"]
}
8 changes: 0 additions & 8 deletions apps/crew/.prettierrc

This file was deleted.

2 changes: 1 addition & 1 deletion apps/crew/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const config: StorybookConfig = {
autodocs: 'tag',
},
webpackFinal(config) {
const imageRule = config.module!.rules!.find(rule => {
const imageRule = config.module!.rules!.find((rule) => {
if (rule && typeof rule !== 'string' && rule.test instanceof RegExp) {
return rule.test.test('.svg');
}
Expand Down
4 changes: 2 additions & 2 deletions apps/crew/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Preview } from '@storybook/react';
import { OverlayProvider } from '../src/hooks/useOverlay/OverlayProvider';
import { OverlayProvider } from '../src/hook/useOverlay/OverlayProvider';
import React from 'react';
import '../styles/globals.css';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -24,7 +24,7 @@ const preview: Preview = {
},
},
decorators: [
Story => {
(Story) => {
const queryClient = new QueryClient();

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/crew/ampli.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
"Language": "TypeScript",
"SDK": "@amplitude/analytics-browser@^1.0",
"Path": "./src/ampli"
}
}
2 changes: 1 addition & 1 deletion apps/crew/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const nextConfig = {
output: 'export',
reactStrictMode: true,
swcMinify: true,
webpack: config => {
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
oneOf: [
Expand Down
7 changes: 2 additions & 5 deletions apps/crew/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
"name": "crew",
"version": "0.1.0",
"private": true,
"prettier": "@sopt-makers/prettier-config",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prettier": "prettier --write . --ignore-path ../../.prettierignore",
"typecheck": "tsc --noemit -p .",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
Expand Down Expand Up @@ -52,12 +54,7 @@
"@hookform/devtools": "^4.3.1",
"@types/react-mentions": "4.1.13",
"@types/react-responsive": "^8.0.5",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react-hooks": "^7.0.1",
"openapi-typescript": "^6.3.9",
"prettier": "^3.0.0",
"wrangler": "^3.0.0"
}
}
160 changes: 65 additions & 95 deletions apps/crew/packages/react-mentions/src/Highlighter.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import React, { Children, useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import { defaultStyle } from './utils'
import React, { Children, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { defaultStyle } from './utils';

import {
iterateMentionsMarkup,
mapPlainTextIndex,
readConfigFromChildren,
isNumber,
} from './utils'
import { iterateMentionsMarkup, mapPlainTextIndex, readConfigFromChildren, isNumber } from './utils';

const _generateComponentKey = (usedKeys, id) => {
if (!usedKeys.hasOwnProperty(id)) {
usedKeys[id] = 0
usedKeys[id] = 0;
} else {
usedKeys[id]++
usedKeys[id]++;
}
return id + '_' + usedKeys[id]
}
return id + '_' + usedKeys[id];
};

function Highlighter({
selectionStart,
Expand All @@ -31,46 +26,41 @@ function Highlighter({
const [position, setPosition] = useState({
left: undefined,
top: undefined,
})
const [caretElement, setCaretElement] = useState()
});
const [caretElement, setCaretElement] = useState();

useEffect(() => {
notifyCaretPosition()
})
notifyCaretPosition();
});

const notifyCaretPosition = () => {
if (!caretElement) {
return
return;
}

const { offsetLeft, offsetTop } = caretElement
const { offsetLeft, offsetTop } = caretElement;

if (position.left === offsetLeft && position.top === offsetTop) {
return
return;
}

const newPosition = { left: offsetLeft, top: offsetTop }
setPosition(newPosition)
const newPosition = { left: offsetLeft, top: offsetTop };
setPosition(newPosition);

onCaretPositionChange(newPosition)
}
onCaretPositionChange(newPosition);
};

const config = readConfigFromChildren(children)
let caretPositionInMarkup
const config = readConfigFromChildren(children);
let caretPositionInMarkup;

if (selectionEnd === selectionStart) {
caretPositionInMarkup = mapPlainTextIndex(
value,
config,
selectionStart,
'START'
)
caretPositionInMarkup = mapPlainTextIndex(value, config, selectionStart, 'START');
}

const resultComponents = []
const componentKeys = {}
let components = resultComponents
let substringComponentKey = 0
const resultComponents = [];
const componentKeys = {};
let components = resultComponents;
let substringComponentKey = 0;

const textIteratee = (substr, index, indexInPlainText) => {
// check whether the caret element has to be inserted inside the current plain substring
Expand All @@ -80,74 +70,60 @@ function Highlighter({
caretPositionInMarkup <= index + substr.length
) {
// if yes, split substr at the caret position and insert the caret component
const splitIndex = caretPositionInMarkup - index
components.push(
renderSubstring(substr.substring(0, splitIndex), substringComponentKey)
)
const splitIndex = caretPositionInMarkup - index;
components.push(renderSubstring(substr.substring(0, splitIndex), substringComponentKey));
// add all following substrings and mention components as children of the caret component
components = [
renderSubstring(substr.substring(splitIndex), substringComponentKey),
]
components = [renderSubstring(substr.substring(splitIndex), substringComponentKey)];
} else {
components.push(renderSubstring(substr, substringComponentKey))
components.push(renderSubstring(substr, substringComponentKey));
}

substringComponentKey++
}
substringComponentKey++;
};

const mentionIteratee = (
markup,
index,
indexInPlainText,
id,
display,
mentionChildIndex,
lastMentionEndIndex
) => {
const key = _generateComponentKey(componentKeys, id)
components.push(
getMentionComponentForMatch(id, display, mentionChildIndex, key)
)
}
const mentionIteratee = (markup, index, indexInPlainText, id, display, mentionChildIndex, lastMentionEndIndex) => {
const key = _generateComponentKey(componentKeys, id);
components.push(getMentionComponentForMatch(id, display, mentionChildIndex, key));
};

const renderSubstring = (string, key) => {
// set substring span to hidden, so that Emojis are not shown double in Mobile Safari
return (
<span {...style('substring')} key={key}>
{string}
</span>
)
}
);
};

const getMentionComponentForMatch = (id, display, mentionChildIndex, key) => {
const props = { id, display, key }
const child = Children.toArray(children)[mentionChildIndex]
return React.cloneElement(child, props)
}
const props = { id, display, key };
const child = Children.toArray(children)[mentionChildIndex];
return React.cloneElement(child, props);
};

const renderHighlighterCaret = (children) => {
return (
<span {...style('caret')} ref={setCaretElement} key="caret">
<span {...style('caret')} ref={setCaretElement} key='caret'>
{children}
</span>
)
}
);
};

iterateMentionsMarkup(value, config, mentionIteratee, textIteratee)
iterateMentionsMarkup(value, config, mentionIteratee, textIteratee);

// append a span containing a space, to ensure the last text line has the correct height
components.push(' ')
components.push(' ');

if (components !== resultComponents) {
// if a caret component is to be rendered, add all components that followed as its children
resultComponents.push(renderHighlighterCaret(components))
resultComponents.push(renderHighlighterCaret(components));
}

return (
<div {...style} ref={containerRef}>
{resultComponents}
</div>
)
);
}

Highlighter.propTypes = {
Expand All @@ -158,42 +134,36 @@ Highlighter.propTypes = {
containerRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({
current:
typeof Element === 'undefined'
? PropTypes.any
: PropTypes.instanceOf(Element),
current: typeof Element === 'undefined' ? PropTypes.any : PropTypes.instanceOf(Element),
}),
]),
children: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element),
]).isRequired,
}
children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]).isRequired,
};

const styled = defaultStyle(
{
position: 'relative',
boxSizing: 'border-box',
width: '100%',
color: 'transparent',
overflow: 'hidden',
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
border: '1px solid transparent',
textAlign: 'start',
'position': 'relative',
'boxSizing': 'border-box',
'width': '100%',
'color': 'transparent',
'overflow': 'hidden',
'whiteSpace': 'pre-wrap',
'wordWrap': 'break-word',
'border': '1px solid transparent',
'textAlign': 'start',

'&singleLine': {
whiteSpace: 'pre',
wordWrap: null,
},

substring: {
'substring': {
visibility: 'hidden',
},
},
(props) => ({
'&singleLine': props.singleLine,
})
)
}),
);

export default styled(Highlighter)
export default styled(Highlighter);
Loading
Loading