@ihabdevteam/core 0.215.0 → 0.216.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.
- package/CHANGELOG.md +28 -0
- package/dist/components.cjs.js +178 -178
- package/dist/hooks.cjs.js +1 -1
- package/dist/i18n.cjs.js +1 -1
- package/dist/ihabdevteam-core.cjs.js +182 -182
- package/dist/ihabdevteam-core.d.ts +21 -3
- package/dist/packages/core/src/components/Training/WordTablePopup.d.ts +10 -1
- package/dist/packages/core/src/components/Training/WordTablePopup.js +3 -3
- package/dist/packages/core/src/components/Word/WordTableBlock.d.ts +1 -1
- package/dist/packages/core/src/components/Word/WordTableBlock.js +10 -4
- package/dist/packages/core/src/components/Word/useWordTableDisplaySettings.js +8 -6
- package/dist/packages/core/src/components/Word/wordTableBlockTypes.d.ts +11 -0
- package/dist/packages/core/src/version.d.ts +1 -1
- package/dist/packages/core/src/version.js +1 -1
- package/dist/utils.cjs.js +1 -1
- package/package.json +1 -1
|
@@ -1626,7 +1626,7 @@ export declare function copyText(text: string): Promise<boolean>;
|
|
|
1626
1626
|
*
|
|
1627
1627
|
* 값은 손으로 적고 `test/coreVersion.test.ts` 가 package.json 과 어긋나면 운다.
|
|
1628
1628
|
*/
|
|
1629
|
-
export declare const CORE_VERSION = "0.
|
|
1629
|
+
export declare const CORE_VERSION = "0.216.0";
|
|
1630
1630
|
|
|
1631
1631
|
/** @public */
|
|
1632
1632
|
declare const coreDefault: Record<string, unknown>;
|
|
@@ -10373,7 +10373,7 @@ export declare interface WordSearchResultWord {
|
|
|
10373
10373
|
*/
|
|
10374
10374
|
export declare function WordTable({ title, titleIcon, disc, className, orientation, contentTypes, cutLine, showOutline, showDivLine, items, editCells, count, activeCell, onActivateCell, onRemoveCell, onRemoveItem, onReorder, renderCellAction, showFillerAdd, contentRef, buttonSize, brand, code, pageNumber, pageNumberPosition, fitHeight, scoring, marks, onMarkClick, scoreIndexOffset, }: WordTableProps): JSX.Element;
|
|
10375
10375
|
|
|
10376
|
-
export declare function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }: WordTableBlockProps): JSX.Element;
|
|
10376
|
+
export declare function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, brand, code, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }: WordTableBlockProps): JSX.Element;
|
|
10377
10377
|
|
|
10378
10378
|
/** @public */
|
|
10379
10379
|
export declare interface WordTableBlockProps {
|
|
@@ -10410,6 +10410,16 @@ export declare interface WordTableBlockProps {
|
|
|
10410
10410
|
onFilterCollapsedChange?: (collapsed: boolean) => void;
|
|
10411
10411
|
/** 그 판이 접혀도 머리 오른쪽에 남는 자리 — 요약. 안 주면 코어가 짓는다(`FilterPanel`). */
|
|
10412
10412
|
filterHeaderSummary?: ReactNode;
|
|
10413
|
+
/**
|
|
10414
|
+
* 종이 머리·바닥 띠 — 안쪽 `WordTable` 로 그대로 간다.
|
|
10415
|
+
*
|
|
10416
|
+
* **`show` 가 켜지면 표 설정에 `상단 정보`·`하단 정보` 고르개가 저절로 선다** — 스위치를
|
|
10417
|
+
* 둘로 나누면 부르는 쪽이 어긋나게 줄 수 있어서다(말귀 요청 ㉛, 2026-09-30). 그 고르개로
|
|
10418
|
+
* 켜고 끈 값은 `top`·`bottom` 을 **덮어쓴다** — 화면에서 사람이 고른 것이 마지막 말이다.
|
|
10419
|
+
*/
|
|
10420
|
+
brand?: WordTableProps['brand'];
|
|
10421
|
+
/** 표 번호 — 띠 위 오른쪽에 선다. 안쪽 `WordTable` 로 그대로 간다. */
|
|
10422
|
+
code?: string;
|
|
10413
10423
|
disc?: ReactNode;
|
|
10414
10424
|
/** 현재 표의 저장된 이름(불러온 표 등). 있으면 인쇄/PDF 저장 시 파일명으로 사용, 없으면 "오늘 날짜 + 단어표/대립쌍표" */
|
|
10415
10425
|
tableName?: string;
|
|
@@ -10622,7 +10632,7 @@ export declare type WordTableOrientation = 'landscape' | 'portrait';
|
|
|
10622
10632
|
* 표 내부에는 제목을 두지 않아 팝업 헤더 제목과 중복되지 않는다.
|
|
10623
10633
|
* @public
|
|
10624
10634
|
*/
|
|
10625
|
-
export declare function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring, onScoreChange, printHeader, beforeClose }: WordTablePopupProps): JSX.Element;
|
|
10635
|
+
export declare function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring, onScoreChange, printHeader, brand, code, beforeClose }: WordTablePopupProps): JSX.Element;
|
|
10626
10636
|
|
|
10627
10637
|
/** @public */
|
|
10628
10638
|
export declare interface WordTablePopupActions {
|
|
@@ -10669,6 +10679,14 @@ export declare interface WordTablePopupProps {
|
|
|
10669
10679
|
/** 종이 맨 위에 찍을 한 줄(누구의·언제·무슨 표). 인쇄되는 것은 격자뿐이라
|
|
10670
10680
|
* 이것이 없으면 뽑아 둔 종이에 아무 단서도 안 남는다. */
|
|
10671
10681
|
printHeader?: string;
|
|
10682
|
+
/**
|
|
10683
|
+
* 종이 머리·바닥 띠 — 안쪽 `WordTable` 의 같은 이름 프롭으로 그대로 간다.
|
|
10684
|
+
* **사람이 실제로 인쇄하는 화면은 이 창을 지난다**(미리보기 · 채점지 · 고객 상세 ·
|
|
10685
|
+
* 훈련 더보기) — 여기가 안 흘리면 앱에서 띠를 켤 길이 없다(말귀 요청 ㉛, 2026-09-30).
|
|
10686
|
+
*/
|
|
10687
|
+
brand?: WordTableProps['brand'];
|
|
10688
|
+
/** 표 번호 — 띠 위 오른쪽에 선다. 안쪽 `WordTable` 로 그대로 간다. */
|
|
10689
|
+
code?: string;
|
|
10672
10690
|
/** 닫기 직전에 불린다. false 를 돌려주면 닫지 않는다(채점을 버릴지 묻는 용). */
|
|
10673
10691
|
beforeClose?: PopupProps['beforeClose'];
|
|
10674
10692
|
/** true면 팝업이 열리고 표가 렌더된 직후 인쇄를 1회 자동 시작한다(메뉴 '인쇄하기' 진입용). */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type PopupProps } from '../Popup/Popup';
|
|
3
|
+
import type { WordTableProps } from '../WordTable';
|
|
3
4
|
import type { WordSearchResultItem } from '../../types/wordSearch';
|
|
4
5
|
import { type ScoreMark } from '../Word/wordTableScoring';
|
|
5
6
|
import './WordTablePopup.css';
|
|
@@ -47,6 +48,14 @@ export interface WordTablePopupProps {
|
|
|
47
48
|
/** 종이 맨 위에 찍을 한 줄(누구의·언제·무슨 표). 인쇄되는 것은 격자뿐이라
|
|
48
49
|
* 이것이 없으면 뽑아 둔 종이에 아무 단서도 안 남는다. */
|
|
49
50
|
printHeader?: string;
|
|
51
|
+
/**
|
|
52
|
+
* 종이 머리·바닥 띠 — 안쪽 `WordTable` 의 같은 이름 프롭으로 그대로 간다.
|
|
53
|
+
* **사람이 실제로 인쇄하는 화면은 이 창을 지난다**(미리보기 · 채점지 · 고객 상세 ·
|
|
54
|
+
* 훈련 더보기) — 여기가 안 흘리면 앱에서 띠를 켤 길이 없다(말귀 요청 ㉛, 2026-09-30).
|
|
55
|
+
*/
|
|
56
|
+
brand?: WordTableProps['brand'];
|
|
57
|
+
/** 표 번호 — 띠 위 오른쪽에 선다. 안쪽 `WordTable` 로 그대로 간다. */
|
|
58
|
+
code?: string;
|
|
50
59
|
/** 닫기 직전에 불린다. false 를 돌려주면 닫지 않는다(채점을 버릴지 묻는 용). */
|
|
51
60
|
beforeClose?: PopupProps['beforeClose'];
|
|
52
61
|
/** true면 팝업이 열리고 표가 렌더된 직후 인쇄를 1회 자동 시작한다(메뉴 '인쇄하기' 진입용). */
|
|
@@ -62,4 +71,4 @@ export interface WordTablePopupProps {
|
|
|
62
71
|
* 표 내부에는 제목을 두지 않아 팝업 헤더 제목과 중복되지 않는다.
|
|
63
72
|
* @public
|
|
64
73
|
*/
|
|
65
|
-
export default function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring, onScoreChange, printHeader, beforeClose }: WordTablePopupProps): import("react").JSX.Element;
|
|
74
|
+
export default function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring, onScoreChange, printHeader, brand, code, beforeClose }: WordTablePopupProps): import("react").JSX.Element;
|
|
@@ -19,7 +19,7 @@ import { useToastState } from '../../hooks/useToastState';
|
|
|
19
19
|
* 표 내부에는 제목을 두지 않아 팝업 헤더 제목과 중복되지 않는다.
|
|
20
20
|
* @public
|
|
21
21
|
*/
|
|
22
|
-
export default function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring = false, onScoreChange, printHeader, beforeClose }) {
|
|
22
|
+
export default function WordTablePopup({ items, words, title, subtitle, emptyText, buttons, renderButtons, renderFooter, footerClassName, footerLayout, printFileName, showSettings, autoPrint, className, onClose, scoring = false, onScoreChange, printHeader, brand, code, beforeClose }) {
|
|
23
23
|
const { t } = useTranslation();
|
|
24
24
|
// items 우선, 없으면 문자열 words → 한 단어=한 칸으로 매핑
|
|
25
25
|
const tableItems = useMemo(() => {
|
|
@@ -30,7 +30,7 @@ export default function WordTablePopup({ items, words, title, subtitle, emptyTex
|
|
|
30
30
|
.map((w, i) => ({ id: `${w}-${i}`, words: [{ label: w }] }));
|
|
31
31
|
}, [items, words]);
|
|
32
32
|
// 표 설정(구성·용지 방향·외곽선·페이지당 개수 등) — showSettings일 때만 FilterPanel로 노출하고, 값은 항상 표에 반영한다.
|
|
33
|
-
const { settings, filterSections, filterSelected, handleSelect, pages, isPaginated, pageNumberPosition } = useWordTableDisplaySettings(tableItems);
|
|
33
|
+
const { settings, filterSections, filterSelected, handleSelect, pages, isPaginated, pageNumberPosition } = useWordTableDisplaySettings(tableItems, { paperBands: Boolean(brand?.show) });
|
|
34
34
|
/* 쪽마다 첫 칸이 표 전체에서 몇 번째인지 — 쪽 안에서 0부터 다시 세는 번호를
|
|
35
35
|
표 전체 번호로 옮긴다. */
|
|
36
36
|
const pageStart = useMemo(() => pageStartIndexes(pages.map(p => p.length)), [pages]);
|
|
@@ -115,5 +115,5 @@ export default function WordTablePopup({ items, words, title, subtitle, emptyTex
|
|
|
115
115
|
}, 100);
|
|
116
116
|
return () => window.clearTimeout(id);
|
|
117
117
|
}, [autoPrint]);
|
|
118
|
-
return (_jsxs(Popup, { title: title ?? t('keyWords.title', '주요 단어'), subtitle: subtitle, size: "large", className: cx('word-table-popup', className), buttons: footerButtons, footer: customFooter, footerClassName: footerClassName, footerLayout: footerLayout, beforeClose: beforeClose, onClose: onClose, children: [tableItems.length > 0 ? (_jsxs("div", { className: "word-table-popup__body", children: [showSettings && (_jsx(TableFilterPanel, { sections: filterSections, selected: filterSelected, onSelect: handleSelect })), isPaginated ? (_jsx("div", { className: "word-table-popup__pages", children: pages.map((page, i) => (_jsx(WordTable, { items: page, orientation: settings.orientation, contentTypes: settings.contentTypes, cutLine: settings.cutLine, showOutline: settings.showOutline, showDivLine: settings.showDivLine, count: settings.count, contentRef: el => { pageRefs.current[i] = el; }, pageNumber: { current: i + 1, total: pages.length }, pageNumberPosition: pageNumberPosition, scoring: scoring, scoreIndexOffset: pageStart[i], marks: 표에줄채점, onMarkClick: handleMarkClick }, i))) })) : (_jsx("div", { className: "word-table-popup__table", children: _jsx(WordTable, { items: tableItems, orientation: settings.orientation, contentTypes: settings.contentTypes, cutLine: settings.cutLine, showOutline: settings.showOutline, showDivLine: settings.showDivLine, count: settings.count, contentRef: contentRef, fitHeight: true, scoring: scoring, marks: 표에줄채점, onMarkClick: handleMarkClick }) }))] })) : (_jsx("p", { className: "word-table-popup__empty body-3", children: emptyText ?? t('keyWords.empty', '추출된 주요 단어가 없습니다.') })), _jsx(Toast, { message: toastMsg, position: "top", onClose: handleToastClose }, toastKey)] }));
|
|
118
|
+
return (_jsxs(Popup, { title: title ?? t('keyWords.title', '주요 단어'), subtitle: subtitle, size: "large", className: cx('word-table-popup', className), buttons: footerButtons, footer: customFooter, footerClassName: footerClassName, footerLayout: footerLayout, beforeClose: beforeClose, onClose: onClose, children: [tableItems.length > 0 ? (_jsxs("div", { className: "word-table-popup__body", children: [showSettings && (_jsx(TableFilterPanel, { sections: filterSections, selected: filterSelected, onSelect: handleSelect })), isPaginated ? (_jsx("div", { className: "word-table-popup__pages", children: pages.map((page, i) => (_jsx(WordTable, { items: page, orientation: settings.orientation, contentTypes: settings.contentTypes, cutLine: settings.cutLine, showOutline: settings.showOutline, showDivLine: settings.showDivLine, count: settings.count, contentRef: el => { pageRefs.current[i] = el; }, pageNumber: { current: i + 1, total: pages.length }, pageNumberPosition: pageNumberPosition, brand: brand && { ...brand, top: settings.showTopInfo, bottom: settings.showBottomInfo }, code: code, scoring: scoring, scoreIndexOffset: pageStart[i], marks: 표에줄채점, onMarkClick: handleMarkClick }, i))) })) : (_jsx("div", { className: "word-table-popup__table", children: _jsx(WordTable, { items: tableItems, orientation: settings.orientation, contentTypes: settings.contentTypes, cutLine: settings.cutLine, showOutline: settings.showOutline, showDivLine: settings.showDivLine, count: settings.count, contentRef: contentRef, fitHeight: true, scoring: scoring, marks: 표에줄채점, onMarkClick: handleMarkClick, brand: brand && { ...brand, top: settings.showTopInfo, bottom: settings.showBottomInfo }, code: code }) }))] })) : (_jsx("p", { className: "word-table-popup__empty body-3", children: emptyText ?? t('keyWords.empty', '추출된 주요 단어가 없습니다.') })), _jsx(Toast, { message: toastMsg, position: "top", onClose: handleToastClose }, toastKey)] }));
|
|
119
119
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import './WordTableBlock.css';
|
|
2
2
|
import type { WordTableBlockProps } from './wordTableBlockTypes';
|
|
3
3
|
export type { WordEntry, WordTableBlockProps } from './wordTableBlockTypes';
|
|
4
|
-
export default function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }: WordTableBlockProps): import("react").JSX.Element;
|
|
4
|
+
export default function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, brand, code, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }: WordTableBlockProps): import("react").JSX.Element;
|
|
@@ -45,7 +45,7 @@ function 겹치지않는id(list) {
|
|
|
45
45
|
return id === it.id ? it : { ...it, id };
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
export default function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }) {
|
|
48
|
+
export default function WordTableBlock({ title, titleIcon, disc, filterTitle, filterCollapsible, filterDefaultCollapsed, filterCollapsed, onFilterCollapsedChange, filterHeaderSummary, brand, code, items, onSaveComplete, onLoad, onRemoveItem, onReset, resetLabel, saveButtonLabel, secondarySaveButtonLabel, onReorder, showCellCount, onAddItem, className, renderSavePopup, renderWordSearch, hideControls, saveOnly, tableName, nameValue, onNameChange, descriptionValue, onDescriptionChange, namePlaceholder, descriptionPlaceholder, existingNames, editingName, onCancel, initialItemsPerPage, renderCellAction, actionsLeftExtra }) {
|
|
49
49
|
const { t } = useTranslation();
|
|
50
50
|
const resolvedResetLabel = resetLabel ?? t('wordPrint.clearAllSelection', '모두 선택 해제');
|
|
51
51
|
const isEditable = items === undefined;
|
|
@@ -76,6 +76,12 @@ export default function WordTableBlock({ title, titleIcon, disc, filterTitle, fi
|
|
|
76
76
|
const [cellCount, setCellCount] = useState(4);
|
|
77
77
|
const [activeCell, setActiveCell] = useState(null);
|
|
78
78
|
const visibleCells = cells.slice(0, cellCount);
|
|
79
|
+
/* 띠를 켠 표면 설정 판에 '상단 정보'·'하단 정보' 고르개가 선다 — 스위치를 따로 두지
|
|
80
|
+
않는다(부르는 쪽이 둘을 어긋나게 줄 일이 없게). 고른 값은 `brand.top`·`bottom` 을 덮는다. */
|
|
81
|
+
const 띠쓰나 = Boolean(brand?.show);
|
|
82
|
+
const [showTopInfo, setShowTopInfo] = useState(true);
|
|
83
|
+
const [showBottomInfo, setShowBottomInfo] = useState(true);
|
|
84
|
+
const 띠 = brand && { ...brand, top: showTopInfo, bottom: showBottomInfo };
|
|
79
85
|
// 공통 단어 표 설정 상태
|
|
80
86
|
const [orientation, setOrientation] = useState('landscape');
|
|
81
87
|
const [contentTypes, setContentTypes] = useState(['이미지', '단어', '표준 발음']);
|
|
@@ -320,15 +326,15 @@ export default function WordTableBlock({ title, titleIcon, disc, filterTitle, fi
|
|
|
320
326
|
setActiveCell(null);
|
|
321
327
|
},
|
|
322
328
|
onClose: handleCloseWordSearch,
|
|
323
|
-
}), !hideControls && (_jsx(TableFilterPanel, { title: filterTitle, collapsible: filterCollapsible, defaultCollapsed: filterDefaultCollapsed, collapsed: filterCollapsed, onCollapsedChange: onFilterCollapsedChange, headerSummary: filterHeaderSummary, hasImage: hasImage, hasColloquial: hasColloquial, contentTypes: contentTypes, orientation: orientation, showOutline: showOutline, cutLine: cutLine, showDivLine: showDivLine, setters: { setContentTypes, setOrientation, setShowOutline, setCutLine, setShowDivLine }, showCutLine: (pagesEnabled ? itemsPerPage : count) > 1, showDivLine2: hasPairs, middleSections: middleSections, extraSelected: middleSelected, onExtraSelect: handleMiddleSelect })), isPaginated && pages ? (_jsx("div", { className: "word-table-block__pages", children: pages.map((page, i) => (_jsx(WordTable, { orientation: orientation, contentTypes: contentTypes, cutLine: cutLine, showOutline: showOutline, showDivLine: showDivLine, count: itemsPerPage, items: page, onRemoveItem: onRemoveItem,
|
|
329
|
+
}), !hideControls && (_jsx(TableFilterPanel, { title: filterTitle, collapsible: filterCollapsible, defaultCollapsed: filterDefaultCollapsed, collapsed: filterCollapsed, onCollapsedChange: onFilterCollapsedChange, headerSummary: filterHeaderSummary, hasImage: hasImage, hasColloquial: hasColloquial, contentTypes: contentTypes, orientation: orientation, showOutline: showOutline, cutLine: cutLine, showDivLine: showDivLine, setters: { setContentTypes, setOrientation, setShowOutline, setCutLine, setShowDivLine, setShowTopInfo, setShowBottomInfo }, showCutLine: (pagesEnabled ? itemsPerPage : count) > 1, showDivLine2: hasPairs, middleSections: middleSections, extraSelected: middleSelected, onExtraSelect: handleMiddleSelect, showPaperBands: 띠쓰나, showTopInfo: showTopInfo, showBottomInfo: showBottomInfo })), isPaginated && pages ? (_jsx("div", { className: "word-table-block__pages", children: pages.map((page, i) => (_jsx(WordTable, { orientation: orientation, contentTypes: contentTypes, cutLine: cutLine, showOutline: showOutline, showDivLine: showDivLine, count: itemsPerPage, items: page, onRemoveItem: onRemoveItem,
|
|
324
330
|
/* 쪽이 나뉘면 끌어 옮기기가 통째로 꺼졌다(말귀 단어 찾기: 9개부터). 쪽 안의 자리를 전체 자리로 옮겨 넘긴다 —
|
|
325
331
|
쪽을 넘는 이동은 하지 않는다. */
|
|
326
332
|
onReorder: onReorder && ((from, to) => onReorder(from + i * itemsPerPage, to + i * itemsPerPage)),
|
|
327
333
|
/* 안쪽 표는 제 쪽 안의 번호를 준다 — 부르는 쪽에는 **표 전체 기준**으로 넘긴다
|
|
328
334
|
(위 `onReorder` 와 같은 셈이다. 쪽이 몇으로 나뉘었는지는 부르는 쪽 일이 아니다). */
|
|
329
|
-
renderCellAction: renderCellAction && ((n, item) => renderCellAction(n + i * itemsPerPage, item)), contentRef: el => { pageRefs.current[i] = el; }, pageNumber: { current: i + 1, total: pages.length }, pageNumberPosition: pageNumberPosition }, i))) })) : (_jsx(WordTable, { orientation: orientation, contentTypes: contentTypes, cutLine: cutLine, showOutline: showOutline, showDivLine: showDivLine, count: count, items: isEditable ? undefined : (items ?? []), editCells: isEditable ? visibleCells : undefined, activeCell: activeCell, onActivateCell: (isEditable || onAddItem) ? setActiveCell : undefined, onRemoveCell: isEditable ? handleRemove : undefined, onRemoveItem: !isEditable ? onRemoveItem : undefined, onReorder: !isEditable ? onReorder : undefined,
|
|
335
|
+
renderCellAction: renderCellAction && ((n, item) => renderCellAction(n + i * itemsPerPage, item)), brand: 띠, code: code, contentRef: el => { pageRefs.current[i] = el; }, pageNumber: { current: i + 1, total: pages.length }, pageNumberPosition: pageNumberPosition }, i))) })) : (_jsx(WordTable, { orientation: orientation, contentTypes: contentTypes, cutLine: cutLine, showOutline: showOutline, showDivLine: showDivLine, count: count, items: isEditable ? undefined : (items ?? []), editCells: isEditable ? visibleCells : undefined, activeCell: activeCell, onActivateCell: (isEditable || onAddItem) ? setActiveCell : undefined, onRemoveCell: isEditable ? handleRemove : undefined, onRemoveItem: !isEditable ? onRemoveItem : undefined, onReorder: !isEditable ? onReorder : undefined,
|
|
330
336
|
/* 편집 모드에는 얹을 항목이 없다 — 칸을 손으로 채우는 꼴이다 */
|
|
331
|
-
renderCellAction: !isEditable ? renderCellAction : undefined, showFillerAdd: !!onAddItem, contentRef: contentRef })), inlineNameFields && !hideControls && (_jsxs(Panel, { size: "medium", labelWidth: 64, useBorder: false, useRowBorder: false, className: "word-table-block__meta", children: [_jsx(PanelRow, { variant: "custom", label: t('wordTable.save.nameLabel', '이름'), required: true, align: "vertical", useFullWidth: true, children: _jsx(TextField, { required: true, value: nameValue ?? '', onChange: onNameChange, placeholder: namePlaceholder ? namePlaceholder + t('wordTable.save.autoFillHint', ' (Tab 또는 space 입력시 자동 입력)') : t('wordTable.save.placeholder', '이 단어표에 대한 제목을 입력하세요.'),
|
|
337
|
+
renderCellAction: !isEditable ? renderCellAction : undefined, brand: 띠, code: code, showFillerAdd: !!onAddItem, contentRef: contentRef })), inlineNameFields && !hideControls && (_jsxs(Panel, { size: "medium", labelWidth: 64, useBorder: false, useRowBorder: false, className: "word-table-block__meta", children: [_jsx(PanelRow, { variant: "custom", label: t('wordTable.save.nameLabel', '이름'), required: true, align: "vertical", useFullWidth: true, children: _jsx(TextField, { required: true, value: nameValue ?? '', onChange: onNameChange, placeholder: namePlaceholder ? namePlaceholder + t('wordTable.save.autoFillHint', ' (Tab 또는 space 입력시 자동 입력)') : t('wordTable.save.placeholder', '이 단어표에 대한 제목을 입력하세요.'),
|
|
332
338
|
/* PanelRow의 라벨은 시각적으로만 붙어 있고 입력과 연결돼 있지 않아, 낭독기에는
|
|
333
339
|
이름 없는 입력으로 읽혔다. placeholder는 자동완성 안내문("Tab 또는 space…")이
|
|
334
340
|
섞여 있어 이름으로 부적절하므로 같은 라벨 문구를 넘긴다. */
|
|
@@ -3,7 +3,7 @@ import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { chunkItems } from '../wordTableLayout';
|
|
5
5
|
import { getImageResolver, checkImageExists } from '../../utils/imageConfig';
|
|
6
|
-
import { buildCompositionSection, buildOrientationSection, buildBorderSection, buildCutLineSection, buildDivLineSection,
|
|
6
|
+
import { buildCompositionSection, buildOrientationSection, buildBorderSection, buildCutLineSection, buildDivLineSection, buildTopInfoSection, buildBottomInfoSection, buildItemsPerPageSection, buildTableSettingsSelected, applyTableSettingsSelect, PAGE_NUM_POSITION_VALUE, parsePageNumberPosition, itemsPerPageFromChoice, } from './wordTableSettings';
|
|
7
7
|
/**
|
|
8
8
|
* 표시 전용 단어표(편집 없음)의 '표 설정' FilterPanel 상태·섹션을 제공하는 훅.
|
|
9
9
|
* 구성·용지 방향·외곽선, 내용이 있으면 페이지당 개수, 2페이지 이상이면 페이지 번호, 항목이 2개 이상이면
|
|
@@ -61,11 +61,13 @@ opts) {
|
|
|
61
61
|
buildOrientationSection(t),
|
|
62
62
|
// 내용이 있는(1개 이상) 표면 페이지당 개수를 항상 노출.
|
|
63
63
|
...(itemCount > 0 ? [buildItemsPerPageSection(t, { hasPairs, itemCount })] : []),
|
|
64
|
-
/* '페이지 번호' 자리 고르개는
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
/* **'페이지 번호' 자리 고르개는 없앤다** — 띠를 쓰든 안 쓰든 아예 안 세운다.
|
|
65
|
+
사용자 지시다(2026-09-30). `pageNumberPosition` 프롭은 남아 있어 부르는 쪽이 코드로
|
|
66
|
+
자리를 정할 수는 있고, 다만 화면에서 고르게 하지 않는다.
|
|
67
|
+
|
|
68
|
+
**한 번 되돌렸다가 다시 걷었다.** 0.215.0 에서 '띠를 안 쓰는 화면의 회귀' 로 보고
|
|
69
|
+
조건을 달아 되살렸는데, 그 판단의 바탕이 된 보고가 틀렸다(한 쪽짜리 표라 안 보였던
|
|
70
|
+
것을 사라진 것으로 읽었다). 없애는 것이 본래 지시였다 — 다시 되살리지 말 것. */
|
|
69
71
|
buildBorderSection(t),
|
|
70
72
|
...(count > 1 ? [buildCutLineSection(t)] : []),
|
|
71
73
|
...(hasPairs ? [buildDivLineSection(t)] : []),
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* WordTableBlock의 순수 타입 및 인터페이스 정의.
|
|
4
4
|
*/
|
|
5
5
|
import type { ReactNode } from 'react';
|
|
6
|
+
import type { WordTableProps } from '../WordTable';
|
|
6
7
|
import type { WordSearchResultItem } from './WordSearchResultBlock';
|
|
7
8
|
export interface WordEntry {
|
|
8
9
|
word: string;
|
|
@@ -49,6 +50,16 @@ export interface WordTableBlockProps {
|
|
|
49
50
|
onFilterCollapsedChange?: (collapsed: boolean) => void;
|
|
50
51
|
/** 그 판이 접혀도 머리 오른쪽에 남는 자리 — 요약. 안 주면 코어가 짓는다(`FilterPanel`). */
|
|
51
52
|
filterHeaderSummary?: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* 종이 머리·바닥 띠 — 안쪽 `WordTable` 로 그대로 간다.
|
|
55
|
+
*
|
|
56
|
+
* **`show` 가 켜지면 표 설정에 `상단 정보`·`하단 정보` 고르개가 저절로 선다** — 스위치를
|
|
57
|
+
* 둘로 나누면 부르는 쪽이 어긋나게 줄 수 있어서다(말귀 요청 ㉛, 2026-09-30). 그 고르개로
|
|
58
|
+
* 켜고 끈 값은 `top`·`bottom` 을 **덮어쓴다** — 화면에서 사람이 고른 것이 마지막 말이다.
|
|
59
|
+
*/
|
|
60
|
+
brand?: WordTableProps['brand'];
|
|
61
|
+
/** 표 번호 — 띠 위 오른쪽에 선다. 안쪽 `WordTable` 로 그대로 간다. */
|
|
62
|
+
code?: string;
|
|
52
63
|
disc?: ReactNode;
|
|
53
64
|
/** 현재 표의 저장된 이름(불러온 표 등). 있으면 인쇄/PDF 저장 시 파일명으로 사용, 없으면 "오늘 날짜 + 단어표/대립쌍표" */
|
|
54
65
|
tableName?: string;
|