@ihabdevteam/core 0.321.0 → 0.323.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.
Files changed (217) hide show
  1. package/CHANGELOG.md +617 -0
  2. package/dist/components.cjs.js +183 -183
  3. package/dist/components.esm.css +1 -1
  4. package/dist/hooks.cjs.js +3 -3
  5. package/dist/i18n.cjs.js +3 -3
  6. package/dist/ihabdevteam-core.cjs.js +187 -187
  7. package/dist/ihabdevteam-core.d.ts +108 -66
  8. package/dist/packages/core/src/components/Accordion.js +3 -3
  9. package/dist/packages/core/src/components/Alert.js +2 -2
  10. package/dist/packages/core/src/components/BarChart.js +120 -119
  11. package/dist/packages/core/src/components/BottomNav.js +18 -18
  12. package/dist/packages/core/src/components/BulkBar.js +25 -25
  13. package/dist/packages/core/src/components/Button.js +16 -16
  14. package/dist/packages/core/src/components/Calendar.js +17 -17
  15. package/dist/packages/core/src/components/ChartSection.js +30 -30
  16. package/dist/packages/core/src/components/CountTile.js +38 -38
  17. package/dist/packages/core/src/components/DatePicker.js +59 -59
  18. package/dist/packages/core/src/components/Dialog.js +14 -14
  19. package/dist/packages/core/src/components/Effect/EffectPartyPopperHost.js +8 -8
  20. package/dist/packages/core/src/components/FilterPanel.js +6 -6
  21. package/dist/packages/core/src/components/FilterSectionInfo.js +6 -6
  22. package/dist/packages/core/src/components/GameIntro.js +1 -1
  23. package/dist/packages/core/src/components/HearingDeviceInfo.d.ts +5 -5
  24. package/dist/packages/core/src/components/HearingDeviceInfo.js +2 -2
  25. package/dist/packages/core/src/components/Icon.js +2 -2
  26. package/dist/packages/core/src/components/ItemActions.js +16 -16
  27. package/dist/packages/core/src/components/LandingHeader.js +6 -6
  28. package/dist/packages/core/src/components/LineChart.js +24 -24
  29. package/dist/packages/core/src/components/Loader.js +5 -5
  30. package/dist/packages/core/src/components/NoticeBox.js +3 -3
  31. package/dist/packages/core/src/components/PageTitle.js +2 -2
  32. package/dist/packages/core/src/components/Pagination.js +4 -4
  33. package/dist/packages/core/src/components/Panel.js +2 -2
  34. package/dist/packages/core/src/components/PanelRow.d.ts +2 -4
  35. package/dist/packages/core/src/components/PanelRow.js +8 -15
  36. package/dist/packages/core/src/components/PassCard/PassCard.js +9 -9
  37. package/dist/packages/core/src/components/PassCard/passCardProduct.js +2 -2
  38. package/dist/packages/core/src/components/PaymentPlan.js +5 -5
  39. package/dist/packages/core/src/components/Popup/ConfirmPopup.js +29 -29
  40. package/dist/packages/core/src/components/Popup/CouponInputPopup.js +2 -2
  41. package/dist/packages/core/src/components/Popup/DeviceListPopup.d.ts +4 -8
  42. package/dist/packages/core/src/components/Popup/DeviceListPopup.js +1 -1
  43. package/dist/packages/core/src/components/Popup/DeviceSideTable.js +19 -26
  44. package/dist/packages/core/src/components/Popup/ListPopup.js +6 -6
  45. package/dist/packages/core/src/components/Popup/LoadTablePopup.js +10 -10
  46. package/dist/packages/core/src/components/Popup/Popup.js +27 -27
  47. package/dist/packages/core/src/components/Popup/SaveTablePopup.js +5 -5
  48. package/dist/packages/core/src/components/Popup/TrainingResultPopup.js +4 -4
  49. package/dist/packages/core/src/components/Popup/customerDetailUtils.js +18 -18
  50. package/dist/packages/core/src/components/Popup/useDiscardGuard.js +4 -4
  51. package/dist/packages/core/src/components/ProgressIndicator.js +5 -5
  52. package/dist/packages/core/src/components/PromoBannerBg/promoBannerBg.js +16 -16
  53. package/dist/packages/core/src/components/Rating.js +20 -20
  54. package/dist/packages/core/src/components/Report/ReportDocument.js +21 -21
  55. package/dist/packages/core/src/components/RingChart.js +5 -5
  56. package/dist/packages/core/src/components/SectionHeadFloat.js +15 -15
  57. package/dist/packages/core/src/components/SegmentedControl.js +34 -34
  58. package/dist/packages/core/src/components/SideNav.js +37 -37
  59. package/dist/packages/core/src/components/Slider.js +2 -2
  60. package/dist/packages/core/src/components/SoundCompass.js +5 -5
  61. package/dist/packages/core/src/components/Table.js +257 -98
  62. package/dist/packages/core/src/components/Tabs.js +12 -12
  63. package/dist/packages/core/src/components/TextField.js +34 -34
  64. package/dist/packages/core/src/components/Toast.js +6 -6
  65. package/dist/packages/core/src/components/Tooltip/MenuTooltip.js +4 -4
  66. package/dist/packages/core/src/components/Tooltip/Tooltip.js +22 -22
  67. package/dist/packages/core/src/components/Tooltip/TrainingTooltip.js +4 -4
  68. package/dist/packages/core/src/components/TopBanner.js +28 -28
  69. package/dist/packages/core/src/components/Training/AudioPlayerWaveForm.js +11 -11
  70. package/dist/packages/core/src/components/Training/CategoryIcon.js +2 -2
  71. package/dist/packages/core/src/components/Training/NoisePlayerContext.d.ts +7 -4
  72. package/dist/packages/core/src/components/Training/NoisePlayerContext.js +12 -12
  73. package/dist/packages/core/src/components/Training/NoiseSettingsTooltip.js +2 -2
  74. package/dist/packages/core/src/components/Training/TrainingBlock.js +12 -12
  75. package/dist/packages/core/src/components/Training/TrainingBlockButton.js +10 -10
  76. package/dist/packages/core/src/components/Training/TrainingBlockGrid.js +21 -21
  77. package/dist/packages/core/src/components/Training/TrainingCard.css +13 -1
  78. package/dist/packages/core/src/components/Training/TrainingCard.js +2 -2
  79. package/dist/packages/core/src/components/Training/TrainingCardGroup.js +6 -6
  80. package/dist/packages/core/src/components/Training/TrainingPagePopup.js +83 -83
  81. package/dist/packages/core/src/components/Training/TrainingPagePopupBottom.js +17 -17
  82. package/dist/packages/core/src/components/Training/TrainingStepAudioPlayer.js +128 -128
  83. package/dist/packages/core/src/components/Training/TrainingStepCard.js +18 -18
  84. package/dist/packages/core/src/components/Training/TrainingStepConfirmWithText.js +4 -4
  85. package/dist/packages/core/src/components/Training/TrainingStepOrderList.js +12 -12
  86. package/dist/packages/core/src/components/Training/TrainingStepTextBox.js +13 -13
  87. package/dist/packages/core/src/components/Training/TrainingStepTitle.js +4 -4
  88. package/dist/packages/core/src/components/Training/TrainingWordCard.js +17 -17
  89. package/dist/packages/core/src/components/Training/WordTablePopup.js +5 -5
  90. package/dist/packages/core/src/components/Training/audioPlaybackRules.js +8 -8
  91. package/dist/packages/core/src/components/Training/audioTimeline.js +25 -25
  92. package/dist/packages/core/src/components/Training/oneShotSound.d.ts +1 -1
  93. package/dist/packages/core/src/components/Training/oneShotSound.js +14 -14
  94. package/dist/packages/core/src/components/Training/stepAnswerable.d.ts +2 -2
  95. package/dist/packages/core/src/components/Training/trainingMissStats.js +22 -22
  96. package/dist/packages/core/src/components/Training/trainingPopupUtils.js +7 -7
  97. package/dist/packages/core/src/components/Training/useAudioPreview.js +15 -15
  98. package/dist/packages/core/src/components/Training/useFloatingFocus.js +14 -14
  99. package/dist/packages/core/src/components/Training/useNoiseFade.js +22 -22
  100. package/dist/packages/core/src/components/Training/useObjectUrls.js +2 -2
  101. package/dist/packages/core/src/components/Training/usePlaybackSequencer.d.ts +2 -2
  102. package/dist/packages/core/src/components/Training/usePlaybackSequencer.js +23 -23
  103. package/dist/packages/core/src/components/Training/useProgressTicker.js +33 -33
  104. package/dist/packages/core/src/components/Training/useTTSPlayback.js +17 -17
  105. package/dist/packages/core/src/components/Training/useWaveReady.js +11 -11
  106. package/dist/packages/core/src/components/UpdateAlert.js +6 -6
  107. package/dist/packages/core/src/components/Word/PhonemeSelectBlock.js +7 -1
  108. package/dist/packages/core/src/components/Word/TableFilterPanel.js +3 -3
  109. package/dist/packages/core/src/components/Word/WordSearchResultBlock.js +18 -18
  110. package/dist/packages/core/src/components/Word/WordTableBlock.js +28 -28
  111. package/dist/packages/core/src/components/Word/WordTableButton.css +16 -2
  112. package/dist/packages/core/src/components/Word/WordTableThumbnail.css +6 -1
  113. package/dist/packages/core/src/components/Word/generatedDraft.js +14 -14
  114. package/dist/packages/core/src/components/Word/useWordTableDisplaySettings.js +7 -7
  115. package/dist/packages/core/src/components/Word/wordScoreStats.js +17 -17
  116. package/dist/packages/core/src/components/Word/wordTablePrint.js +10 -10
  117. package/dist/packages/core/src/components/Word/wordTableRecommend.js +13 -13
  118. package/dist/packages/core/src/components/Word/wordTableReview.js +28 -28
  119. package/dist/packages/core/src/components/Word/wordTableSettings.d.ts +8 -11
  120. package/dist/packages/core/src/components/Word/wordTableSettings.js +48 -36
  121. package/dist/packages/core/src/components/WordTable.js +130 -130
  122. package/dist/packages/core/src/components/barChartData.d.ts +16 -1
  123. package/dist/packages/core/src/components/barChartData.js +49 -29
  124. package/dist/packages/core/src/components/barChartTypes.js +8 -8
  125. package/dist/packages/core/src/components/tableTrackList.js +11 -11
  126. package/dist/packages/core/src/components/updateAlertStack.js +28 -28
  127. package/dist/packages/core/src/components/useBarChartControl.js +4 -6
  128. package/dist/packages/core/src/components/useComboboxSuggestions.js +17 -17
  129. package/dist/packages/core/src/components/useToastLifecycle.js +18 -18
  130. package/dist/packages/core/src/components/wordTableLayout.d.ts +22 -7
  131. package/dist/packages/core/src/components/wordTableLayout.js +5 -5
  132. package/dist/packages/core/src/context/I18nProvider.js +6 -6
  133. package/dist/packages/core/src/hooks/focusReturn.js +27 -27
  134. package/dist/packages/core/src/hooks/inputModality.d.ts +1 -1
  135. package/dist/packages/core/src/hooks/inputModality.js +14 -14
  136. package/dist/packages/core/src/hooks/touchToggle.js +39 -39
  137. package/dist/packages/core/src/hooks/useAnchoredMenu.js +30 -30
  138. package/dist/packages/core/src/hooks/useDailyTrainingSelection.js +28 -28
  139. package/dist/packages/core/src/hooks/useDeviceManagement.d.ts +5 -17
  140. package/dist/packages/core/src/hooks/useDeviceManagement.js +20 -8
  141. package/dist/packages/core/src/hooks/useDocumentTitle.js +10 -10
  142. package/dist/packages/core/src/hooks/useEditableList.js +4 -4
  143. package/dist/packages/core/src/hooks/useFocusTrap.js +2 -2
  144. package/dist/packages/core/src/hooks/useFontScale.js +6 -6
  145. package/dist/packages/core/src/hooks/useIcon.js +7 -7
  146. package/dist/packages/core/src/hooks/useListControls.js +2 -2
  147. package/dist/packages/core/src/hooks/usePageResetOnChange.d.ts +3 -3
  148. package/dist/packages/core/src/hooks/usePageResetOnChange.js +6 -6
  149. package/dist/packages/core/src/hooks/usePasswordChange.js +4 -4
  150. package/dist/packages/core/src/hooks/usePendingPress.js +7 -7
  151. package/dist/packages/core/src/hooks/useRelativeDay.js +4 -4
  152. package/dist/packages/core/src/hooks/useSoundCompassExam.js +6 -6
  153. package/dist/packages/core/src/hooks/useTablePaging.d.ts +7 -7
  154. package/dist/packages/core/src/hooks/useTablePaging.js +40 -34
  155. package/dist/packages/core/src/hooks/useTrainingSessionLog.js +35 -35
  156. package/dist/packages/core/src/hooks/useVisitSchedule.js +4 -4
  157. package/dist/packages/core/src/hooks/useWordAttributeFilter.js +14 -14
  158. package/dist/packages/core/src/hooks/useWordMeanings.js +5 -5
  159. package/dist/packages/core/src/hooks/useWordTrainingFilter.d.ts +3 -1
  160. package/dist/packages/core/src/hooks/useWordTrainingFilter.js +14 -12
  161. package/dist/packages/core/src/i18n/locales/en.json +13 -2
  162. package/dist/packages/core/src/i18n/locales/ko.json +12 -1
  163. package/dist/packages/core/src/types/wordSearch.d.ts +9 -0
  164. package/dist/packages/core/src/utils/audioMeter.js +5 -5
  165. package/dist/packages/core/src/utils/audioPeaks.d.ts +1 -1
  166. package/dist/packages/core/src/utils/audioPeaks.js +18 -18
  167. package/dist/packages/core/src/utils/blockGrid.js +4 -4
  168. package/dist/packages/core/src/utils/chunkSkew.js +9 -9
  169. package/dist/packages/core/src/utils/clipboard.js +3 -3
  170. package/dist/packages/core/src/utils/dailySelectionUtils.js +12 -12
  171. package/dist/packages/core/src/utils/date.js +12 -12
  172. package/dist/packages/core/src/utils/devWarn.d.ts +2 -2
  173. package/dist/packages/core/src/utils/devWarn.js +7 -7
  174. package/dist/packages/core/src/utils/deviceKind.d.ts +37 -7
  175. package/dist/packages/core/src/utils/deviceKind.js +53 -10
  176. package/dist/packages/core/src/utils/errorMessage.js +7 -7
  177. package/dist/packages/core/src/utils/filterPanelSummary.d.ts +1 -1
  178. package/dist/packages/core/src/utils/filterPanelSummary.js +16 -16
  179. package/dist/packages/core/src/utils/format.js +4 -4
  180. package/dist/packages/core/src/utils/getTrainingData.js +9 -9
  181. package/dist/packages/core/src/utils/imageConfig.js +17 -17
  182. package/dist/packages/core/src/utils/koreanSyllable.js +18 -18
  183. package/dist/packages/core/src/utils/navScroll.d.ts +2 -2
  184. package/dist/packages/core/src/utils/navScroll.js +6 -6
  185. package/dist/packages/core/src/utils/phonemeConvert.d.ts +7 -0
  186. package/dist/packages/core/src/utils/phonemeConvert.js +19 -10
  187. package/dist/packages/core/src/utils/phonemeGroups.js +2 -2
  188. package/dist/packages/core/src/utils/phonemePairSearch.d.ts +1 -0
  189. package/dist/packages/core/src/utils/phonemePairSearch.js +118 -102
  190. package/dist/packages/core/src/utils/phonemeSectionCodes.d.ts +52 -0
  191. package/dist/packages/core/src/utils/phonemeSectionCodes.js +76 -0
  192. package/dist/packages/core/src/utils/prefetchChunk.js +6 -6
  193. package/dist/packages/core/src/utils/pressable.d.ts +1 -1
  194. package/dist/packages/core/src/utils/pressable.js +3 -3
  195. package/dist/packages/core/src/utils/safeHref.js +4 -4
  196. package/dist/packages/core/src/utils/savedWordTables.js +5 -5
  197. package/dist/packages/core/src/utils/sessionTab.d.ts +7 -7
  198. package/dist/packages/core/src/utils/sessionTab.js +9 -9
  199. package/dist/packages/core/src/utils/speak.js +12 -12
  200. package/dist/packages/core/src/utils/textSort.d.ts +5 -5
  201. package/dist/packages/core/src/utils/textSort.js +47 -47
  202. package/dist/packages/core/src/utils/theme.js +3 -3
  203. package/dist/packages/core/src/utils/trainingItemResults.js +3 -3
  204. package/dist/packages/core/src/utils/ttsConfig.js +2 -2
  205. package/dist/packages/core/src/utils/wordAttributeFilterCodes.d.ts +2 -2
  206. package/dist/packages/core/src/utils/wordAttributeFilterCodes.js +48 -48
  207. package/dist/packages/core/src/utils/wordContrast.js +3 -3
  208. package/dist/packages/core/src/utils/wordPairIndex.js +4 -4
  209. package/dist/packages/core/src/utils/wordTrainingGenerators.js +4 -4
  210. package/dist/packages/core/src/utils/wordTrainingPool.js +15 -15
  211. package/dist/packages/core/src/utils/wordTrainingRuntime.js +6 -6
  212. package/dist/packages/core/src/utils/wornDate.d.ts +3 -3
  213. package/dist/packages/core/src/utils/wornDate.js +14 -14
  214. package/dist/packages/core/src/version.d.ts +1 -1
  215. package/dist/packages/core/src/version.js +1 -1
  216. package/dist/utils.cjs.js +4 -4
  217. package/package.json +1 -1
@@ -9,7 +9,7 @@ import { toKstYmd, formatYmd } from '../../utils/date';
9
9
  * 이 파일에는 화면도 저장도 없다. 무엇을 담을지만 안다.
10
10
  */
11
11
  /** 다음 표에 담을 표시 — 틀림과 애매. */
12
- const 담을것 = new Set(['x', 'triangle']);
12
+ const COUNTED_MARKS = new Set(['x', 'triangle']);
13
13
  /**
14
14
  * 다음 표에 담을 칸들.
15
15
  *
@@ -28,29 +28,29 @@ export function reviewCells(items, marks) {
28
28
  const out = [];
29
29
  for (let i = 0; i < items.length; i++) {
30
30
  const m = marks[String(i)];
31
- if (m && 담을것.has(m))
31
+ if (m && COUNTED_MARKS.has(m))
32
32
  out.push(items[i]);
33
33
  }
34
34
  return out;
35
35
  }
36
36
  /** 복습 꼬리 — `[N차 ]복습 MM.DD`. '복습' 뒤에 날짜가 따라와야만 꼬리로 본다("복습 자료" 같은 이름을 잘라 먹지 않게). */
37
- const 복습꼬리 = /\s*(?:(\d+)차\s*)?복습\s*\d{2}\.\d{2}$/;
37
+ const REVIEW_SUFFIX = /\s*(?:(\d+)차\s*)?복습\s*\d{2}\.\d{2}$/;
38
38
  /** 원래 표 → (꼬리를 뗀 바탕 이름, 새 복습표의 회차). 메타가 있으면 메타를, 없으면 이름을 읽는다. */
39
- function 바탕과회차(src) {
40
- const 이름 = src.name.trim();
41
- const 메타회차 = src.reviewRound;
42
- if (typeof 메타회차 === 'number' && Number.isFinite(메타회차) && 메타회차 >= 0) {
43
- const 지난 = Math.floor(메타회차);
44
- if (지난 === 0)
45
- return { 바탕: 이름, 회차: 1 };
39
+ function baseAndRound(src) {
40
+ const name = src.name.trim();
41
+ const metaRound = src.reviewRound;
42
+ if (typeof metaRound === 'number' && Number.isFinite(metaRound) && metaRound >= 0) {
43
+ const past = Math.floor(metaRound);
44
+ if (past === 0)
45
+ return { base: name, round: 1 };
46
46
  /* 메타가 말하는 **그 회차의 꼬리 하나만** 뗀다 — `수업 3차 복습 09.15`(1회) 에서 `3차` 를 회차로 먹지 않는다.
47
47
  N차는 앞이 공백·처음일 때만 — `수업 13차 복습`(3회) 의 `3차` 를 떼지 않게. 사람이 이름을 고쳐 꼬리가 없으면
48
48
  이름을 통째로 바탕으로 둔다. */
49
- const 그꼬리 = 지난 === 1
49
+ const suffix = past === 1
50
50
  ? /\s*복습\s*\d{2}\.\d{2}$/
51
- : new RegExp(`(?:^|\\s)${지난}차\\s*복습\\s*\\d{2}\\.\\d{2}$`);
52
- const m = 그꼬리.exec(이름);
53
- return { 바탕: m ? 이름.slice(0, m.index).trim() : 이름, 회차: 지난 + 1 };
51
+ : new RegExp(`(?:^|\\s)${past}차\\s*복습\\s*\\d{2}\\.\\d{2}$`);
52
+ const m = suffix.exec(name);
53
+ return { base: m ? name.slice(0, m.index).trim() : name, round: past + 1 };
54
54
  }
55
55
  /* **메타 없는 옛 표 — 이름을 파싱한다.** 복습표를 또 복습하면 꼬리가 쌓인다. 그대로 두면
56
56
  `검수 대립쌍 복습 08.29 복습 08.30 복습 09.02` 처럼 자란다 — 복습을 거듭하는 것은
@@ -63,16 +63,16 @@ function 바탕과회차(src) {
63
63
 
64
64
  '복습' 은 뒤에 `MM.DD` 가 따라와야만 꼬리로 본다 — "복습 자료" 같은 사람이 지은
65
65
  이름을 잘라 먹지 않으려는 것이다. */
66
- let 바탕 = 이름;
67
- let 세대 = 1;
66
+ let base = name;
67
+ let generation = 1;
68
68
  for (;;) {
69
- const m = 복습꼬리.exec(바탕);
69
+ const m = REVIEW_SUFFIX.exec(base);
70
70
  if (!m)
71
71
  break;
72
- 세대 = Math.max(세대, (m[1] ? Number(m[1]) : 1) + 1);
73
- 바탕 = 바탕.slice(0, m.index).trim();
72
+ generation = Math.max(generation, (m[1] ? Number(m[1]) : 1) + 1);
73
+ base = base.slice(0, m.index).trim();
74
74
  }
75
- return { 바탕, 회차: 세대 };
75
+ return { base, round: generation };
76
76
  }
77
77
  /**
78
78
  * 복습표 이름.
@@ -89,11 +89,11 @@ export function reviewTableName(original, today) {
89
89
  /* 지역 날짜가 아니라 KST 로 읽는다 — 이 날짜는 **표 이름에 저장되고** 같은 이름끼리
90
90
  겹치는지 세는 데 쓰인다. 기기 시간대를 따르면 같은 날 만든 표가 다른 날짜를 달고
91
91
  남아 회차 세기가 어긋난다. */
92
- const [, 월, 일] = toKstYmd(today).split('-');
93
- const 날짜 = `${월}.${일}`;
94
- const { 바탕, 회차: 세대 } = 바탕과회차(typeof original === 'string' ? { name: original } : original);
95
- const 회차 = 세대 >= 2 ? `${세대}차 ` : '';
96
- return `${바탕 || '단어표'} ${회차}복습 ${날짜}`;
92
+ const [, month, day] = toKstYmd(today).split('-');
93
+ const dateLabel = `${month}.${day}`;
94
+ const { base, round: generation } = baseAndRound(typeof original === 'string' ? { name: original } : original);
95
+ const round = generation >= 2 ? `${generation}차 ` : '';
96
+ return `${base || '단어표'} ${round}복습 ${dateLabel}`;
97
97
  }
98
98
  /**
99
99
  * 새로 만들 복습표에 **함께 저장할 메타** — 맨 처음 원본 표 id 와 이번이 몇 번째 복습인지.
@@ -106,7 +106,7 @@ export function reviewTableName(original, today) {
106
106
  export function reviewMeta(source) {
107
107
  return {
108
108
  reviewOf: source.reviewOf ?? source.id ?? undefined,
109
- reviewRound: 바탕과회차(source).회차,
109
+ reviewRound: baseAndRound(source).round,
110
110
  };
111
111
  }
112
112
  /**
@@ -165,6 +165,6 @@ export function labelOfCellKey(key) {
165
165
  */
166
166
  export function scoreSheetHeader(customerName, tableName, today) {
167
167
  /* 인쇄물에 찍히는 날짜다 — 치료실의 그날(KST)이어야 한다. */
168
- const 날짜 = formatYmd(today);
169
- return [customerName.trim(), 날짜, tableName.trim()].filter(Boolean).join(' · ');
168
+ const dateLabel = formatYmd(today);
169
+ return [customerName.trim(), dateLabel, tableName.trim()].filter(Boolean).join(' · ');
170
170
  }
@@ -1,14 +1,6 @@
1
1
  import type { TFunction } from 'i18next';
2
2
  import { type FilterPanelSection } from '../FilterPanel';
3
3
  import type { WordTableOrientation, WordTableContentType, WordTableCutLine, PageNumberPosition } from '../WordTable';
4
- /**
5
- * '표 설정'(단어표 표시 옵션) 공용 섹션 빌더·선택상태·핸들러.
6
- * 표시 전용 훅(useWordTableDisplaySettings)과 편집/페이지분할까지 있는 WordTableBlock이 기본 5개 설정
7
- * (구성·용지 방향·외곽선·절취선·구분선)을 여기서 공용으로 조립한다. 각 소비처는 자신의 표시 조건
8
- * (절취선=칸>1, 구분선=대립쌍 등)에 따라 섹션 포함 여부만 결정하고, WordTableBlock은 칸 수·페이지당
9
- * 개수·페이지 번호 섹션을 그 사이에 끼워 넣는다.
10
- */
11
- /** @public 구성(이미지/단어/표준발음/구어체발음) 다중 토글 섹션. */
12
4
  export declare function buildCompositionSection(t: TFunction, opts: {
13
5
  hasImage: boolean;
14
6
  hasColloquial: boolean;
@@ -41,9 +33,14 @@ export declare function buildItemsPerPageSection(t: TFunction, opts: {
41
33
  export declare function itemsPerPageFromChoice(n: number, itemCount: number): number;
42
34
  /** @public 페이지 번호 위치(왼쪽/중앙/오른쪽/미표시) 세그먼트 섹션 — 실제 2페이지 이상일 때만 노출. */
43
35
  export declare function buildPageNumberSection(t: TFunction): FilterPanelSection;
44
- /** @public 페이지 번호 위치 → filterSelected 표시값. */
45
- export declare const PAGE_NUM_POSITION_VALUE: Record<PageNumberPosition, string>;
46
- /** @public FilterPanel 선택값 → 페이지 번호 위치. */
36
+ /**
37
+ * @public FilterPanel 선택값 → 페이지 번호 위치.
38
+ *
39
+ * **섹션의 `value` 가 곧 코드다.** 전에는 `value` 가 한글(`'왼쪽'`)이라 여기서 되돌리는 표
40
+ * (`PAGE_NUM_POSITION_VALUE`)와 파서가 **둘 다** 필요했다 — 값을 코드로 돌리니 그 둘이
41
+ * 항등식이 되어 표를 걷었다(2026-10-13). *옮기는 표가 사라지는 것이 옳게 옮긴 표시다.*
42
+ * 모르는 값은 `'none'` 으로 떨어뜨린다(옛 한글 값이 어디선가 오더라도 번호를 안 찍는다).
43
+ */
47
44
  export declare function parsePageNumberPosition(value: string): PageNumberPosition;
48
45
  /** @public 기본 5개 설정의 filterSelected 엔트리(호출부가 자신의 추가 섹션과 spread). */
49
46
  export declare function buildTableSettingsSelected(t: TFunction, v: {
@@ -8,14 +8,21 @@ import { ITEMS_PER_PAGE_OPTIONS } from './wordTableBlockTypes';
8
8
  * 개수·페이지 번호 섹션을 그 사이에 끼워 넣는다.
9
9
  */
10
10
  /** @public 구성(이미지/단어/표준발음/구어체발음) 다중 토글 섹션. */
11
+ /**
12
+ * 켜고 끄는 절의 값 — **코드다.** 보일 글은 사전(`wordTable.filter.show`·`.hide`)이 쥔다.
13
+ * 외곽선·대립선·상단/하단 정보·절취선이 같은 짝을 쓰므로 한 자리에 둔다
14
+ * (한글 `'표시'`·`'미표시'` 에서 2026-10-13 옮겼다 — 사장님 지시 "모두 표준으로").
15
+ */
16
+ const SHOW = 'show';
17
+ const HIDE = 'hide';
11
18
  export function buildCompositionSection(t, opts) {
12
19
  return {
13
20
  label: t('wordTable.filter.composition', '구성'),
14
21
  items: [
15
- { value: '이미지', disabled: !opts.hasImage, displayLabel: t('wordTable.filter.image', '이미지') },
16
- { value: '단어', displayLabel: t('wordTable.filter.word', '단어') },
17
- { value: '표준 발음', displayLabel: t('wordTable.filter.standardPron', '표준 발음') },
18
- { value: '구어체 발음', disabled: !opts.hasColloquial, displayLabel: t('wordTable.filter.colloquialPron', '구어체 발음') },
22
+ { value: 'image', disabled: !opts.hasImage, displayLabel: t('wordTable.filter.image', '이미지') },
23
+ { value: 'word', displayLabel: t('wordTable.filter.word', '단어') },
24
+ { value: 'standardPron', displayLabel: t('wordTable.filter.standardPron', '표준 발음') },
25
+ { value: 'colloquialPron', disabled: !opts.hasColloquial, displayLabel: t('wordTable.filter.colloquialPron', '구어체 발음') },
19
26
  ],
20
27
  multiple: true,
21
28
  allOption: true,
@@ -26,8 +33,8 @@ export function buildOrientationSection(t) {
26
33
  return {
27
34
  label: t('wordTable.filter.paperOrientation', '용지 방향'),
28
35
  items: [
29
- { value: '가로', displayLabel: t('wordTable.filter.landscape', '가로') },
30
- { value: '세로', displayLabel: t('wordTable.filter.portrait', '세로') },
36
+ { value: 'landscape', displayLabel: t('wordTable.filter.landscape', '가로') },
37
+ { value: 'portrait', displayLabel: t('wordTable.filter.portrait', '세로') },
31
38
  ],
32
39
  display: 'segmented',
33
40
  };
@@ -37,8 +44,8 @@ export function buildBorderSection(t) {
37
44
  return {
38
45
  label: t('wordTable.filter.border', '외곽선'),
39
46
  items: [
40
- { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
41
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
47
+ { value: SHOW, displayLabel: t('wordTable.filter.show', '표시') },
48
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
42
49
  ],
43
50
  display: 'segmented',
44
51
  };
@@ -48,8 +55,8 @@ export function buildTopInfoSection(t) {
48
55
  return {
49
56
  label: t('wordTable.filter.topInfo', '상단 정보'),
50
57
  items: [
51
- { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
52
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
58
+ { value: SHOW, displayLabel: t('wordTable.filter.show', '표시') },
59
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
53
60
  ],
54
61
  display: 'segmented',
55
62
  };
@@ -59,8 +66,8 @@ export function buildBottomInfoSection(t) {
59
66
  return {
60
67
  label: t('wordTable.filter.bottomInfo', '하단 정보'),
61
68
  items: [
62
- { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
63
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
69
+ { value: SHOW, displayLabel: t('wordTable.filter.show', '표시') },
70
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
64
71
  ],
65
72
  display: 'segmented',
66
73
  };
@@ -70,10 +77,10 @@ export function buildCutLineSection(t) {
70
77
  return {
71
78
  label: t('wordTable.filter.cutLine', '절취선'),
72
79
  items: [
73
- { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
74
- { value: '점선', displayLabel: t('wordTable.filter.dotted', '점선') },
75
- { value: '코너', displayLabel: t('wordTable.filter.corner', '코너') },
76
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
80
+ { value: SHOW, displayLabel: t('wordTable.filter.show', '표시') },
81
+ { value: 'dashed', displayLabel: t('wordTable.filter.dotted', '점선') },
82
+ { value: 'corner', displayLabel: t('wordTable.filter.corner', '코너') },
83
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
77
84
  ],
78
85
  display: 'segmented',
79
86
  };
@@ -83,8 +90,8 @@ export function buildDivLineSection(t) {
83
90
  return {
84
91
  label: t('wordPrint.divLine', '대립선'),
85
92
  items: [
86
- { value: '표시', displayLabel: t('wordTable.filter.show', '표시') },
87
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
93
+ { value: SHOW, displayLabel: t('wordTable.filter.show', '표시') },
94
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
88
95
  ],
89
96
  display: 'segmented',
90
97
  };
@@ -115,35 +122,40 @@ export function buildPageNumberSection(t) {
115
122
  return {
116
123
  label: t('wordTable.filter.pageNumber', '페이지 번호'),
117
124
  items: [
118
- { value: '왼쪽', displayLabel: t('wordTable.filter.pageNumberLeft', '왼쪽') },
119
- { value: '중앙', displayLabel: t('wordTable.filter.pageNumberCenter', '중앙') },
120
- { value: '오른쪽', displayLabel: t('wordTable.filter.pageNumberRight', '오른쪽') },
121
- { value: '미표시', displayLabel: t('wordTable.filter.hide', '미표시') },
125
+ { value: 'left', displayLabel: t('wordTable.filter.pageNumberLeft', '왼쪽') },
126
+ { value: 'center', displayLabel: t('wordTable.filter.pageNumberCenter', '중앙') },
127
+ { value: 'right', displayLabel: t('wordTable.filter.pageNumberRight', '오른쪽') },
128
+ { value: HIDE, displayLabel: t('wordTable.filter.hide', '미표시') },
122
129
  ],
123
130
  display: 'segmented',
124
131
  };
125
132
  }
126
- /** @public 페이지 번호 위치 → filterSelected 표시값. */
127
- export const PAGE_NUM_POSITION_VALUE = { left: '왼쪽', center: '중앙', right: '오른쪽', none: '미표시' };
128
- /** @public FilterPanel 선택값 → 페이지 번호 위치. */
133
+ /**
134
+ * @public FilterPanel 선택값 → 페이지 번호 위치.
135
+ *
136
+ * **섹션의 `value` 가 곧 코드다.** 전에는 `value` 가 한글(`'왼쪽'`)이라 여기서 되돌리는 표
137
+ * (`PAGE_NUM_POSITION_VALUE`)와 파서가 **둘 다** 필요했다 — 값을 코드로 돌리니 그 둘이
138
+ * 항등식이 되어 표를 걷었다(2026-10-13). *옮기는 표가 사라지는 것이 옳게 옮긴 표시다.*
139
+ * 모르는 값은 `'none'` 으로 떨어뜨린다(옛 한글 값이 어디선가 오더라도 번호를 안 찍는다).
140
+ */
129
141
  export function parsePageNumberPosition(value) {
130
- return value === '왼쪽' ? 'left' : value === '중앙' ? 'center' : value === '오른쪽' ? 'right' : 'none';
142
+ return value === 'left' || value === 'center' || value === 'right' ? value : 'none';
131
143
  }
132
144
  /** @public 기본 5개 설정의 filterSelected 엔트리(호출부가 자신의 추가 섹션과 spread). */
133
145
  export function buildTableSettingsSelected(t, v) {
134
146
  return {
135
147
  [t('wordTable.filter.composition', '구성')]: v.contentTypes,
136
- [t('wordTable.filter.paperOrientation', '용지 방향')]: v.orientation === 'landscape' ? '가로' : '세로',
137
- [t('wordTable.filter.border', '외곽선')]: v.showOutline ? '표시' : '미표시',
148
+ [t('wordTable.filter.paperOrientation', '용지 방향')]: v.orientation,
149
+ [t('wordTable.filter.border', '외곽선')]: v.showOutline ? SHOW : HIDE,
138
150
  [t('wordTable.filter.cutLine', '절취선')]: v.cutLine,
139
- [t('wordPrint.divLine', '대립선')]: v.showDivLine ? '표시' : '미표시',
151
+ [t('wordPrint.divLine', '대립선')]: v.showDivLine ? SHOW : HIDE,
140
152
  /* **`undefined` 는 '안 쓴다' 다** — `false`('미표시')와 다르다. 띠를 안 쓰는 화면은
141
153
  값을 안 주므로 항목 자체를 안 넣는다. 지금은 절 목록에 그 절이 없어 어차피 안
142
154
  보이지만, 여기 죽은 항목을 남겨 두면 **요약이 절이 아니라 이 맵을 훑도록 바뀌는 날**
143
155
  쓰지도 않는 줄 둘이 따라 선다. 그렇게 될 뻔한 것을 말귀가 tarball 을 뜯어 보고
144
156
  짚었다(2026-09-30). 쪽 번호가 쓰던 꼴(`isPaginated ? {…} : {}`)과 같게 둔다. */
145
- ...(v.showTopInfo != null ? { [t('wordTable.filter.topInfo', '상단 정보')]: v.showTopInfo ? '표시' : '미표시' } : {}),
146
- ...(v.showBottomInfo != null ? { [t('wordTable.filter.bottomInfo', '하단 정보')]: v.showBottomInfo ? '표시' : '미표시' } : {}),
157
+ ...(v.showTopInfo != null ? { [t('wordTable.filter.topInfo', '상단 정보')]: v.showTopInfo ? SHOW : HIDE } : {}),
158
+ ...(v.showBottomInfo != null ? { [t('wordTable.filter.bottomInfo', '하단 정보')]: v.showBottomInfo ? SHOW : HIDE } : {}),
147
159
  };
148
160
  }
149
161
  /**
@@ -161,11 +173,11 @@ export function applyTableSettingsSelect(t, value, sectionLabel, s) {
161
173
  return true;
162
174
  }
163
175
  if (sectionLabel === t('wordTable.filter.paperOrientation', '용지 방향')) {
164
- s.setOrientation(value === '가로' ? 'landscape' : 'portrait');
176
+ s.setOrientation(value === 'landscape' ? 'landscape' : 'portrait');
165
177
  return true;
166
178
  }
167
179
  if (sectionLabel === t('wordTable.filter.border', '외곽선')) {
168
- s.setShowOutline(value === '표시');
180
+ s.setShowOutline(value === SHOW);
169
181
  return true;
170
182
  }
171
183
  if (sectionLabel === t('wordTable.filter.cutLine', '절취선')) {
@@ -173,15 +185,15 @@ export function applyTableSettingsSelect(t, value, sectionLabel, s) {
173
185
  return true;
174
186
  }
175
187
  if (sectionLabel === t('wordPrint.divLine', '대립선')) {
176
- s.setShowDivLine(value === '표시');
188
+ s.setShowDivLine(value === SHOW);
177
189
  return true;
178
190
  }
179
191
  if (sectionLabel === t('wordTable.filter.topInfo', '상단 정보')) {
180
- s.setShowTopInfo?.(value === '표시');
192
+ s.setShowTopInfo?.(value === SHOW);
181
193
  return true;
182
194
  }
183
195
  if (sectionLabel === t('wordTable.filter.bottomInfo', '하단 정보')) {
184
- s.setShowBottomInfo?.(value === '표시');
196
+ s.setShowBottomInfo?.(value === SHOW);
185
197
  return true;
186
198
  }
187
199
  return false;