@loword/loword-design-system 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,7 @@ const variantColorClasses = {
16
16
  filled: {
17
17
  neutral: 'bg-neutral50 text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:bg-tintBlue focus-within:outline-lb500',
18
18
  point: 'bg-tintBlue text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:outline-lb500',
19
- danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:outline-danger600',
19
+ danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-danger600 outline-solid -outline-offset-2',
20
20
  },
21
21
  outline: {
22
22
  neutral: 'bg-transparent text-neutral900 border-none outline-2 outline-neutral100 outline-solid -outline-offset-2 focus-within:outline-lb500',
@@ -23,7 +23,7 @@ const variantColorClasses = {
23
23
  filled: {
24
24
  neutral: 'bg-neutral50 text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:bg-tintBlue focus-within:outline-lb500',
25
25
  point: 'bg-tintBlue text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:outline-lb500',
26
- danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-transparent outline-solid -outline-offset-2 focus-within:outline-danger600',
26
+ danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-danger600 outline-solid -outline-offset-2',
27
27
  },
28
28
  outline: {
29
29
  neutral: 'bg-transparent text-neutral900 border-none outline-2 outline-neutral100 outline-solid -outline-offset-2 focus-within:outline-lb500',
@@ -1 +1 @@
1
- {"version":3,"file":"LDEditor.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/LDEditor.tsx"],"names":[],"mappings":"AA4EA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9B;AAED,QAAA,MAAM,QAAQ,GAAI,sDAKf,aAAa,4CAYf,CAAC;AAyjBF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"LDEditor.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/LDEditor.tsx"],"names":[],"mappings":"AA8IA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9B;AAED,QAAA,MAAM,QAAQ,GAAI,sDAKf,aAAa,4CAYf,CAAC;AAwmBF,eAAe,QAAQ,CAAC"}
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useEditorState } from '@tiptap/react';
4
4
  import { BubbleMenu } from '@tiptap/react/menus';
5
- import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, ChevronDown, Image as ImageIcon, Italic, Link2, List, ListOrdered, Redo, Strikethrough, Underline, Undo, Unlink, } from 'lucide-react';
5
+ import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, ChevronDown, Image as ImageIcon, Italic, Link2, List, ListOrdered, Redo, Strikethrough, Table as TableIcon, Underline, Undo, Unlink, } from 'lucide-react';
6
6
  import { useEffect, useState } from 'react';
7
7
  import EditorBase, { useEditorContext } from '../../components/LDEditor/EditorBase.js';
8
8
  import { createEditorExtensions } from '../../components/LDEditor/extensions.js';
@@ -35,6 +35,40 @@ const HEADINGS = [
35
35
  { label: '제목 2', level: 2 },
36
36
  { label: '제목 3', level: 3 },
37
37
  ];
38
+ const TABLE_GRID_MAX = 5;
39
+ const TABLE_ACTIONS = [
40
+ { label: '위에 행 추가', run: (e) => e.chain().focus().addRowBefore().run() },
41
+ { label: '아래 행 추가', run: (e) => e.chain().focus().addRowAfter().run() },
42
+ {
43
+ label: '왼쪽 열 추가',
44
+ run: (e) => e.chain().focus().addColumnBefore().run(),
45
+ },
46
+ {
47
+ label: '오른쪽 열 추가',
48
+ run: (e) => e.chain().focus().addColumnAfter().run(),
49
+ },
50
+ { label: '행 삭제', run: (e) => e.chain().focus().deleteRow().run() },
51
+ { label: '열 삭제', run: (e) => e.chain().focus().deleteColumn().run() },
52
+ {
53
+ label: '헤더 행 토글',
54
+ run: (e) => e.chain().focus().toggleHeaderRow().run(),
55
+ },
56
+ { label: '표 삭제', run: (e) => e.chain().focus().deleteTable().run() },
57
+ ];
58
+ // 삽입할 표 크기를 호버(키보드는 포커스)로 고르는 5x5 그리드.
59
+ // Dropdown의 children은 렌더 콜백이라 훅을 쓸 수 없어 별도 컴포넌트로 뺀다.
60
+ const TableGridPicker = ({ onSelect, }) => {
61
+ const [size, setSize] = useState({ rows: 0, cols: 0 });
62
+ return (_jsxs("div", { className: "p-2", children: [_jsx("div", { className: "grid grid-cols-5 gap-1", children: Array.from({ length: TABLE_GRID_MAX * TABLE_GRID_MAX }, (_, index) => {
63
+ const rows = Math.floor(index / TABLE_GRID_MAX) + 1;
64
+ const cols = (index % TABLE_GRID_MAX) + 1;
65
+ const filled = rows <= size.rows && cols <= size.cols;
66
+ return (_jsx("button", { type: "button", "aria-label": `${rows}행 ${cols}열 표 삽입`, onMouseEnter: () => setSize({ rows, cols }), onFocus: () => setSize({ rows, cols }), onClick: (event) => {
67
+ event.preventDefault();
68
+ onSelect(rows, cols);
69
+ }, className: cn('size-5 cursor-pointer rounded-xs border border-neutral200', filled && 'border-blue-500 bg-blue-100') }, index));
70
+ }) }), _jsx("p", { className: "mt-2 text-center text-sm", children: size.rows ? `${size.rows} x ${size.cols}` : '크기 선택' })] }));
71
+ };
38
72
  const iconBtn = 'p-1 rounded-lg cursor-pointer transition hover:bg-mono100 disabled:opacity-30 disabled:cursor-not-allowed';
39
73
  const activeBtn = 'bg-mono100';
40
74
  const LDDivider = () => _jsx("div", { className: "mx-1 h-6 w-px bg-neutral200" });
@@ -77,6 +111,7 @@ const EditorToolbar = ({ handleImageUpload, }) => {
77
111
  canUndo: editor.can().undo(),
78
112
  canRedo: editor.can().redo(),
79
113
  isLink: editor.isActive('link'),
114
+ isTable: editor.isActive('table'),
80
115
  hasSelection: !editor.state.selection.empty,
81
116
  };
82
117
  },
@@ -175,7 +210,18 @@ const EditorToolbar = ({ handleImageUpload, }) => {
175
210
  setLinkUrl('');
176
211
  close();
177
212
  }, className: "rounded-lg border border-neutral200 px-3 py-1.5 text-sm transition duration-300 hover:bg-mono100", children: "\uCDE8\uC18C" })] })] }));
178
- } }), _jsx(EditorBase.Toolbar.LDButton, { disabled: !state.isLink, onClick: () => editor.chain().focus().unsetLink().run(), className: iconBtn, "aria-label": "\uB9C1\uD06C \uD574\uC81C", children: _jsx(Unlink, { className: "size-5" }) })] })), _jsx(LDDivider, {}), _jsxs("label", { className: cn(iconBtn, 'relative'), children: [_jsx(ImageIcon, { className: "size-5" }), _jsx("input", { type: "file", accept: "image/*", "aria-label": "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", className: "absolute inset-0 size-full cursor-pointer opacity-0", onChange: (e) => {
213
+ } }), _jsx(EditorBase.Toolbar.LDButton, { disabled: !state.isLink, onClick: () => editor.chain().focus().unsetLink().run(), className: iconBtn, "aria-label": "\uB9C1\uD06C \uD574\uC81C", children: _jsx(Unlink, { className: "size-5" }) })] })), _jsx(LDDivider, {}), _jsx(EditorBase.Toolbar.Dropdown, { className: "min-w-40 rounded-lg border border-neutral200 bg-white shadow-lg", trigger: ({ toggle }) => (_jsx(EditorBase.Toolbar.LDButton, { "aria-label": "\uD45C", onClick: toggle, className: cn(iconBtn, state.isTable && activeBtn), children: _jsx(TableIcon, { className: "size-5" }) })), children: ({ close }) => state.isTable ? (_jsx("div", { children: TABLE_ACTIONS.map(({ label, run }) => (_jsx("button", { type: "button", onClick: (e) => {
214
+ e.preventDefault();
215
+ run(editor);
216
+ close();
217
+ }, className: "w-full cursor-pointer px-3 py-2 text-left text-sm first:rounded-t-lg last:rounded-b-lg hover:bg-mono100", children: label }, label))) })) : (_jsx(TableGridPicker, { onSelect: (rows, cols) => {
218
+ editor
219
+ .chain()
220
+ .focus()
221
+ .insertTable({ rows, cols, withHeaderRow: true })
222
+ .run();
223
+ close();
224
+ } })) }), _jsxs("label", { className: cn(iconBtn, 'relative'), children: [_jsx(ImageIcon, { className: "size-5" }), _jsx("input", { type: "file", accept: "image/*", "aria-label": "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", className: "absolute inset-0 size-full cursor-pointer opacity-0", onChange: (e) => {
179
225
  handleImageUploadAction(e.target.files);
180
226
  e.target.value = '';
181
227
  } })] })] }), isMobile && (_jsxs(BubbleMenu, { editor: editor, className: "flex items-center gap-1 rounded-lg border border-neutral200 bg-white p-1 shadow-lg", children: [_jsx(EditorBase.Toolbar.LDButton, { onClick: () => editor.chain().focus().toggleBold().run(), className: cn(iconBtn, state.isBold && activeBtn), "aria-label": "\uAD75\uAC8C", children: _jsx(Bold, { className: "size-5" }) }), _jsx(EditorBase.Toolbar.LDButton, { onClick: () => editor.chain().focus().toggleItalic().run(), className: cn(iconBtn, state.isItalic && activeBtn), "aria-label": "\uAE30\uC6B8\uC784", children: _jsx(Italic, { className: "size-5" }) }), _jsx(EditorBase.Toolbar.LDButton, { onClick: () => editor.chain().focus().toggleUnderline().run(), className: cn(iconBtn, state.isUnderline && activeBtn), "aria-label": "\uBC11\uC904", children: _jsx(Underline, { className: "size-5" }) }), _jsx(EditorBase.Toolbar.LDButton, { onClick: () => editor.chain().focus().toggleStrike().run(), className: cn(iconBtn, state.isStrike && activeBtn), "aria-label": "\uCDE8\uC18C\uC120", children: _jsx(Strikethrough, { className: "size-5" }) }), _jsx(EditorBase.Toolbar.Dropdown, { className: "min-w-35 rounded-lg border border-neutral200 bg-white shadow-lg", trigger: ({ toggle }) => (_jsxs(EditorBase.Toolbar.LDButton, { onClick: toggle, className: cn(iconBtn, 'flex items-center gap-1 px-2'), "aria-label": "\uAE00\uC790 \uC0C9", children: [_jsx("span", { className: "size-4 rounded-full", style: { backgroundColor: state.color } }), _jsx(ChevronDown, { className: "size-4" })] })), children: ({ close }) => COLORS.map((color) => (_jsxs("button", { type: "button", onClick: (e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"LDViewer.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/LDViewer.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,QAAQ,GAAI,wBAAwB,aAAa,4CAQtD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"LDViewer.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/LDViewer.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,QAAQ,GAAI,wBAAwB,aAAa,4CAWtD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -4,6 +4,9 @@ import EditorBase from '../../components/LDEditor/EditorBase.js';
4
4
  import { createEditorExtensions } from '../../components/LDEditor/extensions.js';
5
5
  import cn from '../../utils/cn.js';
6
6
  const LDViewer = ({ content, className }) => {
7
- return (_jsx(EditorBase.LDViewer, { extensions: createEditorExtensions({ resizableImage: false }), content: content, className: cn('prose prose-lg w-full max-w-none', className) }));
7
+ return (_jsx(EditorBase.LDViewer, { extensions: createEditorExtensions({
8
+ resizableImage: false,
9
+ resizableTable: false,
10
+ }), content: content, className: cn('prose prose-lg w-full max-w-none', className) }));
8
11
  };
9
12
  export default LDViewer;
@@ -1,6 +1,7 @@
1
1
  import type { Extensions } from '@tiptap/react';
2
2
  export interface EditorExtensionOptions {
3
3
  resizableImage?: boolean;
4
+ resizableTable?: boolean;
4
5
  }
5
- export declare const createEditorExtensions: ({ resizableImage, }?: EditorExtensionOptions) => Extensions;
6
+ export declare const createEditorExtensions: ({ resizableImage, resizableTable, }?: EditorExtensionOptions) => Extensions;
6
7
  //# sourceMappingURL=extensions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/extensions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,sBAAsB,GAAI,sBAEpC,sBAA2B,KAAG,UA+BhC,CAAC"}
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/components/LDEditor/extensions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,sBAAsB,GAAI,sCAGpC,sBAA2B,KAAG,UAwChC,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import Image from '@tiptap/extension-image';
2
+ import { TableKit } from '@tiptap/extension-table';
2
3
  import TextAlign from '@tiptap/extension-text-align';
3
4
  import { Color, FontSize, TextStyle } from '@tiptap/extension-text-style';
4
5
  import StarterKit from '@tiptap/starter-kit';
5
- export const createEditorExtensions = ({ resizableImage = true, } = {}) => [
6
+ export const createEditorExtensions = ({ resizableImage = true, resizableTable = true, } = {}) => [
6
7
  // link·underline은 StarterKit에 포함돼 있다. 따로 등록하면 중복 경고가 난다.
7
8
  StarterKit.configure({
8
9
  heading: {
@@ -33,4 +34,13 @@ export const createEditorExtensions = ({ resizableImage = true, } = {}) => [
33
34
  }
34
35
  : false,
35
36
  }),
37
+ TableKit.configure({
38
+ table: {
39
+ resizable: resizableTable,
40
+ // 리사이즈로 표가 컨테이너보다 넓어질 수 있다. 래퍼가 있어야 가로 스크롤을
41
+ // 표에만 줄 수 있다. 편집 모드에서는 TableView가 항상 래퍼를 만들지만
42
+ // 읽기 전용(LDViewer)에서는 이 옵션이 있어야 생긴다.
43
+ renderWrapper: true,
44
+ },
45
+ }),
36
46
  ];
@@ -22,6 +22,8 @@ export interface LDModalOptions<T = undefined> {
22
22
  icon?: 'success' | 'fail';
23
23
  /** 스크롤 동작 (LDModalView와 동일) */
24
24
  scrollBehavior?: 'inside' | 'outside';
25
+ /** 오버레이(모달 바깥) 클릭으로 닫기 허용 여부 */
26
+ closeOnOverlayClick?: boolean;
25
27
  /** 모달 패널에 적용할 추가 CSS 클래스 */
26
28
  className?: string;
27
29
  /** 모달 패널 인라인 스타일 (자유 width/height 등) */
@@ -1 +1 @@
1
- {"version":3,"file":"LDModal.d.ts","sourceRoot":"","sources":["../../../src/components/LDModal/LDModal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAoB,MAAM,OAAO,CAAC;AAG7E,OAAoB,EAElB,KAAK,SAAS,EACd,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,SAAS;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAA;KAAE,KAAK,SAAS,CAAC,CAAC;IAC9E,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;QACzD,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;QACvC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;KAC1D,EAAE,CAAC;IACJ,eAAe;IACf,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,+BAA+B;IAC/B,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACtC,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACjD,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,QAAA,MAAM,OAAO,GAAI,CAAC,GAAG,SAAS,EAC5B,SAAS,cAAc,CAAC,CAAC,CAAC,KACzB,OAAO,CAAC,CAAC,GAAG,SAAS,CA2EvB,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"LDModal.d.ts","sourceRoot":"","sources":["../../../src/components/LDModal/LDModal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAoB,MAAM,OAAO,CAAC;AAG7E,OAAoB,EAElB,KAAK,SAAS,EACd,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,SAAS;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAA;KAAE,KAAK,SAAS,CAAC,CAAC;IAC9E,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;QACzD,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;QACvC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;KAC1D,EAAE,CAAC;IACJ,eAAe;IACf,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,+BAA+B;IAC/B,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACtC,gCAAgC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACjD,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,QAAA,MAAM,OAAO,GAAI,CAAC,GAAG,SAAS,EAC5B,SAAS,cAAc,CAAC,CAAC,CAAC,KACzB,OAAO,CAAC,CAAC,GAAG,SAAS,CA4EvB,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -50,7 +50,7 @@ const LDModal = (options) => {
50
50
  return (_jsx(LDModalView, { open: open, onOpenChange: (next) => {
51
51
  if (!next)
52
52
  close(undefined);
53
- }, name: options.name, title: options.title, description: options.description, size: options.size, icon: options.icon, scrollBehavior: options.scrollBehavior, style: options.style, buttons: list ? { direction: options.buttonsDirection, list } : undefined, classNames: options.classNames, children: content }));
53
+ }, name: options.name, title: options.title, description: options.description, size: options.size, icon: options.icon, scrollBehavior: options.scrollBehavior, closeOnOverlayClick: options.closeOnOverlayClick, style: options.style, buttons: list ? { direction: options.buttonsDirection, list } : undefined, classNames: options.classNames, children: content }));
54
54
  };
55
55
  root.render(_jsx(ModalHost, {}));
56
56
  });
@@ -50,12 +50,14 @@ export interface LDModalViewProps {
50
50
  buttons?: ModalButtons;
51
51
  /** 스크롤 동작 */
52
52
  scrollBehavior?: 'inside' | 'outside';
53
+ /** 오버레이(모달 바깥) 클릭으로 닫기 허용 여부 */
54
+ closeOnOverlayClick?: boolean;
53
55
  /** 인라인 스타일 (모달 패널에 적용) */
54
56
  style?: React.CSSProperties;
55
57
  /** 버튼 클릭 시 해당 버튼의 value를 전달하는 콜백 */
56
58
  onButtonClick?: (value: unknown) => void;
57
59
  classNames?: TModalClassNames;
58
60
  }
59
- declare const LDModalView: ({ open, defaultOpen, onOpenChange, name, title, description, children, size, icon, buttons, scrollBehavior, classNames, style, onButtonClick, }: LDModalViewProps) => import("react/jsx-runtime").JSX.Element;
61
+ declare const LDModalView: ({ open, defaultOpen, onOpenChange, name, title, description, children, size, icon, buttons, scrollBehavior, closeOnOverlayClick, classNames, style, onButtonClick, }: LDModalViewProps) => import("react/jsx-runtime").JSX.Element;
60
62
  export default LDModalView;
61
63
  //# sourceMappingURL=LDModalView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LDModalView.d.ts","sourceRoot":"","sources":["../../../src/components/LDModal/LDModalView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAU,MAAM,OAAO,CAAC;AAK/C,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,EAAE,CAAC,CAAC;IACT,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;IACzD,eAAe;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvC,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0BAA0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yBAAyB;IACzB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,YAAY;IACZ,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gBAAgB;IAChB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,aAAa;IACb,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gBAAgB;IAChB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,eAAe;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa;IACb,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACtC,0BAA0B;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AA6CD,QAAA,MAAM,WAAW,GAAI,iJAelB,gBAAgB,4CAkLlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"LDModalView.d.ts","sourceRoot":"","sources":["../../../src/components/LDModal/LDModalView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAU,MAAM,OAAO,CAAC;AAK/C,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,EAAE,CAAC,CAAC;IACT,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;IACzD,eAAe;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvC,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0BAA0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yBAAyB;IACzB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,YAAY;IACZ,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gBAAgB;IAChB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,aAAa;IACb,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,gBAAgB;IAChB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,eAAe;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa;IACb,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACtC,gCAAgC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,0BAA0B;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AA6CD,QAAA,MAAM,WAAW,GAAI,sKAgBlB,gBAAgB,4CAsLlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -42,7 +42,7 @@ const statusIconSizeClasses = {
42
42
  large: 'size-12.5',
43
43
  xlarge: 'size-12.5',
44
44
  };
45
- const LDModalView = ({ open, defaultOpen, onOpenChange, name, title, description, children, size = 'small', icon, buttons, scrollBehavior = 'inside', classNames, style, onButtonClick, }) => {
45
+ const LDModalView = ({ open, defaultOpen, onOpenChange, name, title, description, children, size = 'small', icon, buttons, scrollBehavior = 'inside', closeOnOverlayClick = true, classNames, style, onButtonClick, }) => {
46
46
  const overlayRef = useRef(false);
47
47
  const hasHeader = name || title || description || icon;
48
48
  const handleClick = async (button) => {
@@ -57,8 +57,9 @@ const LDModalView = ({ open, defaultOpen, onOpenChange, name, title, description
57
57
  return (_jsxs(ModalBase.Root, { open: open, defaultOpen: defaultOpen, onOpenChange: onOpenChange, children: [_jsx(ModalBase.Overlay, { className: classNames?.overlay }), _jsx(ModalBase.Content, { className: cn({
58
58
  ['top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2']: scrollBehavior === 'inside',
59
59
  ['inset-0 flex items-start justify-center overflow-y-auto py-20']: scrollBehavior === 'outside',
60
- }, classNames?.content), onMouseDown: (e) => (overlayRef.current = e.target === e.currentTarget), onClick: (e) => {
61
- if (scrollBehavior === 'outside' &&
60
+ }, classNames?.content), onPointerDownOutside: closeOnOverlayClick ? undefined : (e) => e.preventDefault(), onMouseDown: (e) => (overlayRef.current = e.target === e.currentTarget), onClick: (e) => {
61
+ if (closeOnOverlayClick &&
62
+ scrollBehavior === 'outside' &&
62
63
  e.target === e.currentTarget &&
63
64
  overlayRef.current)
64
65
  onOpenChange?.(false);
@@ -21,6 +21,7 @@ export declare const FILE_EXTENSIONS: {
21
21
  readonly 'image/tiff': "tiff";
22
22
  readonly 'image/webp': "webp";
23
23
  readonly 'image/x-icon': "ico";
24
+ readonly 'image/vnd.microsoft.icon': "ico";
24
25
  readonly 'image/heic': "heic";
25
26
  readonly 'image/heif': "heif";
26
27
  readonly 'application/pdf': "pdf";
@@ -37,7 +38,7 @@ export declare const FILE_EXTENSIONS: {
37
38
  export type TMimeType = keyof typeof FILE_EXTENSIONS;
38
39
  export type TFileExtension = (typeof FILE_EXTENSIONS)[TMimeType];
39
40
  export declare const SUPPORTED_FILE_MIME_TYPES: TMimeType[];
40
- export declare const SUPPORTED_IMAGE_MIME_TYPES: ("image/avif" | "image/apng" | "image/bmp" | "image/gif" | "image/jpg" | "image/jpeg" | "image/pjpeg" | "image/png" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/x-icon" | "image/heic" | "image/heif" | "application/pdf" | "text/plain" | "text/csv" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/json" | "application/zip" | "application/x-zip-compressed")[];
41
+ export declare const SUPPORTED_IMAGE_MIME_TYPES: ("image/avif" | "image/apng" | "image/bmp" | "image/gif" | "image/jpg" | "image/jpeg" | "image/pjpeg" | "image/png" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/x-icon" | "image/vnd.microsoft.icon" | "image/heic" | "image/heif" | "application/pdf" | "text/plain" | "text/csv" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/json" | "application/zip" | "application/x-zip-compressed")[];
41
42
  /** 에디터 툴바 이미지 업로드 허용 형식 */
42
43
  export declare const TOOLBAR_ALLOWED_EXTENSIONS: TMimeType[];
43
44
  /** 에디터 툴바 이미지 업로드 최대 용량 (5MB) */
@@ -1 +1 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/constants/file.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,uBAAuB;AACvB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;CA0BlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,eAAe,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC;AAEjE,eAAO,MAAM,yBAAyB,EAEjC,SAAS,EAAE,CAAC;AAEjB,eAAO,MAAM,0BAA0B,uhBAEtC,CAAC;AAEF,2BAA2B;AAC3B,eAAO,MAAM,0BAA0B,EAAE,SAAS,EAQjD,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,gBAAgB,QAAwB,CAAC"}
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/constants/file.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,uBAAuB;AACvB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,eAAe,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC;AAEjE,eAAO,MAAM,yBAAyB,EAEjC,SAAS,EAAE,CAAC;AAEjB,eAAO,MAAM,0BAA0B,ojBAEtC,CAAC;AAEF,2BAA2B;AAC3B,eAAO,MAAM,0BAA0B,EAAE,SAAS,EAQjD,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,gBAAgB,QAAwB,CAAC"}
@@ -21,6 +21,7 @@ export const FILE_EXTENSIONS = {
21
21
  'image/tiff': 'tiff',
22
22
  'image/webp': 'webp',
23
23
  'image/x-icon': 'ico',
24
+ 'image/vnd.microsoft.icon': 'ico',
24
25
  'image/heic': 'heic',
25
26
  'image/heif': 'heif',
26
27
  'application/pdf': 'pdf',
package/dist/index.css CHANGED
@@ -9,6 +9,7 @@
9
9
  "Courier New", monospace;
10
10
  --color-red-500: oklch(63.7% 0.237 25.331);
11
11
  --color-yellow-400: oklch(85.2% 0.199 91.936);
12
+ --color-blue-100: oklch(93.2% 0.032 255.585);
12
13
  --color-blue-400: oklch(70.7% 0.165 254.624);
13
14
  --color-blue-500: oklch(62.3% 0.214 259.815);
14
15
  --color-blue-600: oklch(54.6% 0.245 262.881);
@@ -2018,6 +2019,9 @@
2018
2019
  .grid-cols-3 {
2019
2020
  grid-template-columns: repeat(3, minmax(0, 1fr));
2020
2021
  }
2022
+ .grid-cols-5 {
2023
+ grid-template-columns: repeat(5, minmax(0, 1fr));
2024
+ }
2021
2025
  .grid-cols-7 {
2022
2026
  grid-template-columns: repeat(7, minmax(0, 1fr));
2023
2027
  }
@@ -2361,6 +2365,9 @@
2361
2365
  --tw-border-style: solid;
2362
2366
  border-style: solid;
2363
2367
  }
2368
+ .border-blue-500 {
2369
+ border-color: var(--color-blue-500);
2370
+ }
2364
2371
  .border-blue500 {
2365
2372
  border-color: var(--color-blue500);
2366
2373
  }
@@ -2439,6 +2446,9 @@
2439
2446
  background-color: color-mix(in oklab, var(--color-black) 40%, transparent);
2440
2447
  }
2441
2448
  }
2449
+ .bg-blue-100 {
2450
+ background-color: var(--color-blue-100);
2451
+ }
2442
2452
  .bg-blue-500 {
2443
2453
  background-color: var(--color-blue-500);
2444
2454
  }
@@ -4845,6 +4855,13 @@
4845
4855
  letter-spacing: var(--tracking-display14);
4846
4856
  }
4847
4857
  }
4858
+ .tablet-down\:display16 {
4859
+ @media (max-width: calc(992px - 1px)) {
4860
+ font-size: var(--text-display16);
4861
+ line-height: var(--leading-display16);
4862
+ letter-spacing: var(--tracking-display16);
4863
+ }
4864
+ }
4848
4865
  .\[\&_svg\]\:icon-2xs {
4849
4866
  & svg {
4850
4867
  width: var(--control-icon-2xs);
@@ -5604,6 +5621,51 @@
5604
5621
  .ProseMirror [data-resize-wrapper] img {
5605
5622
  margin: 0 !important;
5606
5623
  }
5624
+ .ProseMirror .tableWrapper {
5625
+ overflow-x: auto;
5626
+ margin: 1rem 0;
5627
+ }
5628
+ .ProseMirror table {
5629
+ width: 100%;
5630
+ margin: 0;
5631
+ table-layout: fixed;
5632
+ border-collapse: collapse;
5633
+ }
5634
+ .ProseMirror table td, .ProseMirror table th {
5635
+ position: relative;
5636
+ min-width: 1em;
5637
+ padding: 0.5rem 0.75rem;
5638
+ border: 1px solid var(--color-neutral200);
5639
+ vertical-align: top;
5640
+ }
5641
+ .ProseMirror table th {
5642
+ background: var(--color-mono100);
5643
+ font-weight: 600;
5644
+ text-align: left;
5645
+ }
5646
+ .ProseMirror table p {
5647
+ margin: 0;
5648
+ }
5649
+ .ProseMirror .selectedCell::after {
5650
+ content: '';
5651
+ position: absolute;
5652
+ inset: 0;
5653
+ background: rgba(59, 130, 246, 0.15);
5654
+ pointer-events: none;
5655
+ z-index: 2;
5656
+ }
5657
+ .ProseMirror .column-resize-handle {
5658
+ position: absolute;
5659
+ top: 0;
5660
+ right: -2px;
5661
+ bottom: -2px;
5662
+ width: 4px;
5663
+ background: #3b82f6;
5664
+ pointer-events: none;
5665
+ }
5666
+ .ProseMirror.resize-cursor {
5667
+ cursor: col-resize;
5668
+ }
5607
5669
  @layer components {
5608
5670
  .select-2xs {
5609
5671
  height: var(--control-height-2xs);
@@ -1 +1 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/utils/file.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,YACW,CAAC;AAE/C,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,YACU,CAAC;AAgCnD,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,YAM9C,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,UAAU,SAAS,KAClB,cAAc,GAAG,MAEnB,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,OAAO,CAoB1D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,EAAE,SAAS,MAAM,YAExD,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,MAAM,IAAI,EACV,mBAAmB,SAAS,EAAE,YAG/B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,oBAS7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CAM5D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,KAAK,CAa5D,CAAC"}
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/utils/file.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,YACW,CAAC;AAE/C,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,YACU,CAAC;AAgCnD,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,YAM9C,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,UAAU,SAAS,KAClB,cAAc,GAAG,MAEnB,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,OAAO,CAoB1D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,EAAE,SAAS,MAAM,YAExD,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,MAAM,IAAI,EACV,mBAAmB,SAAS,EAAE,YAS/B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,oBAS7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CAM5D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,KAAK,CAa5D,CAAC"}
@@ -63,7 +63,10 @@ export const validFileSize = (file, maxSize) => {
63
63
  return file.size <= maxSize;
64
64
  };
65
65
  export const validAllowedExtensions = (file, allowedExtensions) => {
66
- return allowedExtensions.includes(file.type);
66
+ const mimeType = file.type;
67
+ return allowedExtensions.some((allowed) => allowed === mimeType ||
68
+ (FILE_EXTENSIONS[mimeType] === 'ico' &&
69
+ FILE_EXTENSIONS[allowed] === 'ico'));
67
70
  };
68
71
  export const getFileSizeUnit = (number) => {
69
72
  if (number < FILE_SIZE_UNIT.kb)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loword/loword-design-system",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "로워드 디자인 시스템 컴포넌트 패키지(Tailwind v4)",
5
5
  "keywords": [
6
6
  "react",
@@ -38,6 +38,7 @@
38
38
  },
39
39
  "./theme.css": "./src/theme.css",
40
40
  "./styles.css": "./dist/index.css",
41
+ "./components.css": "./src/styles/components.css",
41
42
  "./*": {
42
43
  "types": "./dist/*.d.ts",
43
44
  "default": "./dist/*.js"
@@ -62,6 +63,7 @@
62
63
  "@tiptap/extension-highlight": "^3.26.0",
63
64
  "@tiptap/extension-image": "^3.26.0",
64
65
  "@tiptap/extension-link": "^3.26.0",
66
+ "@tiptap/extension-table": "^3.26.0",
65
67
  "@tiptap/extension-text-align": "^3.26.0",
66
68
  "@tiptap/extension-text-style": "^3.26.0",
67
69
  "@tiptap/extension-underline": "^3.26.0",
@@ -75,7 +77,7 @@
75
77
  "embla-carousel-auto-scroll": "^8.6.0",
76
78
  "embla-carousel-autoplay": "^8.6.0",
77
79
  "embla-carousel-react": "^8.6.0",
78
- "next": "^15",
80
+ "next": "^15 || ^16",
79
81
  "react": "^19",
80
82
  "react-chartjs-2": "^5.2.0",
81
83
  "react-daum-postcode": "^4.0.0",
@@ -130,6 +132,9 @@
130
132
  "@tiptap/extension-link": {
131
133
  "optional": true
132
134
  },
135
+ "@tiptap/extension-table": {
136
+ "optional": true
137
+ },
133
138
  "@tiptap/extension-text-align": {
134
139
  "optional": true
135
140
  },
@@ -199,7 +204,6 @@
199
204
  "@storybook/addon-vitest": "10.5.7",
200
205
  "@storybook/nextjs-vite": "10.5.7",
201
206
  "@tailwindcss/cli": "^4.1.5",
202
- "@tailwindcss/typography": "^0.5.20",
203
207
  "@tailwindcss/vite": "^4.2.2",
204
208
  "@tanstack/react-table": "^8.21.3",
205
209
  "@tiptap/core": "^3.26.0",
@@ -209,6 +213,7 @@
209
213
  "@tiptap/extension-highlight": "^3.26.0",
210
214
  "@tiptap/extension-image": "^3.26.0",
211
215
  "@tiptap/extension-link": "^3.26.0",
216
+ "@tiptap/extension-table": "^3.26.0",
212
217
  "@tiptap/extension-text-align": "^3.26.0",
213
218
  "@tiptap/extension-text-style": "^3.26.0",
214
219
  "@tiptap/extension-underline": "^3.26.0",
@@ -261,6 +266,7 @@
261
266
  "@dnd-kit/modifiers": "^9.0.0",
262
267
  "@dnd-kit/sortable": "^10.0.0",
263
268
  "@dnd-kit/utilities": "^3.2.2",
269
+ "@tailwindcss/typography": "^0.5.20",
264
270
  "clsx": "^2.1.1",
265
271
  "lucide-react": "^0.536.0",
266
272
  "react-hook-form": "^7.62.0",
@@ -165,3 +165,65 @@
165
165
  .ProseMirror [data-resize-wrapper] img {
166
166
  margin: 0 !important;
167
167
  }
168
+
169
+ /* 표
170
+ prose 기본 표는 가로줄만 그어 에디터에서 셀 경계가 보이지 않는다. 격자 테두리로 덮는다.
171
+ @layer 밖(=무레이어)이라 utilities 레이어의 prose보다 우선한다. */
172
+ .ProseMirror .tableWrapper {
173
+ overflow-x: auto;
174
+ margin: 1rem 0;
175
+ }
176
+
177
+ .ProseMirror table {
178
+ width: 100%;
179
+ margin: 0;
180
+ /* 열 너비 리사이즈(colgroup width)가 반영되려면 fixed여야 한다. */
181
+ table-layout: fixed;
182
+ border-collapse: collapse;
183
+ }
184
+
185
+ .ProseMirror table td,
186
+ .ProseMirror table th {
187
+ /* 열 리사이즈 핸들의 위치 기준 */
188
+ position: relative;
189
+ min-width: 1em;
190
+ padding: 0.5rem 0.75rem;
191
+ border: 1px solid var(--color-neutral200);
192
+ vertical-align: top;
193
+ }
194
+
195
+ .ProseMirror table th {
196
+ background: var(--color-mono100);
197
+ font-weight: 600;
198
+ text-align: left;
199
+ }
200
+
201
+ /* 셀 안 문단은 prose의 블록 여백을 쓰지 않는다 — 셀 높이가 과하게 늘어난다. */
202
+ .ProseMirror table p {
203
+ margin: 0;
204
+ }
205
+
206
+ /* 드래그로 여러 셀을 선택했을 때 */
207
+ .ProseMirror .selectedCell::after {
208
+ content: '';
209
+ position: absolute;
210
+ inset: 0;
211
+ background: rgba(59, 130, 246, 0.15);
212
+ pointer-events: none;
213
+ z-index: 2;
214
+ }
215
+
216
+ /* 열 너비 리사이즈 핸들 (셀 오른쪽 경계) */
217
+ .ProseMirror .column-resize-handle {
218
+ position: absolute;
219
+ top: 0;
220
+ right: -2px;
221
+ bottom: -2px;
222
+ width: 4px;
223
+ background: #3b82f6;
224
+ pointer-events: none;
225
+ }
226
+
227
+ .ProseMirror.resize-cursor {
228
+ cursor: col-resize;
229
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * components.css — 소비처의 Tailwind 컴파일러가 직접 처리하는 raw 컴포넌트 스타일 진입점.
3
+ *
4
+ * `theme.css`(토큰·유틸 정의)의 짝이다. 둘을 함께 import 하면 컴파일된
5
+ * dist/index.css(styles.css) 없이도 LDS 를 전부 쓸 수 있다.
6
+ *
7
+ * @import 'tailwindcss';
8
+ * @import '@loword/loword-design-system/theme.css';
9
+ * @import '@loword/loword-design-system/components.css';
10
+ * @source '<...>/node_modules/@loword/loword-design-system/dist';
11
+ *
12
+ * styles.css 와 함께 쓰지 않는다 — 같은 유틸이 정적 사본으로 중복 출력되고, 그 사본이
13
+ * 소비처가 생성한 변형 유틸(`tablet-down:display16` 등)보다 뒤에 놓여 오버라이드를 막는다.
14
+ *
15
+ * 주의:
16
+ * - `@import 'tailwindcss'`를 넣지 않는다. 소비처가 이미 import 하므로 중복되면 충돌난다.
17
+ * - 토큰·유틸 정의는 포함하지 않는다 — theme.css 가 담당한다.
18
+ * - `@source` 로 dist 를 스캔해야 컴포넌트가 쓰는 클래스가 tree-shaking 되지 않는다.
19
+ */
20
+ @import './components/index.css';
21
+ @import './slider.css';
22
+ @import './carousel.css';
23
+
24
+ @plugin '@tailwindcss/typography';