@ihabdevteam/core 0.322.0 → 0.324.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 +557 -0
- package/dist/components.cjs.js +183 -183
- package/dist/components.esm.css +1 -1
- package/dist/hooks.cjs.js +3 -3
- package/dist/i18n.cjs.js +3 -3
- package/dist/ihabdevteam-core.cjs.js +187 -187
- package/dist/ihabdevteam-core.d.ts +55 -17
- package/dist/packages/core/src/components/Accordion.js +3 -3
- package/dist/packages/core/src/components/Alert.js +2 -2
- package/dist/packages/core/src/components/BarChart.js +120 -119
- package/dist/packages/core/src/components/BottomNav.js +18 -18
- package/dist/packages/core/src/components/BulkBar.js +25 -25
- package/dist/packages/core/src/components/Button.js +16 -16
- package/dist/packages/core/src/components/Calendar.js +17 -17
- package/dist/packages/core/src/components/ChartSection.js +30 -30
- package/dist/packages/core/src/components/CountTile.js +38 -38
- package/dist/packages/core/src/components/DatePicker.js +59 -59
- package/dist/packages/core/src/components/Dialog.js +14 -14
- package/dist/packages/core/src/components/Effect/EffectPartyPopperHost.js +8 -8
- package/dist/packages/core/src/components/FilterPanel.js +6 -6
- package/dist/packages/core/src/components/FilterSectionInfo.js +6 -6
- package/dist/packages/core/src/components/GameIntro.js +1 -1
- package/dist/packages/core/src/components/Icon.js +2 -2
- package/dist/packages/core/src/components/ItemActions.js +16 -16
- package/dist/packages/core/src/components/LandingHeader.js +6 -6
- package/dist/packages/core/src/components/LineChart.js +24 -24
- package/dist/packages/core/src/components/Loader.js +5 -5
- package/dist/packages/core/src/components/NoticeBox.js +3 -3
- package/dist/packages/core/src/components/PageTitle.js +2 -2
- package/dist/packages/core/src/components/Pagination.js +4 -4
- package/dist/packages/core/src/components/Panel.js +2 -2
- package/dist/packages/core/src/components/PanelRow.js +6 -13
- package/dist/packages/core/src/components/PassCard/PassCard.js +9 -9
- package/dist/packages/core/src/components/PassCard/passCardProduct.js +2 -2
- package/dist/packages/core/src/components/PaymentPlan.js +5 -5
- package/dist/packages/core/src/components/Popup/ConfirmPopup.js +29 -29
- package/dist/packages/core/src/components/Popup/CouponInputPopup.js +2 -2
- package/dist/packages/core/src/components/Popup/DeviceSideTable.js +18 -25
- package/dist/packages/core/src/components/Popup/ListPopup.js +3 -3
- package/dist/packages/core/src/components/Popup/LoadTablePopup.js +7 -7
- package/dist/packages/core/src/components/Popup/Popup.js +27 -27
- package/dist/packages/core/src/components/Popup/SaveTablePopup.js +5 -5
- package/dist/packages/core/src/components/Popup/TrainingResultPopup.js +4 -4
- package/dist/packages/core/src/components/Popup/customerDetailUtils.js +18 -18
- package/dist/packages/core/src/components/Popup/useDiscardGuard.js +4 -4
- package/dist/packages/core/src/components/ProgressIndicator.js +5 -5
- package/dist/packages/core/src/components/PromoBannerBg/promoBannerBg.js +16 -16
- package/dist/packages/core/src/components/Rating.js +20 -20
- package/dist/packages/core/src/components/Report/ReportDocument.js +21 -21
- package/dist/packages/core/src/components/RingChart.js +5 -5
- package/dist/packages/core/src/components/SectionHeadFloat.js +15 -15
- package/dist/packages/core/src/components/SegmentedControl.js +34 -34
- package/dist/packages/core/src/components/SideNav.js +37 -37
- package/dist/packages/core/src/components/Slider.js +2 -2
- package/dist/packages/core/src/components/SoundCompass.js +5 -5
- package/dist/packages/core/src/components/Table.js +257 -98
- package/dist/packages/core/src/components/Tabs.js +12 -12
- package/dist/packages/core/src/components/TextField.js +34 -34
- package/dist/packages/core/src/components/Toast.js +6 -6
- package/dist/packages/core/src/components/Tooltip/MenuTooltip.js +4 -4
- package/dist/packages/core/src/components/Tooltip/Tooltip.js +22 -22
- package/dist/packages/core/src/components/Tooltip/TrainingTooltip.js +4 -4
- package/dist/packages/core/src/components/TopBanner.js +28 -28
- package/dist/packages/core/src/components/Training/AudioPlayerWaveForm.js +11 -11
- package/dist/packages/core/src/components/Training/CategoryIcon.js +2 -2
- package/dist/packages/core/src/components/Training/NoisePlayerContext.js +12 -12
- package/dist/packages/core/src/components/Training/NoiseSettingsTooltip.js +2 -2
- package/dist/packages/core/src/components/Training/TrainingBlock.js +11 -11
- package/dist/packages/core/src/components/Training/TrainingBlockButton.js +10 -10
- package/dist/packages/core/src/components/Training/TrainingBlockGrid.js +21 -21
- package/dist/packages/core/src/components/Training/TrainingCard.css +13 -1
- package/dist/packages/core/src/components/Training/TrainingCard.js +2 -2
- package/dist/packages/core/src/components/Training/TrainingCardGroup.js +6 -6
- package/dist/packages/core/src/components/Training/TrainingPagePopup.js +81 -81
- package/dist/packages/core/src/components/Training/TrainingPagePopupBottom.js +17 -17
- package/dist/packages/core/src/components/Training/TrainingStepAudioPlayer.js +127 -127
- package/dist/packages/core/src/components/Training/TrainingStepCard.js +18 -18
- package/dist/packages/core/src/components/Training/TrainingStepConfirmWithText.js +4 -4
- package/dist/packages/core/src/components/Training/TrainingStepOrderList.js +12 -12
- package/dist/packages/core/src/components/Training/TrainingStepTextBox.js +12 -12
- package/dist/packages/core/src/components/Training/TrainingStepTitle.js +4 -4
- package/dist/packages/core/src/components/Training/TrainingWordCard.js +17 -17
- package/dist/packages/core/src/components/Training/WordTablePopup.js +5 -5
- package/dist/packages/core/src/components/Training/audioPlaybackRules.js +8 -8
- package/dist/packages/core/src/components/Training/audioTimeline.js +25 -25
- package/dist/packages/core/src/components/Training/oneShotSound.js +13 -13
- package/dist/packages/core/src/components/Training/trainingMissStats.js +20 -20
- package/dist/packages/core/src/components/Training/trainingPopupUtils.js +7 -7
- package/dist/packages/core/src/components/Training/useAudioPreview.js +15 -15
- package/dist/packages/core/src/components/Training/useFloatingFocus.js +14 -14
- package/dist/packages/core/src/components/Training/useNoiseFade.js +22 -22
- package/dist/packages/core/src/components/Training/useObjectUrls.js +2 -2
- package/dist/packages/core/src/components/Training/usePlaybackSequencer.d.ts +2 -2
- package/dist/packages/core/src/components/Training/usePlaybackSequencer.js +23 -23
- package/dist/packages/core/src/components/Training/useProgressTicker.js +33 -33
- package/dist/packages/core/src/components/Training/useTTSPlayback.js +17 -17
- package/dist/packages/core/src/components/Training/useWaveReady.js +11 -11
- package/dist/packages/core/src/components/UpdateAlert.js +6 -6
- package/dist/packages/core/src/components/Word/PhonemeSelectBlock.js +7 -1
- package/dist/packages/core/src/components/Word/TableFilterPanel.js +3 -3
- package/dist/packages/core/src/components/Word/WordSearchResultBlock.js +10 -10
- package/dist/packages/core/src/components/Word/WordTableBlock.js +28 -28
- package/dist/packages/core/src/components/Word/WordTableButton.css +16 -2
- package/dist/packages/core/src/components/Word/WordTableThumbnail.css +6 -1
- package/dist/packages/core/src/components/Word/generatedDraft.js +14 -14
- package/dist/packages/core/src/components/Word/useWordTableDisplaySettings.js +7 -7
- package/dist/packages/core/src/components/Word/wordScoreStats.js +15 -15
- package/dist/packages/core/src/components/Word/wordTablePrint.js +10 -10
- package/dist/packages/core/src/components/Word/wordTableRecommend.js +11 -11
- package/dist/packages/core/src/components/Word/wordTableReview.js +28 -28
- package/dist/packages/core/src/components/Word/wordTableSettings.d.ts +8 -11
- package/dist/packages/core/src/components/Word/wordTableSettings.js +48 -36
- package/dist/packages/core/src/components/WordTable.js +130 -130
- package/dist/packages/core/src/components/barChartData.d.ts +16 -1
- package/dist/packages/core/src/components/barChartData.js +49 -29
- package/dist/packages/core/src/components/barChartTypes.js +8 -8
- package/dist/packages/core/src/components/tableTrackList.js +11 -11
- package/dist/packages/core/src/components/updateAlertStack.js +28 -28
- package/dist/packages/core/src/components/useBarChartControl.js +4 -6
- package/dist/packages/core/src/components/useComboboxSuggestions.js +17 -17
- package/dist/packages/core/src/components/useToastLifecycle.js +18 -18
- package/dist/packages/core/src/components/wordTableLayout.d.ts +17 -4
- package/dist/packages/core/src/components/wordTableLayout.js +5 -5
- package/dist/packages/core/src/context/I18nProvider.js +6 -6
- package/dist/packages/core/src/hooks/focusReturn.js +27 -27
- package/dist/packages/core/src/hooks/inputModality.js +13 -13
- package/dist/packages/core/src/hooks/touchToggle.js +39 -39
- package/dist/packages/core/src/hooks/useAnchoredMenu.js +30 -30
- package/dist/packages/core/src/hooks/useDailyTrainingSelection.js +28 -28
- package/dist/packages/core/src/hooks/useDocumentTitle.js +10 -10
- package/dist/packages/core/src/hooks/useEditableList.js +4 -4
- package/dist/packages/core/src/hooks/useFocusTrap.js +2 -2
- package/dist/packages/core/src/hooks/useFontScale.js +6 -6
- package/dist/packages/core/src/hooks/useIcon.js +7 -7
- package/dist/packages/core/src/hooks/useListControls.js +2 -2
- package/dist/packages/core/src/hooks/usePageResetOnChange.js +3 -3
- package/dist/packages/core/src/hooks/usePasswordChange.js +4 -4
- package/dist/packages/core/src/hooks/usePendingPress.js +7 -7
- package/dist/packages/core/src/hooks/useRelativeDay.js +4 -4
- package/dist/packages/core/src/hooks/useSoundCompassExam.js +6 -6
- package/dist/packages/core/src/hooks/useTablePaging.d.ts +0 -11
- package/dist/packages/core/src/hooks/useTablePaging.js +29 -34
- package/dist/packages/core/src/hooks/useTrainingSessionLog.js +35 -35
- package/dist/packages/core/src/hooks/useVisitSchedule.js +4 -4
- package/dist/packages/core/src/hooks/useWordAttributeFilter.js +14 -14
- package/dist/packages/core/src/hooks/useWordMeanings.js +5 -5
- package/dist/packages/core/src/hooks/useWordTrainingFilter.js +7 -7
- package/dist/packages/core/src/i18n/locales/en.json +14 -2
- package/dist/packages/core/src/i18n/locales/ko.json +13 -1
- package/dist/packages/core/src/types/wordSearch.d.ts +9 -0
- package/dist/packages/core/src/utils/audioMeter.js +5 -5
- package/dist/packages/core/src/utils/audioPeaks.d.ts +1 -1
- package/dist/packages/core/src/utils/audioPeaks.js +18 -18
- package/dist/packages/core/src/utils/blockGrid.js +4 -4
- package/dist/packages/core/src/utils/chunkSkew.js +9 -9
- package/dist/packages/core/src/utils/clipboard.js +3 -3
- package/dist/packages/core/src/utils/dailySelectionUtils.js +12 -12
- package/dist/packages/core/src/utils/date.js +12 -12
- package/dist/packages/core/src/utils/devWarn.js +4 -4
- package/dist/packages/core/src/utils/deviceKind.d.ts +37 -7
- package/dist/packages/core/src/utils/deviceKind.js +53 -10
- package/dist/packages/core/src/utils/errorMessage.js +7 -7
- package/dist/packages/core/src/utils/filterPanelSummary.js +14 -14
- package/dist/packages/core/src/utils/format.js +4 -4
- package/dist/packages/core/src/utils/getTrainingData.js +9 -9
- package/dist/packages/core/src/utils/imageConfig.js +17 -17
- package/dist/packages/core/src/utils/koreanSyllable.js +18 -18
- package/dist/packages/core/src/utils/navScroll.js +2 -2
- package/dist/packages/core/src/utils/phonemeConvert.d.ts +7 -0
- package/dist/packages/core/src/utils/phonemeConvert.js +19 -10
- package/dist/packages/core/src/utils/phonemeGroups.js +2 -2
- package/dist/packages/core/src/utils/phonemePairSearch.d.ts +1 -0
- package/dist/packages/core/src/utils/phonemePairSearch.js +129 -105
- package/dist/packages/core/src/utils/phonemePairSearchTypes.d.ts +2 -0
- package/dist/packages/core/src/utils/phonemeSectionCodes.d.ts +52 -0
- package/dist/packages/core/src/utils/phonemeSectionCodes.js +76 -0
- package/dist/packages/core/src/utils/prefetchChunk.js +6 -6
- package/dist/packages/core/src/utils/safeHref.js +4 -4
- package/dist/packages/core/src/utils/savedWordTables.js +5 -5
- package/dist/packages/core/src/utils/speak.js +12 -12
- package/dist/packages/core/src/utils/textSort.d.ts +0 -10
- package/dist/packages/core/src/utils/textSort.js +38 -48
- package/dist/packages/core/src/utils/theme.js +3 -3
- package/dist/packages/core/src/utils/trainingItemResults.js +3 -3
- package/dist/packages/core/src/utils/ttsConfig.js +2 -2
- package/dist/packages/core/src/utils/wordAttributeFilterCodes.d.ts +1 -1
- package/dist/packages/core/src/utils/wordAttributeFilterCodes.js +65 -45
- package/dist/packages/core/src/utils/wordContrast.js +3 -3
- package/dist/packages/core/src/utils/wordPairIndex.js +4 -4
- package/dist/packages/core/src/utils/wordTrainingGenerators.js +4 -4
- package/dist/packages/core/src/utils/wordTrainingPool.js +15 -15
- package/dist/packages/core/src/utils/wordTrainingRuntime.js +6 -6
- package/dist/packages/core/src/utils/wornDate.d.ts +3 -3
- package/dist/packages/core/src/utils/wornDate.js +14 -14
- package/dist/packages/core/src/version.d.ts +1 -1
- package/dist/packages/core/src/version.js +1 -1
- package/dist/utils.cjs.js +4 -4
- package/package.json +1 -1
|
@@ -417,12 +417,12 @@ async function _buildUsablePool(opts) {
|
|
|
417
417
|
let posContrastMap = null;
|
|
418
418
|
if (posContrast) {
|
|
419
419
|
const mapKey = _posContrastCacheKey(opts);
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
posContrastMap =
|
|
423
|
-
?
|
|
420
|
+
const imageOkSet = excludeNoImage ? getImageOkWordSet() : null;
|
|
421
|
+
const cached = _posContrastCache.get(mapKey);
|
|
422
|
+
posContrastMap = cached && cached.imageOkSet === imageOkSet
|
|
423
|
+
? cached.map
|
|
424
424
|
: buildMultiPartPosContrast(composition, allOkArr, decompOf, sameStructureOnly, phonemeView, pronOfWord);
|
|
425
|
-
_posContrastCache.set(mapKey, {
|
|
425
|
+
_posContrastCache.set(mapKey, { imageOkSet, map: posContrastMap });
|
|
426
426
|
}
|
|
427
427
|
// candidates 크기 제한 — 이미지 필터 이후이므로 okCandidates 기반
|
|
428
428
|
const RANDOM_CAND_CAP = 500; // random: classifyPairDifficulty 없으나 루프 자체 제한
|
|
@@ -471,28 +471,28 @@ async function _buildUsablePool(opts) {
|
|
|
471
471
|
else if (useRandomPool) {
|
|
472
472
|
// 'random' 또는 null(difficulty:false 타입): 음운론적 제약은 없지만,
|
|
473
473
|
// 정답과 오답의 음절수는 같아야 한다(단어 길이만으로 정답을 짐작하지 못하도록) — 본 단어와 다른 단어 + 음절수(글자수) 동일
|
|
474
|
-
const
|
|
474
|
+
const canUse = (other) => other !== w.w && other.length === w.w.length && pronOfWord(other) !== wPron;
|
|
475
475
|
/* 셈(fullCount — 가능 단어 수 안내)은 **서로 소리가 다른 오답이 보기 수 − 1 개** 있는지까지만 본다(countUsableWords 가 그
|
|
476
476
|
기준으로 센다). 2.2만 후보마다 600개를 끝까지 걸러 칩 한 번에 300ms 넘게 멈췄다. */
|
|
477
477
|
if (opts.fullCount) {
|
|
478
478
|
const need = Math.max(1, (opts.choicesPerItem ?? 3) - 1);
|
|
479
|
-
const
|
|
480
|
-
const
|
|
479
|
+
const picked = [];
|
|
480
|
+
const prons = new Set();
|
|
481
481
|
for (const other of distractorPool) {
|
|
482
|
-
if (
|
|
482
|
+
if (!canUse(other))
|
|
483
483
|
continue;
|
|
484
484
|
const p = pronOfWord(other);
|
|
485
|
-
if (
|
|
485
|
+
if (prons.has(p))
|
|
486
486
|
continue;
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (
|
|
487
|
+
prons.add(p);
|
|
488
|
+
picked.push(other);
|
|
489
|
+
if (picked.length >= need)
|
|
490
490
|
break;
|
|
491
491
|
}
|
|
492
|
-
usable =
|
|
492
|
+
usable = picked;
|
|
493
493
|
}
|
|
494
494
|
else
|
|
495
|
-
usable = distractorPool.filter(
|
|
495
|
+
usable = distractorPool.filter(canUse);
|
|
496
496
|
}
|
|
497
497
|
else {
|
|
498
498
|
// cho/jung/jong: 발음 기반 pairIndex에서 해당 종류 대립쌍 조회(공용 엔진). 구조 필터는 후처리에서 일괄.
|
|
@@ -73,10 +73,10 @@ async function genIncluded(opts) {
|
|
|
73
73
|
const syllables = [...pron]; // 한 글자 = 한 음절
|
|
74
74
|
/* 음소를 골랐으면 **그 음소를 가진 음절**을 들려준다 — 전에는 아무 음절이나 골라 초성 ㄱ 을 골라도 '가방' 의 '방' 을
|
|
75
75
|
들려주었다(고른 음소와 무관한 훈련). 들리는 음절(발음)에 그 음소가 없으면 전처럼 아무 음절. */
|
|
76
|
-
const
|
|
76
|
+
const pickedPart = comp && primarySelPart(comp)
|
|
77
77
|
? syllables.filter(s => { const p = parseSyllable(s); return !!p && syllMatchesComp(p, comp); })
|
|
78
78
|
: [];
|
|
79
|
-
const targetSyllable = pickOne(
|
|
79
|
+
const targetSyllable = pickOne(pickedPart.length ? pickedPart : syllables);
|
|
80
80
|
if (!targetSyllable)
|
|
81
81
|
continue;
|
|
82
82
|
// 오답: targetSyllable이 발음에 포함되지 않고, 정답과 음절수(글자수)가 같으며, 발음이 다른 단어.
|
|
@@ -357,7 +357,7 @@ async function genMerge3Syll(opts) {
|
|
|
357
357
|
}
|
|
358
358
|
/* 탈락 문제의 '실단어' 집합 — '이미지 있는 단어만' 이면 이미지 있는 낱말로. 전에는 늘 전체 낱말이라, 이미지만 켠(앱 기본) 탈락 카드의
|
|
359
359
|
정답·오답이 이미지 없는 낱말(관상 → 상·땅·탕)로 나와 글자를 숨긴 카드가 빈칸이 됐다. 음절 바꾸기와 같은 방식. */
|
|
360
|
-
function
|
|
360
|
+
function droppedWordSet(opts) {
|
|
361
361
|
const all = MVP.map(w => w.w);
|
|
362
362
|
return opts.excludeNoImage ? filterByCachedImage(all) : new Set(all);
|
|
363
363
|
}
|
|
@@ -368,7 +368,7 @@ async function genDrop1From2Syll(opts) {
|
|
|
368
368
|
// 편집기와 동일한 대립쌍 오답을 item에 심는다(공유 코어 buildDropContrastProblem).
|
|
369
369
|
// 러너(WordManipulationTrainingPagePopup)가 preset distractors를 그대로 쓰므로 자동생성도 편집기 품질이 된다.
|
|
370
370
|
const pronMap = getPronMap();
|
|
371
|
-
const wordSet =
|
|
371
|
+
const wordSet = droppedWordSet(opts);
|
|
372
372
|
const phonemeView = opts.phonemeView ?? 'char';
|
|
373
373
|
const out = [];
|
|
374
374
|
for (const e of shuffle(pool)) {
|
|
@@ -398,7 +398,7 @@ async function genDrop1From3Syll(opts) {
|
|
|
398
398
|
const pool = (await buildUsablePool({ ...opts })).filter(e => e.word.s === 3);
|
|
399
399
|
// 편집기와 동일한 대립쌍 오답을 item에 심는다(공유 코어 buildDropContrast3Problem).
|
|
400
400
|
const pronMap = getPronMap();
|
|
401
|
-
const wordSet =
|
|
401
|
+
const wordSet = droppedWordSet(opts);
|
|
402
402
|
const phonemeView = opts.phonemeView ?? 'char';
|
|
403
403
|
const out = [];
|
|
404
404
|
for (const e of shuffle(pool)) {
|
|
@@ -436,7 +436,7 @@ async function genDropCompound(opts) {
|
|
|
436
436
|
// 2음절 낱말은 1음절 조각 둘로만 나뉘어 합성어가 될 수 없다(buildDropCompoundProblem) — 3음절부터
|
|
437
437
|
const pool = (await buildUsablePool({ ...opts })).filter(e => e.word.s >= 3);
|
|
438
438
|
const pronMap = getPronMap();
|
|
439
|
-
const wordSet =
|
|
439
|
+
const wordSet = droppedWordSet(opts);
|
|
440
440
|
const phonemeView = opts.phonemeView ?? 'char';
|
|
441
441
|
const out = [];
|
|
442
442
|
for (const e of shuffle(pool)) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 타입은 문자열이지만 서버에서는 **월·일이 null 로 오기도 한다**(연도만 적은 옛 기록). 그대로 끼우면 화면에
|
|
5
5
|
* `2026.null.null` 이 찍혔고, 정렬 열쇠를 만들 때는 `null.padStart` 에서 표가 통째로 터졌다. 빈 값은 '' 로 다룬다.
|
|
6
6
|
*/
|
|
7
|
-
type
|
|
7
|
+
type CellValue = string | number | null | undefined;
|
|
8
8
|
/**
|
|
9
9
|
* 화면에 적을 착용일.
|
|
10
10
|
*
|
|
@@ -18,7 +18,7 @@ type 칸값 = string | number | null | undefined;
|
|
|
18
18
|
* `lang` 을 안 주면 **예전 그대로** 점 꼴이다(`2026.09.09`) — 부르는 자리가 말을 모르는 곳도 있을
|
|
19
19
|
* 수 있어 깨지지 않게 둔다. 화면에 그리는 자리는 주는 쪽이 맞다.
|
|
20
20
|
*/
|
|
21
|
-
export declare function formatWornDate(year:
|
|
21
|
+
export declare function formatWornDate(year: CellValue, month: CellValue, day: CellValue, lang?: string): string;
|
|
22
22
|
/** 착용일 정렬 열쇠 — 자리수를 채워(`2026-05-02`) 글자 비교가 날짜 차례와 같게. 연도가 없으면 ''. */
|
|
23
|
-
export declare function wornDateSortKey(year:
|
|
23
|
+
export declare function wornDateSortKey(year: CellValue, month: CellValue, day: CellValue): string;
|
|
24
24
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatDateLocale } from './date';
|
|
2
|
-
const
|
|
2
|
+
const text = (v) => (v == null ? '' : String(v).trim());
|
|
3
3
|
/**
|
|
4
4
|
* 화면에 적을 착용일.
|
|
5
5
|
*
|
|
@@ -14,7 +14,7 @@ const 글자 = (v) => (v == null ? '' : String(v).trim());
|
|
|
14
14
|
* 수 있어 깨지지 않게 둔다. 화면에 그리는 자리는 주는 쪽이 맞다.
|
|
15
15
|
*/
|
|
16
16
|
export function formatWornDate(year, month, day, lang) {
|
|
17
|
-
const y =
|
|
17
|
+
const y = text(year), m = text(month), d = text(day);
|
|
18
18
|
if (lang && y && m && d) {
|
|
19
19
|
/* 자리수를 채워 ISO 로 만든다 — `formatDateLocale` 이 읽는 꼴. */
|
|
20
20
|
const iso = `${y.padStart(4, '0')}-${m.padStart(2, '0')}-${d.padStart(2, '0')}`;
|
|
@@ -28,23 +28,23 @@ export function formatWornDate(year, month, day, lang) {
|
|
|
28
28
|
* *이 가름은 못이 안 울어서 찾았다* — `&& m && d` 조건만 깨뜨려 봤을 때는 조용했다(그때는
|
|
29
29
|
* `2026-00-00` 이 **못 읽는 날짜**라 저절로 떨어졌다). 못이 안 울면 **무엇이 막고 있나**를 묻는다.
|
|
30
30
|
*/
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
31
|
+
const date = new Date(iso);
|
|
32
|
+
const roundTrips = !Number.isNaN(date.getTime()) && date.toISOString().slice(0, 10) === iso;
|
|
33
|
+
if (roundTrips) {
|
|
34
|
+
const localized = formatDateLocale(iso, lang);
|
|
35
|
+
if (localized)
|
|
36
|
+
return localized;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
const
|
|
40
|
-
while (
|
|
41
|
-
|
|
42
|
-
return
|
|
39
|
+
const parts = [y, m, d];
|
|
40
|
+
while (parts.length > 0 && parts[parts.length - 1] === '')
|
|
41
|
+
parts.pop();
|
|
42
|
+
return parts.join('.');
|
|
43
43
|
}
|
|
44
44
|
/** 착용일 정렬 열쇠 — 자리수를 채워(`2026-05-02`) 글자 비교가 날짜 차례와 같게. 연도가 없으면 ''. */
|
|
45
45
|
export function wornDateSortKey(year, month, day) {
|
|
46
|
-
const y =
|
|
46
|
+
const y = text(year);
|
|
47
47
|
if (!y)
|
|
48
48
|
return '';
|
|
49
|
-
return `${y}-${
|
|
49
|
+
return `${y}-${text(month).padStart(2, '0')}-${text(day).padStart(2, '0')}`;
|
|
50
50
|
}
|