@ihabdevteam/core 0.213.0 → 0.215.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.
@@ -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.213.0";
1629
+ export declare const CORE_VERSION = "0.215.0";
1630
1630
 
1631
1631
  /** @public */
1632
1632
  declare const coreDefault: Record<string, unknown>;
@@ -7332,6 +7332,10 @@ declare interface TableFilterPanelSmartProps extends TableFilterPanelBaseProps {
7332
7332
  showCutLine?: boolean;
7333
7333
  /** 구분선 섹션 노출 여부 — 대립쌍표 등 짝이 있는 표에서만(호출부가 판단). */
7334
7334
  showDivLine2?: boolean;
7335
+ /** 상단·하단 정보(종이 머리·바닥 띠) 절을 세운다 — 띠를 쓰는 화면에서만(호출부가 판단). */
7336
+ showPaperBands?: boolean;
7337
+ showTopInfo?: boolean;
7338
+ showBottomInfo?: boolean;
7335
7339
  /** 용지 방향과 외곽선 사이에 끼워 넣을 추가 섹션 — 칸 수/페이지당 개수/페이지 번호 등, 호출부 전용이라 직접 구성해 넘긴다. */
7336
7340
  middleSections?: FilterPanelSection[];
7337
7341
  /** middleSections의 현재 선택값. */
@@ -7458,6 +7462,8 @@ declare interface TableSettingsSetters {
7458
7462
  setShowOutline: (v: boolean) => void;
7459
7463
  setCutLine: (v: WordTableCutLine) => void;
7460
7464
  setShowDivLine: (v: boolean) => void;
7465
+ setShowTopInfo?: (v: boolean) => void;
7466
+ setShowBottomInfo?: (v: boolean) => void;
7461
7467
  }
7462
7468
 
7463
7469
  /** `useTableSort` 의 선택 인자. @public */
@@ -9747,7 +9753,12 @@ export declare function useWordMeanings(rows: {
9747
9753
  * WordTablePopup 등 표를 미리 보여주고 인쇄하는 곳에서 쓴다.
9748
9754
  * @public
9749
9755
  */
9750
- export declare function useWordTableDisplaySettings(items: WordSearchResultItem[]): UseWordTableDisplaySettingsResult;
9756
+ export declare function useWordTableDisplaySettings(items: WordSearchResultItem[],
9757
+ /** 종이 머리·바닥 띠를 쓰는 화면이면 참 — '상단 정보'·'하단 정보' 절이 함께 선다.
9758
+ * 안 쓰는 화면에 켜고 끌 것이 없는 절이 서면 안 되므로 기본은 거짓이다. */
9759
+ opts?: {
9760
+ paperBands?: boolean;
9761
+ }): UseWordTableDisplaySettingsResult;
9751
9762
 
9752
9763
  /** @public */
9753
9764
  export declare interface UseWordTableDisplaySettingsResult {
@@ -10585,6 +10596,10 @@ export declare interface WordTableDisplaySettings {
10585
10596
  contentTypes: WordTableContentType[];
10586
10597
  cutLine: WordTableCutLine;
10587
10598
  showOutline: boolean;
10599
+ /** 종이 머리 띠(로고·표 번호)를 찍나 */
10600
+ showTopInfo: boolean;
10601
+ /** 종이 바닥 띠(만든 곳·주소·쪽 번호)를 찍나 */
10602
+ showBottomInfo: boolean;
10588
10603
  showDivLine: boolean;
10589
10604
  /** 표 칸 수(= 페이지당 개수, 최소 1). */
10590
10605
  count: number;
@@ -10757,10 +10772,18 @@ export declare interface WordTableProps {
10757
10772
  brand?: {
10758
10773
  /** 로고와 저작권을 세운다. 나머지 자리는 각자 값이 있을 때만 선다. */
10759
10774
  show?: boolean;
10775
+ /** 위 띠만 끈다(`show` 가 켜져 있을 때). 표 설정의 '상단 정보' 가 이것을 움직인다. */
10776
+ top?: boolean;
10777
+ /** 아래 띠만 끈다(`show` 가 켜져 있을 때). 표 설정의 '하단 정보' 가 이것을 움직인다. */
10778
+ bottom?: boolean;
10760
10779
  /**
10761
10780
  * 아래 오른쪽 — **이 표로 가는 주소**. 회사 홈 주소가 아니라 그 표의 공유 링크다
10762
10781
  * (사용자 지시 2026-09-30). 종이를 든 사람이 이 주소로 같은 표를 화면에서 연다.
10763
10782
  *
10783
+ * **`code` 와는 다른 것이다.** 표 번호는 기관 안에서 매긴 번호고 이 주소는 따로 난
10784
+ * 공유 링크다 — 번호에서 주소를 만들어 내지 않는다. 둘 다 이 표를 가리키지만 나오는
10785
+ * 데가 다르므로 각각 받는다.
10786
+ *
10764
10787
  * 종이라 누를 수 없으니 글자 그대로 찍는다 — 그래서 **사람이 옮겨 칠 수 있는 길이**
10765
10788
  * 여야 한다. 긴 주소를 그대로 주면 넘쳐 …로 잘리고, 잘린 주소는 옮겨 칠 수 없다.
10766
10789
  * 짧은 주소를 쓰거나, 표 번호로 찾는 길을 함께 두는 편이 낫다.
@@ -10768,6 +10791,15 @@ export declare interface WordTableProps {
10768
10791
  link?: string;
10769
10792
  /** 저작권 글월 — 안 주면 `© IHAB, Inc. All rights reserved.` */
10770
10793
  copyright?: string;
10794
+ /** 위 오른쪽 맨 앞 — **이 표의 이름**. `표 제목 · 기관 이름 · 표 번호` 로 선다. */
10795
+ title?: string;
10796
+ /**
10797
+ * 위 오른쪽 — **표 번호 앞에 붙는 기관 이름**(말귀매니저). 번호는 그 기관 안에서만
10798
+ * 고유하므로 이름과 함께여야 어느 곳의 몇 번인지가 정해진다(사용자 지시 2026-09-30).
10799
+ * `이름 · 번호` 로 선다. 이름이 길면 이름만 줄고 번호는 안 줄인다 — 번호가 잘리면
10800
+ * 확인 글자가 사라져 뜻이 없다.
10801
+ */
10802
+ owner?: string;
10771
10803
  };
10772
10804
  /**
10773
10805
  * **짧은 식별 글** — 표 번호(`1043-E`). `brand` 를 줬을 때 위 오른쪽에 선다.
@@ -45,6 +45,10 @@ export interface TableFilterPanelSmartProps extends TableFilterPanelBaseProps {
45
45
  showCutLine?: boolean;
46
46
  /** 구분선 섹션 노출 여부 — 대립쌍표 등 짝이 있는 표에서만(호출부가 판단). */
47
47
  showDivLine2?: boolean;
48
+ /** 상단·하단 정보(종이 머리·바닥 띠) 절을 세운다 — 띠를 쓰는 화면에서만(호출부가 판단). */
49
+ showPaperBands?: boolean;
50
+ showTopInfo?: boolean;
51
+ showBottomInfo?: boolean;
48
52
  /** 용지 방향과 외곽선 사이에 끼워 넣을 추가 섹션 — 칸 수/페이지당 개수/페이지 번호 등, 호출부 전용이라 직접 구성해 넘긴다. */
49
53
  middleSections?: FilterPanelSection[];
50
54
  /** middleSections의 현재 선택값. */
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import FilterPanel from '../FilterPanel';
5
- import { buildCompositionSection, buildOrientationSection, buildBorderSection, buildCutLineSection, buildDivLineSection, buildTableSettingsSelected, applyTableSettingsSelect, } from './wordTableSettings';
5
+ import { buildCompositionSection, buildOrientationSection, buildBorderSection, buildCutLineSection, buildDivLineSection, buildTopInfoSection, buildBottomInfoSection, buildTableSettingsSelected, applyTableSettingsSelect, } from './wordTableSettings';
6
6
  function isShellProps(props) {
7
7
  return 'sections' in props;
8
8
  }
@@ -22,7 +22,7 @@ export default function TableFilterPanel(props) {
22
22
  if (isShellProps(props)) {
23
23
  return (_jsx(FilterPanel, { className: className, title: title ?? t('wordTable.filterTitle', '표 설정'), sections: props.sections, selected: props.selected, onSelect: props.onSelect, ...접기, align: "inline" }));
24
24
  }
25
- const { hasImage, hasColloquial, contentTypes, orientation, showOutline, cutLine, showDivLine, setters, showCutLine = false, showDivLine2 = false, middleSections = [], extraSelected = {}, onExtraSelect, } = props;
25
+ const { hasImage, hasColloquial, contentTypes, orientation, showOutline, cutLine, showDivLine, setters, showCutLine = false, showDivLine2 = false, middleSections = [], extraSelected = {}, onExtraSelect, showPaperBands = false, showTopInfo = true, showBottomInfo = true, } = props;
26
26
  const sections = [
27
27
  buildCompositionSection(t, { hasImage, hasColloquial }),
28
28
  buildOrientationSection(t),
@@ -30,9 +30,11 @@ export default function TableFilterPanel(props) {
30
30
  buildBorderSection(t),
31
31
  ...(showCutLine ? [buildCutLineSection(t)] : []),
32
32
  ...(showDivLine2 ? [buildDivLineSection(t)] : []),
33
+ /* 띠를 쓰는 화면에서만 — 안 쓰는 표에 켜고 끌 것이 없는 절이 서면 안 된다 */
34
+ ...(showPaperBands ? [buildTopInfoSection(t), buildBottomInfoSection(t)] : []),
33
35
  ];
34
36
  const selected = {
35
- ...buildTableSettingsSelected(t, { contentTypes, orientation, showOutline, cutLine, showDivLine }),
37
+ ...buildTableSettingsSelected(t, { contentTypes, orientation, showOutline, cutLine, showDivLine, showTopInfo, showBottomInfo }),
36
38
  ...extraSelected,
37
39
  };
38
40
  const onSelect = (value, sectionLabel) => {
@@ -196,6 +196,8 @@ export default function WordTableBlock({ title, titleIcon, disc, filterTitle, fi
196
196
  ...((isEditable || showCellCount) ? [{ label: t('wordTable.filter.columns', '칸 수'), items: CELL_COUNTS.map(n => ({ value: `${n}칸`, displayLabel: t('wordTable.filter.column', { count: n }) })), display: 'segmented' }] : []),
197
197
  // 내용이 있는(1개 이상) 표면 '페이지당 대립쌍/단어 수'를 항상 노출한다(표시 모드 한정).
198
198
  ...(pagesEnabled && (items?.length ?? 0) > 0 ? [buildItemsPerPageSection(t, { hasPairs, itemCount })] : []),
199
+ /* 이 블록은 종이 띠를 안 받는다 — 쪽 번호가 설 데가 여기뿐이라 자리 고르개를 그대로 둔다
200
+ (띠를 쓰는 `WordTable` 쪽만 이 절을 걷는다). */
199
201
  ...(isPaginated ? [buildPageNumberSection(t)] : []),
200
202
  ], [t, isEditable, showCellCount, pagesEnabled, items?.length, hasPairs, itemCount, isPaginated]);
201
203
  const middleSelected = {
@@ -7,6 +7,10 @@ export interface WordTableDisplaySettings {
7
7
  contentTypes: WordTableContentType[];
8
8
  cutLine: WordTableCutLine;
9
9
  showOutline: boolean;
10
+ /** 종이 머리 띠(로고·표 번호)를 찍나 */
11
+ showTopInfo: boolean;
12
+ /** 종이 바닥 띠(만든 곳·주소·쪽 번호)를 찍나 */
13
+ showBottomInfo: boolean;
10
14
  showDivLine: boolean;
11
15
  /** 표 칸 수(= 페이지당 개수, 최소 1). */
12
16
  count: number;
@@ -32,4 +36,9 @@ export interface UseWordTableDisplaySettingsResult {
32
36
  * WordTablePopup 등 표를 미리 보여주고 인쇄하는 곳에서 쓴다.
33
37
  * @public
34
38
  */
35
- export declare function useWordTableDisplaySettings(items: WordSearchResultItem[]): UseWordTableDisplaySettingsResult;
39
+ export declare function useWordTableDisplaySettings(items: WordSearchResultItem[],
40
+ /** 종이 머리·바닥 띠를 쓰는 화면이면 참 — '상단 정보'·'하단 정보' 절이 함께 선다.
41
+ * 안 쓰는 화면에 켜고 끌 것이 없는 절이 서면 안 되므로 기본은 거짓이다. */
42
+ opts?: {
43
+ paperBands?: boolean;
44
+ }): UseWordTableDisplaySettingsResult;
@@ -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, buildItemsPerPageSection, buildPageNumberSection, buildTableSettingsSelected, applyTableSettingsSelect, PAGE_NUM_POSITION_VALUE, parsePageNumberPosition, itemsPerPageFromChoice, } from './wordTableSettings';
6
+ import { buildCompositionSection, buildOrientationSection, buildBorderSection, buildCutLineSection, buildDivLineSection, buildPageNumberSection, buildTopInfoSection, buildBottomInfoSection, buildItemsPerPageSection, buildTableSettingsSelected, applyTableSettingsSelect, PAGE_NUM_POSITION_VALUE, parsePageNumberPosition, itemsPerPageFromChoice, } from './wordTableSettings';
7
7
  /**
8
8
  * 표시 전용 단어표(편집 없음)의 '표 설정' FilterPanel 상태·섹션을 제공하는 훅.
9
9
  * 구성·용지 방향·외곽선, 내용이 있으면 페이지당 개수, 2페이지 이상이면 페이지 번호, 항목이 2개 이상이면
@@ -11,12 +11,19 @@ import { buildCompositionSection, buildOrientationSection, buildBorderSection, b
11
11
  * WordTablePopup 등 표를 미리 보여주고 인쇄하는 곳에서 쓴다.
12
12
  * @public
13
13
  */
14
- export function useWordTableDisplaySettings(items) {
14
+ export function useWordTableDisplaySettings(items,
15
+ /** 종이 머리·바닥 띠를 쓰는 화면이면 참 — '상단 정보'·'하단 정보' 절이 함께 선다.
16
+ * 안 쓰는 화면에 켜고 끌 것이 없는 절이 서면 안 되므로 기본은 거짓이다. */
17
+ opts) {
15
18
  const { t } = useTranslation();
19
+ const 띠쓰나 = opts?.paperBands === true;
16
20
  const [orientation, setOrientation] = useState('landscape');
17
21
  const [contentTypes, setContentTypes] = useState(['이미지', '단어', '표준 발음']);
18
22
  const [cutLine, setCutLine] = useState('표시');
19
23
  const [showOutline, setShowOutline] = useState(true);
24
+ /* 종이 머리·바닥 띠 — 기본은 켬(브랜드가 찍힌 종이가 기본값이다) */
25
+ const [showTopInfo, setShowTopInfo] = useState(true);
26
+ const [showBottomInfo, setShowBottomInfo] = useState(true);
20
27
  const [showDivLine, setShowDivLine] = useState(true);
21
28
  const [itemsPerPageSetting, setItemsPerPageSetting] = useState(8);
22
29
  const [pageNumberPosition, setPageNumberPosition] = useState('right');
@@ -54,19 +61,25 @@ export function useWordTableDisplaySettings(items) {
54
61
  buildOrientationSection(t),
55
62
  // 내용이 있는(1개 이상) 표면 페이지당 개수를 항상 노출.
56
63
  ...(itemCount > 0 ? [buildItemsPerPageSection(t, { hasPairs, itemCount })] : []),
57
- ...(isPaginated ? [buildPageNumberSection(t)] : []),
64
+ /* '페이지 번호' 자리 고르개는 **띠를 켠 화면에서만** 걷는다(사용자 지시 2026-09-30) —
65
+ 거기서는 쪽 번호가 바닥 띠 오른쪽에 고정으로 서므로 고를 자리가 없다. 띠를 안 쓰는
66
+ 화면은 전과 똑같아야 한다: 한때 조건 없이 걷었는데, 그러면 이 기능을 쓰던 화면에서
67
+ 절이 통째로 사라진다(말귀가 깔기 전에 짚었다, 2026-09-30). */
68
+ ...(!띠쓰나 && isPaginated ? [buildPageNumberSection(t)] : []),
58
69
  buildBorderSection(t),
59
70
  ...(count > 1 ? [buildCutLineSection(t)] : []),
60
71
  ...(hasPairs ? [buildDivLineSection(t)] : []),
61
- ], [t, hasImage, hasColloquial, itemCount, hasPairs, isPaginated, count]);
72
+ /* 띠를 쓰는 화면에서만 — 안 쓰는 표에 켜고 끌 것이 없는 절이 서면 안 된다 */
73
+ ...(띠쓰나 ? [buildTopInfoSection(t), buildBottomInfoSection(t)] : []),
74
+ ], [t, hasImage, hasColloquial, itemCount, hasPairs, isPaginated, count, 띠쓰나]);
62
75
  const filterSelected = {
63
- ...buildTableSettingsSelected(t, { contentTypes, orientation, showOutline, cutLine, showDivLine }),
76
+ ...buildTableSettingsSelected(t, { contentTypes, orientation, showOutline, cutLine, showDivLine, showTopInfo, showBottomInfo }),
64
77
  ...(itemCount > 0 ? { [t(hasPairs ? 'wordTable.filter.itemsPerPagePair' : 'wordTable.filter.itemsPerPageWord')]: `${effectiveItemsPerPage}개` } : {}),
65
78
  ...(isPaginated ? { [t('wordTable.filter.pageNumber', '페이지 번호')]: PAGE_NUM_POSITION_VALUE[pageNumberPosition] } : {}),
66
79
  };
67
80
  const handleSelect = useCallback((value, sectionLabel) => {
68
81
  // 기본 5개 설정은 공용 헬퍼가 처리 — 처리했으면 종료. 나머지(페이지당 개수·페이지 번호)만 여기서.
69
- if (applyTableSettingsSelect(t, value, sectionLabel, { setContentTypes, setOrientation, setShowOutline, setCutLine, setShowDivLine }))
82
+ if (applyTableSettingsSelect(t, value, sectionLabel, { setContentTypes, setOrientation, setShowOutline, setCutLine, setShowDivLine, setShowTopInfo, setShowBottomInfo }))
70
83
  return;
71
84
  if (sectionLabel === t('wordTable.filter.itemsPerPagePair', '페이지당 대립쌍 수') || sectionLabel === t('wordTable.filter.itemsPerPageWord', '페이지당 단어 수')) {
72
85
  setItemsPerPageSetting(itemsPerPageFromChoice(parseInt(value), itemCount));
@@ -76,7 +89,7 @@ export function useWordTableDisplaySettings(items) {
76
89
  }
77
90
  }, [t, itemCount]);
78
91
  return {
79
- settings: { orientation, contentTypes, cutLine, showOutline, showDivLine, count },
92
+ settings: { orientation, contentTypes, cutLine, showOutline, showDivLine, count, showTopInfo, showBottomInfo },
80
93
  filterSections, filterSelected, handleSelect,
81
94
  pages, isPaginated, pageNumberPosition,
82
95
  };
@@ -17,6 +17,10 @@ export declare function buildCompositionSection(t: TFunction, opts: {
17
17
  export declare function buildOrientationSection(t: TFunction): FilterPanelSection;
18
18
  /** @public 외곽선(표시/미표시) 세그먼트 섹션. */
19
19
  export declare function buildBorderSection(t: TFunction): FilterPanelSection;
20
+ /** @public 상단 정보(표시/미표시) 세그먼트 섹션 — 종이 머리 띠(로고·표 번호)를 켜고 끈다. */
21
+ export declare function buildTopInfoSection(t: TFunction): FilterPanelSection;
22
+ /** @public 하단 정보(표시/미표시) 세그먼트 섹션 — 종이 바닥 띠(만든 곳·주소·쪽 번호)를 켜고 끈다. */
23
+ export declare function buildBottomInfoSection(t: TFunction): FilterPanelSection;
20
24
  /** @public 절취선(표시/점선/코너/미표시) 세그먼트 섹션. */
21
25
  export declare function buildCutLineSection(t: TFunction): FilterPanelSection;
22
26
  /** @public 구분선(대립선, 표시/미표시) 세그먼트 섹션 — 대립쌍표에만 노출. */
@@ -48,6 +52,8 @@ export declare function buildTableSettingsSelected(t: TFunction, v: {
48
52
  showOutline: boolean;
49
53
  cutLine: WordTableCutLine;
50
54
  showDivLine: boolean;
55
+ showTopInfo?: boolean;
56
+ showBottomInfo?: boolean;
51
57
  }): Record<string, string | string[]>;
52
58
  /** @public 기본 5개 설정 상태 setter 묶음. */
53
59
  export interface TableSettingsSetters {
@@ -56,6 +62,8 @@ export interface TableSettingsSetters {
56
62
  setShowOutline: (v: boolean) => void;
57
63
  setCutLine: (v: WordTableCutLine) => void;
58
64
  setShowDivLine: (v: boolean) => void;
65
+ setShowTopInfo?: (v: boolean) => void;
66
+ setShowBottomInfo?: (v: boolean) => void;
59
67
  }
60
68
  /**
61
69
  * @public 기본 5개 설정 섹션의 FilterPanel select 처리. 처리했으면 true, 아니면(추가 섹션 라벨) false를
@@ -43,6 +43,28 @@ export function buildBorderSection(t) {
43
43
  display: 'segmented',
44
44
  };
45
45
  }
46
+ /** @public 상단 정보(표시/미표시) 세그먼트 섹션 — 종이 머리 띠(로고·표 번호)를 켜고 끈다. */
47
+ export function buildTopInfoSection(t) {
48
+ return {
49
+ label: t('wordTable.filter.topInfo', '상단 정보'),
50
+ items: [
51
+ { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
52
+ { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
53
+ ],
54
+ display: 'segmented',
55
+ };
56
+ }
57
+ /** @public 하단 정보(표시/미표시) 세그먼트 섹션 — 종이 바닥 띠(만든 곳·주소·쪽 번호)를 켜고 끈다. */
58
+ export function buildBottomInfoSection(t) {
59
+ return {
60
+ label: t('wordTable.filter.bottomInfo', '하단 정보'),
61
+ items: [
62
+ { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
63
+ { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
64
+ ],
65
+ display: 'segmented',
66
+ };
67
+ }
46
68
  /** @public 절취선(표시/점선/코너/미표시) 세그먼트 섹션. */
47
69
  export function buildCutLineSection(t) {
48
70
  return {
@@ -115,6 +137,13 @@ export function buildTableSettingsSelected(t, v) {
115
137
  [t('wordTable.filter.border', '외곽선')]: v.showOutline ? '표시' : '미표시',
116
138
  [t('wordTable.filter.cutLine', '절취선')]: v.cutLine,
117
139
  [t('wordPrint.divLine', '대립선')]: v.showDivLine ? '표시' : '미표시',
140
+ /* **`undefined` 는 '안 쓴다' 다** — `false`('미표시')와 다르다. 띠를 안 쓰는 화면은
141
+ 값을 안 주므로 항목 자체를 안 넣는다. 지금은 절 목록에 그 절이 없어 어차피 안
142
+ 보이지만, 여기 죽은 항목을 남겨 두면 **요약이 절이 아니라 이 맵을 훑도록 바뀌는 날**
143
+ 쓰지도 않는 줄 둘이 따라 선다. 그렇게 될 뻔한 것을 말귀가 tarball 을 뜯어 보고
144
+ 짚었다(2026-09-30). 쪽 번호가 쓰던 꼴(`isPaginated ? {…} : {}`)과 같게 둔다. */
145
+ ...(v.showTopInfo != null ? { [t('wordTable.filter.topInfo', '상단 정보')]: v.showTopInfo ? '표시' : '미표시' } : {}),
146
+ ...(v.showBottomInfo != null ? { [t('wordTable.filter.bottomInfo', '하단 정보')]: v.showBottomInfo ? '표시' : '미표시' } : {}),
118
147
  };
119
148
  }
120
149
  /**
@@ -147,5 +176,13 @@ export function applyTableSettingsSelect(t, value, sectionLabel, s) {
147
176
  s.setShowDivLine(value === '표시');
148
177
  return true;
149
178
  }
179
+ if (sectionLabel === t('wordTable.filter.topInfo', '상단 정보')) {
180
+ s.setShowTopInfo?.(value === '표시');
181
+ return true;
182
+ }
183
+ if (sectionLabel === t('wordTable.filter.bottomInfo', '하단 정보')) {
184
+ s.setShowBottomInfo?.(value === '표시');
185
+ return true;
186
+ }
150
187
  return false;
151
188
  }
@@ -66,20 +66,22 @@
66
66
  /* ── 종이 머리·바닥 띠 ────────────────────────────────────────────────
67
67
  쪽 번호가 쓰던 수를 위아래로 넓힌 것이다. 격자가 그만큼 비우고 띠는 그 빈 자리에
68
68
  절대 배치로 선다 — **격자 안**이라 인쇄가 격자만 복사해 가도 함께 간다. */
69
- .word-table-block__content--brand {
70
- /* 띠 높이에 딱 붙인다 — 남는 틈은 4px 뿐이다(사용자 지시 2026-09-30: 여백이 많다).
71
- 비운 자리가 띠보다 크면 로고와 칸 사이가 벌어져 종이가 헐거워 보인다. */
72
- padding-top: calc(32px * var(--wt-unscale, 1));
73
- padding-bottom: calc(24px * var(--wt-unscale, 1));
74
- }
69
+ /* 띠 높이에 딱 붙인다 — 남는 틈은 4px 뿐이다(사용자 지시 2026-09-30: 여백이 많다).
70
+ 비운 자리가 띠보다 크면 로고와 칸 사이가 벌어져 종이가 헐거워 보인다.
71
+ **위아래를 따로 비운다** — 표 설정에서 한쪽만 끌 수 있다. */
72
+ .word-table-block__content--brand-top { padding-top: calc(32px * var(--wt-unscale, 1)); }
73
+ .word-table-block__content--brand-bottom { padding-bottom: calc(26px * var(--wt-unscale, 1)); }
75
74
  /* 절취선 바탕·외곽선은 칸이 있는 데까지만 — 띠까지 두르면 로고가 표 안에 든 것처럼 보인다
76
75
  (쪽 번호 때와 같은 까닭). 아래는 쪽 번호 규칙과 겹치므로 여기서 다시 적어 이긴다. */
77
- .word-table-block__content--brand.word-table-block__content--cut-show {
76
+ .word-table-block__content--brand-top.word-table-block__content--cut-show,
77
+ .word-table-block__content--brand-bottom.word-table-block__content--cut-show {
78
78
  background-clip: content-box;
79
79
  }
80
- .word-table-block__content--brand.word-table-block__content--outline::after {
80
+ .word-table-block__content--brand-top.word-table-block__content--outline::after {
81
81
  top: calc(32px * var(--wt-unscale, 1));
82
- bottom: calc(24px * var(--wt-unscale, 1));
82
+ }
83
+ .word-table-block__content--brand-bottom.word-table-block__content--outline::after {
84
+ bottom: calc(26px * var(--wt-unscale, 1));
83
85
  }
84
86
 
85
87
  .word-table__band {
@@ -93,18 +95,34 @@
93
95
  z-index: 2;
94
96
  pointer-events: none;
95
97
  color: var(--color-gray);
96
- /* **body-3 급**이다(사용자 지시 2026-09-30) — 손으로 적은 13px 대신 디자인 시스템 값을
97
- 쓴다. 클래스(`.body-3`)를 그냥 붙이면 크기가 고정돼 배율 되돌림이 안 먹으므로,
98
- 같은 토큰에 되돌림만 곱한다.
99
- **이 토큰은 보는 사람 쪽 설정을 탄다** — 좁은 화면이면 13px, 큰 글씨 설정이면 16~18px
100
- 이라 종이 글씨가 그만큼 달라진다. 화면과 종이를 한 급으로 맞추기로 한 값이다. */
101
- font-size: calc(var(--text-body-3-size, 14px) * var(--wt-unscale, 1));
102
- line-height: calc(var(--text-body-3-line, 22px) * var(--wt-unscale, 1));
103
- font-weight: var(--text-body-3-weight, 400);
98
+ /* 글꼴 크기는 띠마다 다르다 — 위는 caption-1, 아래는 caption-2(사용자 지시 2026-09-30).
99
+ 클래스(`.caption-1`)를 그냥 붙이면 크기가 고정돼 배율 되돌림이 안 먹으므로 같은
100
+ 토큰에 되돌림만 곱한다. 그 토큰은 보는 사람 쪽 설정(좁은 화면 · 큰 글씨)을 타므로
101
+ 종이 글씨도 그만큼 달라진다 — 화면과 종이를 한 급으로 맞추기로 한 값이다. */
102
+ font-weight: var(--text-caption-1-weight, 400);
104
103
  }
105
104
  /* 비워 둔 44px 안에 든다 */
106
- .word-table__band--top { top: 0; height: calc(28px * var(--wt-unscale, 1)); }
107
- .word-table__band--bottom { bottom: 0; height: calc(20px * var(--wt-unscale, 1)); }
105
+ /* 위는 **11px**, 아래는 **8px** — 둘 다 종이 전용 값이라 토큰에서 벗어난다
106
+ (사용자 지시 2026-09-30). 화면 글씨는 읽는 거리에 맞추지만 이 줄들은 종이에 찍혀
107
+ 필요할 때만 들여다본다. 배율 되돌림은 그대로 받는다. */
108
+ .word-table__band--top {
109
+ top: 0;
110
+ height: calc(28px * var(--wt-unscale, 1));
111
+ font-size: calc(11px * var(--wt-unscale, 1));
112
+ line-height: calc(15px * var(--wt-unscale, 1));
113
+ }
114
+ /* 아래는 **8px** 이다(사용자 지시 2026-09-30) — 만든 곳 · 주소 · 쪽 번호는 찾을 때만 읽는
115
+ 잔글이라 디자인 시스템의 가장 작은 급(caption-2, 11px)보다 더 내린다. 토큰을 안 쓰는
116
+ 유일한 자리이고, **종이 전용 값**이라 그렇다: 화면 글씨는 사람이 읽는 거리에 맞추지만
117
+ 이 줄은 종이에 인쇄돼 필요할 때만 들여다본다. 배율 되돌림은 그대로 받는다. */
118
+ .word-table__band--bottom {
119
+ /* 로고까지 이 색을 받는다 — 마스크를 `currentColor` 로 칠하므로 글씨와 늘 같은 색이다 */
120
+ color: var(--color-gray);
121
+ bottom: 0;
122
+ height: calc(22px * var(--wt-unscale, 1));
123
+ font-size: calc(8px * var(--wt-unscale, 1));
124
+ line-height: calc(12px * var(--wt-unscale, 1));
125
+ }
108
126
 
109
127
  .word-table__brand-logo {
110
128
  height: calc(28px * var(--wt-unscale, 1));
@@ -115,8 +133,30 @@
115
133
  print-color-adjust: exact;
116
134
  -webkit-print-color-adjust: exact;
117
135
  }
118
- /* 만든 곳 로고 — 저작권 글씨와 같은 무게로 물러나 있는다 */
119
- .word-table__brand-logo--small { height: calc(14px * var(--wt-unscale, 1)); }
136
+ /* 만든 곳(ihab) 로고 — **그림이 아니라 꼴**이다. 흰 판 SVG 를 마스크로 오려 그 자리를
137
+ `currentColor` 로 칠하므로 곁의 글씨와 **같은 색**이 된다(사용자 지시 2026-09-30).
138
+ 파일에 `fill` 이 박혀 있어 `<img>` 로는 색을 못 바꾼다. 가로세로비는 파일 그대로(264:100).
139
+ 인쇄에서도 색이 빠지지 않게 말귀 로고와 같은 수를 쓴다. */
140
+ .word-table__brand-logo--ihab {
141
+ display: block;
142
+ height: calc(17px * var(--wt-unscale, 1));
143
+ width: calc(17px * 2.64 * var(--wt-unscale, 1));
144
+ flex-shrink: 0;
145
+ background-color: currentColor;
146
+ /* 이 파일이 로고를 **직접** 가리킨다 — 묶개가 주소를 풀어 준다. 마디에 인라인으로
147
+ 주던 때는 그 값이 화면에 안 실리는 일이 있었고, 무엇보다 여기 적어야 인쇄 문서로
148
+ (스타일시트를 통째로 베껴 가므로) 함께 간다. */
149
+ -webkit-mask-image: url('../logo/Logo_IHAB_en_white.svg');
150
+ mask-image: url('../logo/Logo_IHAB_en_white.svg');
151
+ -webkit-mask-repeat: no-repeat;
152
+ mask-repeat: no-repeat;
153
+ -webkit-mask-size: contain;
154
+ mask-size: contain;
155
+ -webkit-mask-position: center;
156
+ mask-position: center;
157
+ print-color-adjust: exact;
158
+ -webkit-print-color-adjust: exact;
159
+ }
120
160
 
121
161
  /* 만든 곳 — 로고와 저작권이 한 줄로 붙는다 */
122
162
  .word-table__brand-by {
@@ -142,11 +182,34 @@
142
182
  /* 표 번호·주소 — **종이 글씨는 전부 한 글꼴이다**(사용자 지시 2026-09-30). 고정폭으로
143
183
  찍어 봤는데 한 장 안에 글꼴이 둘 섞여 보였다. 종이가 한 벌로 읽히는 쪽을 골랐다 —
144
184
  목록 카드(`WordTableButton`)의 번호는 청한 대로 고정폭 그대로다. */
185
+ /* 기관 이름 · 표 번호 — 번호만 진하게 둔다(찾는 눈이 번호에 먼저 닿게) */
186
+ .word-table__ident {
187
+ display: flex;
188
+ align-items: center;
189
+ gap: calc(6px * var(--wt-unscale, 1));
190
+ min-width: 0;
191
+ }
192
+ /* 이름이 길면 이름만 줄어든다 — 번호는 잘리면 확인 글자가 사라져 뜻이 없다 */
193
+ .word-table__owner {
194
+ min-width: 0;
195
+ overflow: hidden;
196
+ text-overflow: ellipsis;
197
+ white-space: nowrap;
198
+ }
199
+ .word-table__ident-dot { flex-shrink: 0; }
200
+ /* 표 번호 — **띠와 같은 회색**이다(사용자 지시 2026-09-30). 한때 번호만 진하게 뒀는데,
201
+ 머리 줄 전체가 종이를 식별하는 잔글이라 한 무게로 읽히는 편이 낫다. */
145
202
  .word-table__code {
146
- color: var(--color-text-primary);
147
203
  flex-shrink: 0;
148
204
  white-space: nowrap;
149
205
  }
206
+ /* 표 제목 — 셋 중 제일 먼저 줄어든다(기관 이름·번호가 이 종이를 가리키는 값이다) */
207
+ .word-table__paper-title {
208
+ min-width: 0;
209
+ overflow: hidden;
210
+ text-overflow: ellipsis;
211
+ white-space: nowrap;
212
+ }
150
213
  /* 이 표로 가는 주소 — 길 수 있으므로 넘치면 …로 자른다(쪽 번호는 안 밀린다) */
151
214
  .word-table__link {
152
215
  color: var(--color-gray);
@@ -99,10 +99,18 @@ export interface WordTableProps {
99
99
  brand?: {
100
100
  /** 로고와 저작권을 세운다. 나머지 자리는 각자 값이 있을 때만 선다. */
101
101
  show?: boolean;
102
+ /** 위 띠만 끈다(`show` 가 켜져 있을 때). 표 설정의 '상단 정보' 가 이것을 움직인다. */
103
+ top?: boolean;
104
+ /** 아래 띠만 끈다(`show` 가 켜져 있을 때). 표 설정의 '하단 정보' 가 이것을 움직인다. */
105
+ bottom?: boolean;
102
106
  /**
103
107
  * 아래 오른쪽 — **이 표로 가는 주소**. 회사 홈 주소가 아니라 그 표의 공유 링크다
104
108
  * (사용자 지시 2026-09-30). 종이를 든 사람이 이 주소로 같은 표를 화면에서 연다.
105
109
  *
110
+ * **`code` 와는 다른 것이다.** 표 번호는 기관 안에서 매긴 번호고 이 주소는 따로 난
111
+ * 공유 링크다 — 번호에서 주소를 만들어 내지 않는다. 둘 다 이 표를 가리키지만 나오는
112
+ * 데가 다르므로 각각 받는다.
113
+ *
106
114
  * 종이라 누를 수 없으니 글자 그대로 찍는다 — 그래서 **사람이 옮겨 칠 수 있는 길이**
107
115
  * 여야 한다. 긴 주소를 그대로 주면 넘쳐 …로 잘리고, 잘린 주소는 옮겨 칠 수 없다.
108
116
  * 짧은 주소를 쓰거나, 표 번호로 찾는 길을 함께 두는 편이 낫다.
@@ -110,6 +118,15 @@ export interface WordTableProps {
110
118
  link?: string;
111
119
  /** 저작권 글월 — 안 주면 `© IHAB, Inc. All rights reserved.` */
112
120
  copyright?: string;
121
+ /** 위 오른쪽 맨 앞 — **이 표의 이름**. `표 제목 · 기관 이름 · 표 번호` 로 선다. */
122
+ title?: string;
123
+ /**
124
+ * 위 오른쪽 — **표 번호 앞에 붙는 기관 이름**(말귀매니저). 번호는 그 기관 안에서만
125
+ * 고유하므로 이름과 함께여야 어느 곳의 몇 번인지가 정해진다(사용자 지시 2026-09-30).
126
+ * `이름 · 번호` 로 선다. 이름이 길면 이름만 줄고 번호는 안 줄인다 — 번호가 잘리면
127
+ * 확인 글자가 사라져 뜻이 없다.
128
+ */
129
+ owner?: string;
113
130
  };
114
131
  /**
115
132
  * **짧은 식별 글** — 표 번호(`1043-E`). `brand` 를 줬을 때 위 오른쪽에 선다.
@@ -16,10 +16,11 @@ import useMediaQuery from '../hooks/useMediaQuery';
16
16
  import { isTouchPointer, recentlyTouched, useTouchToggle } from '../hooks/touchToggle';
17
17
  /* `Footer` 가 하듯 곧장 가져온다 — 묶개가 알아서 옮겨 주고, 인쇄 창은 `<img>` 가 다 받아진
18
18
  뒤에 인쇄한다. 말귀는 **컬러 판**이다(사용자 지시 2026-09-30) — 종이에서도 색으로 나가야
19
- 하므로 아래 CSS 가 `print-color-adjust: exact` 를 준다. 만든 곳(ihab)은 검정 판이라
20
- 글씨와 같은 무게로 물러나 있는다. */
19
+ 하므로 아래 CSS 가 `print-color-adjust: exact` 를 준다.
20
+
21
+ ihab 은 **흰 판을 마스크로 쓴다**(사용자 지시 2026-09-30: 글자색을 입힌다) — 그쪽은
22
+ `WordTable.css` 가 제 곁의 파일을 직접 가리키므로 여기서 안 들여온다. */
21
23
  import 말귀로고 from '../logo/Logo_speechear_kr.svg';
22
- import ihab로고 from '../logo/Logo_IHAB_en_black.svg';
23
24
  import { WORD_TABLE_PAPER, gridFor, CUT_CLASS, POS_LABEL, WORD_TYPE_LABEL, expandSlashLabel, dotDashStyle, REF_W_BOTH, REF_W_TEXT_ONLY, REF_W_IMAGE_ONLY, REF_H_BOTH, REF_H_TEXT_ONLY, REF_H_IMAGE_ONLY, } from './wordTableLayout';
24
25
  import { useFitScale } from './useFitScale';
25
26
  import { claimSound } from './Training/currentSound';
@@ -371,14 +372,19 @@ export default function WordTable({ title, titleIcon, disc, className, orientati
371
372
  : (items ?? []).some(item => (item.words ?? []).length > 1);
372
373
  /* 로고를 세우기로 한 때만 띠를 두른다. `code`·`link` 만 주고 `show` 를 안 주면 띠가 없으니
373
374
  그 값들도 설 자리가 없다 — 켜는 스위치를 하나로 둔다. */
374
- const 띠쓰나 = Boolean(brand?.show);
375
+ /* 띠를 쓰기로 한 종이인가 — 한쪽을 꺼도 이 종이는 '띠를 쓰는 꼴'이다.
376
+ 쪽 번호가 어디에 서는지를 이 값이 가른다(아래를 보라). */
377
+ const 브랜드쓰나 = Boolean(brand?.show);
378
+ const 띠쓰나 = 브랜드쓰나 && (brand?.top !== false || brand?.bottom !== false);
379
+ const 위띠쓰나 = Boolean(brand?.show) && brand?.top !== false;
380
+ const 아래띠쓰나 = Boolean(brand?.show) && brand?.bottom !== false;
375
381
  const 저작권 = brand?.copyright ?? '© IHAB, Inc. All rights reserved.';
376
382
  const contentClass = cx('word-table-block__content', CUT_CLASS[cutLine], showOutline && 'word-table-block__content--outline', showDivLine && hasPairs && 'word-table-block__content--div-line',
377
383
  /* 번호가 설 자리를 비운다 — 번호가 없으면 비우지 않는다(표가 공연히 낮아지지 않게) */
378
- pageNumber && pageNumberPosition !== 'none' && 'word-table-block__content--page-number',
384
+ !브랜드쓰나 && pageNumber && pageNumberPosition !== 'none' && 'word-table-block__content--page-number',
379
385
  /* 띠가 설 자리를 위아래로 비운다 — 같은 까닭으로 띠가 없으면 안 비운다.
380
386
  바닥 띠가 쪽 번호 자리를 겸하므로 둘이 겹쳐도 아래는 한 번만 비운다(CSS 가 덮어쓴다). */
381
- 띠쓰나 && 'word-table-block__content--brand');
387
+ 위띠쓰나 && 'word-table-block__content--brand-top', 아래띠쓰나 && 'word-table-block__content--brand-bottom');
382
388
  // 빈칸(추가버튼)은 스케일 역보정으로 실제 크기 유지
383
389
  const counterScale = { transform: `scale(${1 / scale})`, transformOrigin: 'center center' };
384
390
  /* **채점 단추는 표와 함께 줄어들면 안 된다.**
@@ -419,7 +425,18 @@ export default function WordTable({ title, titleIcon, disc, className, orientati
419
425
  _jsxs("div", { className: "word-table-block__card-actions", children: [renderCellAction?.(index, item), onRemoveItem && (_jsx("div", { className: "word-table-block__card-close", children: _jsx(Button, { htmlType: "button", size: buttonSize, type: "dot", icon: "x", variant: "transparent-lightGray", useBorder: false, showTooltipInfo: (item.words ?? []).length > 1 ? t('wordPrint.removePair', '대립쌍 빼기') : t('wordPrint.removeWord', '단어 빼기'), ariaLabel: (item.words ?? []).length > 1 ? t('wordPrint.removePair', '대립쌍 빼기') : t('wordPrint.removeWord', '단어 빼기'), onClick: () => onRemoveItem(item.id) }) }))] }))] }, item.id))), Array.from({ length: Math.max(0, cols * rows - (items?.length ?? 0)) }).map((_, i) => {
420
426
  const isWithinCount = (items?.length ?? 0) + i < cellCount;
421
427
  return (_jsx("div", { className: "word-table-block__card word-table-block__card--filler", children: showFillerAdd && onActivateCell && isWithinCount && (_jsx("div", { style: counterScale, children: _jsx(Button, { htmlType: "button", size: buttonSize, type: "bar", icon: "plus", label: t('wordTable.addWord', '추가하기'), onClick: () => onActivateCell((items?.length ?? 0) + i) }) })) }, `filler-${i}`));
422
- })] })), 띠쓰나 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "word-table__band word-table__band--top", children: [_jsx("img", { className: "word-table__brand-logo", src: 말귀로고, alt: "\uB9D0\uADC0" }), code && _jsx("span", { className: "word-table__code", children: code })] }), _jsxs("div", { className: "word-table__band word-table__band--bottom", children: [_jsxs("span", { className: "word-table__brand-by", children: [_jsx("img", { className: "word-table__brand-logo word-table__brand-logo--small", src: ihab로고, alt: "IHAB" }), _jsx("span", { className: "word-table__copyright", children: 저작권 })] }), _jsxs("span", { className: "word-table__band-end", children: [brand?.link && _jsx("span", { className: "word-table__link", children: brand.link }), pageNumber && pageNumberPosition !== 'none' && (_jsx("span", { className: "word-table__page-count", children: t('wordTable.filter.pageIndicator', { current: pageNumber.current, total: pageNumber.total }) }))] })] })] })), !띠쓰나 && pageNumber && pageNumberPosition !== 'none' && (_jsx("span", { className: `word-table__page-number body-3 word-table__page-number--${pageNumberPosition}`, children: t('wordTable.filter.pageIndicator', { current: pageNumber.current, total: pageNumber.total }) }))] }) }), onReorder && _jsx("span", { role: "status", style: 보이지않게, children: 옮김알림 })] }));
428
+ })] })), 위띠쓰나 && (_jsx(_Fragment, { children: _jsxs("div", { className: "word-table__band word-table__band--top", children: [_jsx("img", { className: "word-table__brand-logo", src: 말귀로고, alt: "\uB9D0\uADC0" }), (() => {
429
+ /* 표 제목 · 기관 이름 · 표 번호 — 있는 것끼리만 가운뎃점으로 잇는다
430
+ (사용자 지시 2026-09-30). 없는 것 자리에 점이 남으면 안 된다. */
431
+ const 조각들 = [
432
+ brand?.title && _jsx("span", { className: "word-table__paper-title", children: brand.title }, "t"),
433
+ brand?.owner && _jsx("span", { className: "word-table__owner", children: brand.owner }, "o"),
434
+ code && _jsx("span", { className: "word-table__code", children: code }, "c"),
435
+ ].filter(Boolean);
436
+ if (조각들.length === 0)
437
+ return null;
438
+ return (_jsx("span", { className: "word-table__ident", children: 조각들.map((조각, i) => (_jsxs(Fragment, { children: [i > 0 && _jsx("span", { className: "word-table__ident-dot", "aria-hidden": "true", children: "\u00B7" }), 조각] }, i))) }));
439
+ })()] }) })), 아래띠쓰나 && (_jsx(_Fragment, { children: _jsxs("div", { className: "word-table__band word-table__band--bottom", children: [_jsxs("span", { className: "word-table__brand-by", children: [_jsx("span", { className: "word-table__brand-logo--ihab", role: "img", "aria-label": "IHAB" }), _jsx("span", { className: "word-table__copyright", children: 저작권 })] }), _jsxs("span", { className: "word-table__band-end", children: [brand?.link && _jsx("span", { className: "word-table__link", children: brand.link }), pageNumber && pageNumberPosition !== 'none' && (_jsx("span", { className: "word-table__page-count", children: t('wordTable.filter.pageIndicator', { current: pageNumber.current, total: pageNumber.total }) }))] })] }) })), !브랜드쓰나 && pageNumber && pageNumberPosition !== 'none' && (_jsx("span", { className: `word-table__page-number body-3 word-table__page-number--${pageNumberPosition}`, children: t('wordTable.filter.pageIndicator', { current: pageNumber.current, total: pageNumber.total }) }))] }) }), onReorder && _jsx("span", { role: "status", style: 보이지않게, children: 옮김알림 })] }));
423
440
  /* 담는 틀 — 높이를 받은 자리에서만 두른다. `useFitScale` 은 **스케일러의 부모**를 재므로
424
441
  이 틀이 곧 그 자(척도)가 된다. 가운데 맞춤은 남는 세로를 위아래로 나눈다 — 표가 상자보다
425
442
  납작할 때 아래로만 쏠려 보이지 않게. */
@@ -738,6 +738,8 @@
738
738
  "pageNumberCenter": "Center",
739
739
  "pageNumberRight": "Right",
740
740
  "border": "Border",
741
+ "topInfo": "Header",
742
+ "bottomInfo": "Footer",
741
743
  "cutLine": "Cut Line",
742
744
  "show": "Show",
743
745
  "hide": "Hide",
@@ -736,6 +736,8 @@
736
736
  "pageNumberCenter": "중앙",
737
737
  "pageNumberRight": "오른쪽",
738
738
  "border": "외곽선",
739
+ "topInfo": "상단 정보",
740
+ "bottomInfo": "하단 정보",
739
741
  "cutLine": "절취선",
740
742
  "show": "표시",
741
743
  "hide": "미표시",
@@ -46,4 +46,4 @@
46
46
  *
47
47
  * 값은 손으로 적고 `test/coreVersion.test.ts` 가 package.json 과 어긋나면 운다.
48
48
  */
49
- export declare const CORE_VERSION = "0.213.0";
49
+ export declare const CORE_VERSION = "0.215.0";
@@ -46,4 +46,4 @@
46
46
  *
47
47
  * 값은 손으로 적고 `test/coreVersion.test.ts` 가 package.json 과 어긋나면 운다.
48
48
  */
49
- export const CORE_VERSION = '0.213.0';
49
+ export const CORE_VERSION = '0.215.0';