@wonjin-dev/reacts 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,8 +27,8 @@ function styleInject(css, ref) {
27
27
  }
28
28
  }
29
29
 
30
- var css_248z$1 = ".styles-module__typography___uJJgf{font-family:inherit;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5}.styles-module__typography_color_grey900___tH77b{color:#21252a}.styles-module__typography_color_grey800___f4wMy{color:#3b3f45}.styles-module__typography_color_grey700___GSJui{color:#737373}.styles-module__typography_color_grey600___x6U6a{color:#7f848a}.styles-module__typography_color_grey500___VffNJ{color:#878e98}.styles-module__typography_color_grey400___h8LXZ{color:#a1a6ae}.styles-module__typography_color_grey300___CrH9u{color:#bcc0c6}.styles-module__typography_color_grey200___4e7wo{color:#d8dbe0}.styles-module__typography_color_grey100___s2JGa{color:#f1f3f5}.styles-module__typography_size_sm___IXCiS{font-size:.75rem}.styles-module__typography_size_md___vBKHL{font-size:1rem}.styles-module__typography_size_lg___UE2ty{font-size:1.125rem}.styles-module__typography_size_xl___e2zNJ{font-size:1.375rem}.styles-module__typography_size_2xl___XPIIz{font-size:1.75rem}.styles-module__typography_size_3xl___6dl0M{font-size:2rem}.styles-module__typography_weight_400___LwHSh{font-weight:400}.styles-module__typography_weight_500___QwNXS{font-weight:500}.styles-module__typography_weight_600___tWEhF{font-weight:600}.styles-module__typography_weight_700___V455e{font-weight:700}.styles-module__typography_deco_normal___LdTNr{font-style:normal}.styles-module__typography_deco_italic___MXbnH{font-style:italic}.styles-module__typography_deco_underline___cVSHd{text-decoration:underline;text-decoration-skip-ink:none}.styles-module__typography_deco_line-through___BISKr{text-decoration:line-through}.styles-module__typography_highlight_underline___a-iY0{display:inline-block;position:relative;z-index:1}.styles-module__typography_highlight_underline___a-iY0:after{background-color:#ffe600;border-radius:.1375em;bottom:.125rem;content:\"\";height:.4em;left:0;opacity:.7;position:absolute;width:100%;z-index:-1}";
31
- var styles$1 = {"typography":"styles-module__typography___uJJgf","typography_color_grey900":"styles-module__typography_color_grey900___tH77b","typography_color_grey800":"styles-module__typography_color_grey800___f4wMy","typography_color_grey700":"styles-module__typography_color_grey700___GSJui","typography_color_grey600":"styles-module__typography_color_grey600___x6U6a","typography_color_grey500":"styles-module__typography_color_grey500___VffNJ","typography_color_grey400":"styles-module__typography_color_grey400___h8LXZ","typography_color_grey300":"styles-module__typography_color_grey300___CrH9u","typography_color_grey200":"styles-module__typography_color_grey200___4e7wo","typography_color_grey100":"styles-module__typography_color_grey100___s2JGa","typography_size_sm":"styles-module__typography_size_sm___IXCiS","typography_size_md":"styles-module__typography_size_md___vBKHL","typography_size_lg":"styles-module__typography_size_lg___UE2ty","typography_size_xl":"styles-module__typography_size_xl___e2zNJ","typography_size_2xl":"styles-module__typography_size_2xl___XPIIz","typography_size_3xl":"styles-module__typography_size_3xl___6dl0M","typography_weight_400":"styles-module__typography_weight_400___LwHSh","typography_weight_500":"styles-module__typography_weight_500___QwNXS","typography_weight_600":"styles-module__typography_weight_600___tWEhF","typography_weight_700":"styles-module__typography_weight_700___V455e","typography_deco_normal":"styles-module__typography_deco_normal___LdTNr","typography_deco_italic":"styles-module__typography_deco_italic___MXbnH","typography_deco_underline":"styles-module__typography_deco_underline___cVSHd","typography_deco_line-through":"styles-module__typography_deco_line-through___BISKr","typography_highlight_underline":"styles-module__typography_highlight_underline___a-iY0"};
30
+ var css_248z$1 = ".styles-module__typography___uJJgf{font-family:inherit;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5}.styles-module__typography_color_grey900___tH77b{color:#21252a}.styles-module__typography_color_grey800___f4wMy{color:#3b3f45}.styles-module__typography_color_grey700___GSJui{color:#737373}.styles-module__typography_color_grey600___x6U6a{color:#7f848a}.styles-module__typography_color_grey500___VffNJ{color:#878e98}.styles-module__typography_color_grey400___h8LXZ{color:#a1a6ae}.styles-module__typography_color_grey300___CrH9u{color:#bcc0c6}.styles-module__typography_color_grey200___4e7wo{color:#d8dbe0}.styles-module__typography_color_grey100___s2JGa{color:#f1f3f5}.styles-module__typography_size_sm___IXCiS{font-size:.75rem}.styles-module__typography_size_md___vBKHL{font-size:1rem}.styles-module__typography_size_lg___UE2ty{font-size:1.125rem}.styles-module__typography_size_xl___e2zNJ{font-size:1.375rem}.styles-module__typography_size_2xl___XPIIz{font-size:1.75rem}.styles-module__typography_size_3xl___6dl0M{font-size:2rem}.styles-module__typography_weight_400___LwHSh{font-weight:400}.styles-module__typography_weight_500___QwNXS{font-weight:500}.styles-module__typography_weight_600___tWEhF{font-weight:600}.styles-module__typography_weight_700___V455e{font-weight:700}.styles-module__typography_deco_normal___LdTNr{font-style:normal}.styles-module__typography_deco_italic___MXbnH{font-style:italic}.styles-module__typography_deco_underline___cVSHd{text-decoration:underline;text-decoration-skip-ink:none}.styles-module__typography_deco_line-through___BISKr{text-decoration:line-through}.styles-module__typography_highlight_underline___a-iY0{display:inline-block;position:relative;z-index:1}.styles-module__typography_highlight_underline___a-iY0:after{background-color:#ffe600;border-radius:.1375em;bottom:.125rem;content:\"\";height:.4em;left:0;opacity:.7;position:absolute;width:100%;z-index:-1}.styles-module__typography_highlight_left___3rZDb{border-left:.25rem;border-color:#ffe600;padding-left:.1375rem}";
31
+ var styles$1 = {"typography":"styles-module__typography___uJJgf","typography_color_grey900":"styles-module__typography_color_grey900___tH77b","typography_color_grey800":"styles-module__typography_color_grey800___f4wMy","typography_color_grey700":"styles-module__typography_color_grey700___GSJui","typography_color_grey600":"styles-module__typography_color_grey600___x6U6a","typography_color_grey500":"styles-module__typography_color_grey500___VffNJ","typography_color_grey400":"styles-module__typography_color_grey400___h8LXZ","typography_color_grey300":"styles-module__typography_color_grey300___CrH9u","typography_color_grey200":"styles-module__typography_color_grey200___4e7wo","typography_color_grey100":"styles-module__typography_color_grey100___s2JGa","typography_size_sm":"styles-module__typography_size_sm___IXCiS","typography_size_md":"styles-module__typography_size_md___vBKHL","typography_size_lg":"styles-module__typography_size_lg___UE2ty","typography_size_xl":"styles-module__typography_size_xl___e2zNJ","typography_size_2xl":"styles-module__typography_size_2xl___XPIIz","typography_size_3xl":"styles-module__typography_size_3xl___6dl0M","typography_weight_400":"styles-module__typography_weight_400___LwHSh","typography_weight_500":"styles-module__typography_weight_500___QwNXS","typography_weight_600":"styles-module__typography_weight_600___tWEhF","typography_weight_700":"styles-module__typography_weight_700___V455e","typography_deco_normal":"styles-module__typography_deco_normal___LdTNr","typography_deco_italic":"styles-module__typography_deco_italic___MXbnH","typography_deco_underline":"styles-module__typography_deco_underline___cVSHd","typography_deco_line-through":"styles-module__typography_deco_line-through___BISKr","typography_highlight_underline":"styles-module__typography_highlight_underline___a-iY0","typography_highlight_left":"styles-module__typography_highlight_left___3rZDb"};
32
32
  styleInject(css_248z$1);
33
33
 
34
34
  const classNames = (...args) => {
@@ -29,8 +29,8 @@ function styleInject(css, ref) {
29
29
  }
30
30
  }
31
31
 
32
- var css_248z$1 = ".styles-module__typography___uJJgf{font-family:inherit;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5}.styles-module__typography_color_grey900___tH77b{color:#21252a}.styles-module__typography_color_grey800___f4wMy{color:#3b3f45}.styles-module__typography_color_grey700___GSJui{color:#737373}.styles-module__typography_color_grey600___x6U6a{color:#7f848a}.styles-module__typography_color_grey500___VffNJ{color:#878e98}.styles-module__typography_color_grey400___h8LXZ{color:#a1a6ae}.styles-module__typography_color_grey300___CrH9u{color:#bcc0c6}.styles-module__typography_color_grey200___4e7wo{color:#d8dbe0}.styles-module__typography_color_grey100___s2JGa{color:#f1f3f5}.styles-module__typography_size_sm___IXCiS{font-size:.75rem}.styles-module__typography_size_md___vBKHL{font-size:1rem}.styles-module__typography_size_lg___UE2ty{font-size:1.125rem}.styles-module__typography_size_xl___e2zNJ{font-size:1.375rem}.styles-module__typography_size_2xl___XPIIz{font-size:1.75rem}.styles-module__typography_size_3xl___6dl0M{font-size:2rem}.styles-module__typography_weight_400___LwHSh{font-weight:400}.styles-module__typography_weight_500___QwNXS{font-weight:500}.styles-module__typography_weight_600___tWEhF{font-weight:600}.styles-module__typography_weight_700___V455e{font-weight:700}.styles-module__typography_deco_normal___LdTNr{font-style:normal}.styles-module__typography_deco_italic___MXbnH{font-style:italic}.styles-module__typography_deco_underline___cVSHd{text-decoration:underline;text-decoration-skip-ink:none}.styles-module__typography_deco_line-through___BISKr{text-decoration:line-through}.styles-module__typography_highlight_underline___a-iY0{display:inline-block;position:relative;z-index:1}.styles-module__typography_highlight_underline___a-iY0:after{background-color:#ffe600;border-radius:.1375em;bottom:.125rem;content:\"\";height:.4em;left:0;opacity:.7;position:absolute;width:100%;z-index:-1}";
33
- var styles$1 = {"typography":"styles-module__typography___uJJgf","typography_color_grey900":"styles-module__typography_color_grey900___tH77b","typography_color_grey800":"styles-module__typography_color_grey800___f4wMy","typography_color_grey700":"styles-module__typography_color_grey700___GSJui","typography_color_grey600":"styles-module__typography_color_grey600___x6U6a","typography_color_grey500":"styles-module__typography_color_grey500___VffNJ","typography_color_grey400":"styles-module__typography_color_grey400___h8LXZ","typography_color_grey300":"styles-module__typography_color_grey300___CrH9u","typography_color_grey200":"styles-module__typography_color_grey200___4e7wo","typography_color_grey100":"styles-module__typography_color_grey100___s2JGa","typography_size_sm":"styles-module__typography_size_sm___IXCiS","typography_size_md":"styles-module__typography_size_md___vBKHL","typography_size_lg":"styles-module__typography_size_lg___UE2ty","typography_size_xl":"styles-module__typography_size_xl___e2zNJ","typography_size_2xl":"styles-module__typography_size_2xl___XPIIz","typography_size_3xl":"styles-module__typography_size_3xl___6dl0M","typography_weight_400":"styles-module__typography_weight_400___LwHSh","typography_weight_500":"styles-module__typography_weight_500___QwNXS","typography_weight_600":"styles-module__typography_weight_600___tWEhF","typography_weight_700":"styles-module__typography_weight_700___V455e","typography_deco_normal":"styles-module__typography_deco_normal___LdTNr","typography_deco_italic":"styles-module__typography_deco_italic___MXbnH","typography_deco_underline":"styles-module__typography_deco_underline___cVSHd","typography_deco_line-through":"styles-module__typography_deco_line-through___BISKr","typography_highlight_underline":"styles-module__typography_highlight_underline___a-iY0"};
32
+ var css_248z$1 = ".styles-module__typography___uJJgf{font-family:inherit;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5}.styles-module__typography_color_grey900___tH77b{color:#21252a}.styles-module__typography_color_grey800___f4wMy{color:#3b3f45}.styles-module__typography_color_grey700___GSJui{color:#737373}.styles-module__typography_color_grey600___x6U6a{color:#7f848a}.styles-module__typography_color_grey500___VffNJ{color:#878e98}.styles-module__typography_color_grey400___h8LXZ{color:#a1a6ae}.styles-module__typography_color_grey300___CrH9u{color:#bcc0c6}.styles-module__typography_color_grey200___4e7wo{color:#d8dbe0}.styles-module__typography_color_grey100___s2JGa{color:#f1f3f5}.styles-module__typography_size_sm___IXCiS{font-size:.75rem}.styles-module__typography_size_md___vBKHL{font-size:1rem}.styles-module__typography_size_lg___UE2ty{font-size:1.125rem}.styles-module__typography_size_xl___e2zNJ{font-size:1.375rem}.styles-module__typography_size_2xl___XPIIz{font-size:1.75rem}.styles-module__typography_size_3xl___6dl0M{font-size:2rem}.styles-module__typography_weight_400___LwHSh{font-weight:400}.styles-module__typography_weight_500___QwNXS{font-weight:500}.styles-module__typography_weight_600___tWEhF{font-weight:600}.styles-module__typography_weight_700___V455e{font-weight:700}.styles-module__typography_deco_normal___LdTNr{font-style:normal}.styles-module__typography_deco_italic___MXbnH{font-style:italic}.styles-module__typography_deco_underline___cVSHd{text-decoration:underline;text-decoration-skip-ink:none}.styles-module__typography_deco_line-through___BISKr{text-decoration:line-through}.styles-module__typography_highlight_underline___a-iY0{display:inline-block;position:relative;z-index:1}.styles-module__typography_highlight_underline___a-iY0:after{background-color:#ffe600;border-radius:.1375em;bottom:.125rem;content:\"\";height:.4em;left:0;opacity:.7;position:absolute;width:100%;z-index:-1}.styles-module__typography_highlight_left___3rZDb{border-left:.25rem;border-color:#ffe600;padding-left:.1375rem}";
33
+ var styles$1 = {"typography":"styles-module__typography___uJJgf","typography_color_grey900":"styles-module__typography_color_grey900___tH77b","typography_color_grey800":"styles-module__typography_color_grey800___f4wMy","typography_color_grey700":"styles-module__typography_color_grey700___GSJui","typography_color_grey600":"styles-module__typography_color_grey600___x6U6a","typography_color_grey500":"styles-module__typography_color_grey500___VffNJ","typography_color_grey400":"styles-module__typography_color_grey400___h8LXZ","typography_color_grey300":"styles-module__typography_color_grey300___CrH9u","typography_color_grey200":"styles-module__typography_color_grey200___4e7wo","typography_color_grey100":"styles-module__typography_color_grey100___s2JGa","typography_size_sm":"styles-module__typography_size_sm___IXCiS","typography_size_md":"styles-module__typography_size_md___vBKHL","typography_size_lg":"styles-module__typography_size_lg___UE2ty","typography_size_xl":"styles-module__typography_size_xl___e2zNJ","typography_size_2xl":"styles-module__typography_size_2xl___XPIIz","typography_size_3xl":"styles-module__typography_size_3xl___6dl0M","typography_weight_400":"styles-module__typography_weight_400___LwHSh","typography_weight_500":"styles-module__typography_weight_500___QwNXS","typography_weight_600":"styles-module__typography_weight_600___tWEhF","typography_weight_700":"styles-module__typography_weight_700___V455e","typography_deco_normal":"styles-module__typography_deco_normal___LdTNr","typography_deco_italic":"styles-module__typography_deco_italic___MXbnH","typography_deco_underline":"styles-module__typography_deco_underline___cVSHd","typography_deco_line-through":"styles-module__typography_deco_line-through___BISKr","typography_highlight_underline":"styles-module__typography_highlight_underline___a-iY0","typography_highlight_left":"styles-module__typography_highlight_left___3rZDb"};
34
34
  styleInject(css_248z$1);
35
35
 
36
36
  const classNames = (...args) => {
@@ -33,9 +33,10 @@
33
33
  * });
34
34
  * // Output: "2020.01 ~ 2020.05"
35
35
  */
36
- export declare function formatCareerPeriod({ startAt, endAt, showDuration, lng, }: {
36
+ declare const formatCareerPeriod: ({ startAt, endAt, showDuration, lng, }: {
37
37
  startAt: Date;
38
- endAt?: Date;
39
- showDuration?: boolean;
40
- lng?: string;
41
- }): string;
38
+ endAt?: Date | undefined;
39
+ showDuration?: boolean | undefined;
40
+ lng?: string | undefined;
41
+ }) => string;
42
+ export default formatCareerPeriod;
@@ -1 +1,2 @@
1
1
  export { default as classNames } from './classNames/index';
2
+ export { default as formatCareerPeriod } from './formatCareerPeriod/index';
@@ -33,9 +33,10 @@
33
33
  * });
34
34
  * // Output: "2020.01 ~ 2020.05"
35
35
  */
36
- export declare function formatCareerPeriod({ startAt, endAt, showDuration, lng, }: {
36
+ declare const formatCareerPeriod: ({ startAt, endAt, showDuration, lng, }: {
37
37
  startAt: Date;
38
- endAt?: Date;
39
- showDuration?: boolean;
40
- lng?: string;
41
- }): string;
38
+ endAt?: Date | undefined;
39
+ showDuration?: boolean | undefined;
40
+ lng?: string | undefined;
41
+ }) => string;
42
+ export default formatCareerPeriod;
@@ -1 +1,2 @@
1
1
  export { default as classNames } from './classNames/index';
2
+ export { default as formatCareerPeriod } from './formatCareerPeriod/index';
@@ -1,3 +1,45 @@
1
1
  declare const classNames: (...args: (string | undefined)[]) => string | undefined;
2
2
 
3
- export { classNames };
3
+ /**
4
+ * Formats the career duration between two dates into a readable string.
5
+ * It handles internationalization (Korean/English) and the "Present" status for ongoing roles.
6
+ *
7
+ * @param props - The configuration object.
8
+ * @param props.startAt - The start date of the period.
9
+ * @param props.endAt - The end date. If undefined, it defaults to the current date (calculates duration up to now) and displays "Present" or "현재".
10
+ * @param props.showDuration - Whether to append the calculated duration (e.g., "(2y 6m)"). Defaults to true.
11
+ * @param props.lng - Language code ('ko' | 'en'). Defaults to 'ko'.
12
+ * @returns A formatted string: "YYYY.MM ~ YYYY.MM (Duration)" or "YYYY.MM ~ Present (Duration)".
13
+ *
14
+ * @example
15
+ * // 1. Ongoing role (Korean default)
16
+ * // Current date: 2024-02
17
+ * formatCareerPeriod({ startAt: new Date('2023-01-01') });
18
+ * // Output: "2023.01 ~ 현재 (1년 2개월)"
19
+ *
20
+ * @example
21
+ * // 2. Completed role with duration (English)
22
+ * formatCareerPeriod({
23
+ * startAt: new Date('2020-01-01'),
24
+ * endAt: new Date('2022-06-01'),
25
+ * lng: 'en'
26
+ * });
27
+ * // Output: "2020.01 ~ 2022.06 (2y 6m)"
28
+ *
29
+ * @example
30
+ * // 3. Hide duration
31
+ * formatCareerPeriod({
32
+ * startAt: new Date('2020-01-01'),
33
+ * endAt: new Date('2020-05-01'),
34
+ * showDuration: false
35
+ * });
36
+ * // Output: "2020.01 ~ 2020.05"
37
+ */
38
+ declare const formatCareerPeriod: ({ startAt, endAt, showDuration, lng, }: {
39
+ startAt: Date;
40
+ endAt?: Date | undefined;
41
+ showDuration?: boolean | undefined;
42
+ lng?: string | undefined;
43
+ }) => string;
44
+
45
+ export { classNames, formatCareerPeriod };
@@ -7,5 +7,75 @@ const classNames = (...args) => {
7
7
  }, '');
8
8
  };
9
9
 
10
- export { classNames };
10
+ /**
11
+ * Formats the career duration between two dates into a readable string.
12
+ * It handles internationalization (Korean/English) and the "Present" status for ongoing roles.
13
+ *
14
+ * @param props - The configuration object.
15
+ * @param props.startAt - The start date of the period.
16
+ * @param props.endAt - The end date. If undefined, it defaults to the current date (calculates duration up to now) and displays "Present" or "현재".
17
+ * @param props.showDuration - Whether to append the calculated duration (e.g., "(2y 6m)"). Defaults to true.
18
+ * @param props.lng - Language code ('ko' | 'en'). Defaults to 'ko'.
19
+ * @returns A formatted string: "YYYY.MM ~ YYYY.MM (Duration)" or "YYYY.MM ~ Present (Duration)".
20
+ *
21
+ * @example
22
+ * // 1. Ongoing role (Korean default)
23
+ * // Current date: 2024-02
24
+ * formatCareerPeriod({ startAt: new Date('2023-01-01') });
25
+ * // Output: "2023.01 ~ 현재 (1년 2개월)"
26
+ *
27
+ * @example
28
+ * // 2. Completed role with duration (English)
29
+ * formatCareerPeriod({
30
+ * startAt: new Date('2020-01-01'),
31
+ * endAt: new Date('2022-06-01'),
32
+ * lng: 'en'
33
+ * });
34
+ * // Output: "2020.01 ~ 2022.06 (2y 6m)"
35
+ *
36
+ * @example
37
+ * // 3. Hide duration
38
+ * formatCareerPeriod({
39
+ * startAt: new Date('2020-01-01'),
40
+ * endAt: new Date('2020-05-01'),
41
+ * showDuration: false
42
+ * });
43
+ * // Output: "2020.01 ~ 2020.05"
44
+ */
45
+ const formatCareerPeriod = ({ startAt, endAt, showDuration = true, lng = 'ko', }) => {
46
+ const lang = lng === 'en' ? 'en' : 'ko';
47
+ const LABELS = {
48
+ current: { ko: '현재', en: 'Present' },
49
+ year: { ko: '년', en: 'y' },
50
+ month: { ko: '개월', en: 'm' },
51
+ };
52
+ const formatYearMonth = (d) => {
53
+ const year = d.getFullYear();
54
+ const month = String(d.getMonth() + 1).padStart(2, '0');
55
+ return `${year}.${month}`;
56
+ };
57
+ const endDate = endAt || new Date();
58
+ const startText = formatYearMonth(startAt);
59
+ const endText = endAt ? formatYearMonth(endAt) : LABELS.current[lang];
60
+ if (!showDuration) {
61
+ return `${startText} ~ ${endText}`;
62
+ }
63
+ const totalMonths = (endDate.getFullYear() - startAt.getFullYear()) * 12 +
64
+ (endDate.getMonth() - startAt.getMonth()) +
65
+ 1;
66
+ if (totalMonths < 1) {
67
+ return `${startText} ~ ${endText}`;
68
+ }
69
+ const years = Math.floor(totalMonths / 12);
70
+ const months = totalMonths % 12;
71
+ const durationParts = [
72
+ years > 0 ? `${years}${LABELS.year[lang]}` : null,
73
+ months > 0 ? `${months}${LABELS.month[lang]}` : null,
74
+ ].filter(Boolean);
75
+ const durationString = durationParts.join(' ');
76
+ const durationSuffix = durationString ? ` (${durationString})` : '';
77
+ return `${startText} ~ ${endText}${durationSuffix}`;
78
+ };
79
+
80
+ export { classNames, formatCareerPeriod };
11
81
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../src/utils/classNames/index.ts"],"sourcesContent":["const classNames = (...args: (string | undefined)[]) => {\n\treturn args.reduce((acc, className) => {\n\t\tif (className) {\n\t\t\treturn acc ? `${acc} ${className}` : className;\n\t\t}\n\t\treturn acc;\n\t}, '');\n};\n\nexport default classNames;\n"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,GAAG,IAA4B,KAAI;IACtD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,KAAI;QACrC,IAAI,SAAS,EAAE;AACd,YAAA,OAAO,GAAG,GAAG,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,SAAS,CAAE,CAAA,GAAG,SAAS,CAAC;SAC/C;AACD,QAAA,OAAO,GAAG,CAAC;KACX,EAAE,EAAE,CAAC,CAAC;AACR;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/utils/classNames/index.ts","../../src/utils/formatCareerPeriod/index.ts"],"sourcesContent":["const classNames = (...args: (string | undefined)[]) => {\n\treturn args.reduce((acc, className) => {\n\t\tif (className) {\n\t\t\treturn acc ? `${acc} ${className}` : className;\n\t\t}\n\t\treturn acc;\n\t}, '');\n};\n\nexport default classNames;\n","type SupportedLang = 'ko' | 'en';\n\n/**\n * Formats the career duration between two dates into a readable string.\n * It handles internationalization (Korean/English) and the \"Present\" status for ongoing roles.\n *\n * @param props - The configuration object.\n * @param props.startAt - The start date of the period.\n * @param props.endAt - The end date. If undefined, it defaults to the current date (calculates duration up to now) and displays \"Present\" or \"현재\".\n * @param props.showDuration - Whether to append the calculated duration (e.g., \"(2y 6m)\"). Defaults to true.\n * @param props.lng - Language code ('ko' | 'en'). Defaults to 'ko'.\n * @returns A formatted string: \"YYYY.MM ~ YYYY.MM (Duration)\" or \"YYYY.MM ~ Present (Duration)\".\n *\n * @example\n * // 1. Ongoing role (Korean default)\n * // Current date: 2024-02\n * formatCareerPeriod({ startAt: new Date('2023-01-01') });\n * // Output: \"2023.01 ~ 현재 (1년 2개월)\"\n *\n * @example\n * // 2. Completed role with duration (English)\n * formatCareerPeriod({\n * startAt: new Date('2020-01-01'),\n * endAt: new Date('2022-06-01'),\n * lng: 'en'\n * });\n * // Output: \"2020.01 ~ 2022.06 (2y 6m)\"\n *\n * @example\n * // 3. Hide duration\n * formatCareerPeriod({\n * startAt: new Date('2020-01-01'),\n * endAt: new Date('2020-05-01'),\n * showDuration: false\n * });\n * // Output: \"2020.01 ~ 2020.05\"\n */\nconst formatCareerPeriod = ({\n\tstartAt,\n\tendAt,\n\tshowDuration = true,\n\tlng = 'ko',\n}: {\n\tstartAt: Date;\n\tendAt?: Date;\n\tshowDuration?: boolean;\n\tlng?: string;\n}): string => {\n\tconst lang: SupportedLang = lng === 'en' ? 'en' : 'ko';\n\n\tconst LABELS = {\n\t\tcurrent: { ko: '현재', en: 'Present' },\n\t\tyear: { ko: '년', en: 'y' },\n\t\tmonth: { ko: '개월', en: 'm' },\n\t} as const;\n\n\tconst formatYearMonth = (d: Date) => {\n\t\tconst year = d.getFullYear();\n\t\tconst month = String(d.getMonth() + 1).padStart(2, '0');\n\t\treturn `${year}.${month}`;\n\t};\n\n\tconst endDate = endAt || new Date();\n\n\tconst startText = formatYearMonth(startAt);\n\tconst endText = endAt ? formatYearMonth(endAt) : LABELS.current[lang];\n\n\tif (!showDuration) {\n\t\treturn `${startText} ~ ${endText}`;\n\t}\n\n\tconst totalMonths =\n\t\t(endDate.getFullYear() - startAt.getFullYear()) * 12 +\n\t\t(endDate.getMonth() - startAt.getMonth()) +\n\t\t1;\n\n\tif (totalMonths < 1) {\n\t\treturn `${startText} ~ ${endText}`;\n\t}\n\n\tconst years = Math.floor(totalMonths / 12);\n\tconst months = totalMonths % 12;\n\n\tconst durationParts = [\n\t\tyears > 0 ? `${years}${LABELS.year[lang]}` : null,\n\t\tmonths > 0 ? `${months}${LABELS.month[lang]}` : null,\n\t].filter(Boolean);\n\n\tconst durationString = durationParts.join(' ');\n\tconst durationSuffix = durationString ? ` (${durationString})` : '';\n\n\treturn `${startText} ~ ${endText}${durationSuffix}`;\n};\n\nexport default formatCareerPeriod;\n"],"names":[],"mappings":"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"}
@@ -9,5 +9,76 @@ const classNames = (...args) => {
9
9
  }, '');
10
10
  };
11
11
 
12
+ /**
13
+ * Formats the career duration between two dates into a readable string.
14
+ * It handles internationalization (Korean/English) and the "Present" status for ongoing roles.
15
+ *
16
+ * @param props - The configuration object.
17
+ * @param props.startAt - The start date of the period.
18
+ * @param props.endAt - The end date. If undefined, it defaults to the current date (calculates duration up to now) and displays "Present" or "현재".
19
+ * @param props.showDuration - Whether to append the calculated duration (e.g., "(2y 6m)"). Defaults to true.
20
+ * @param props.lng - Language code ('ko' | 'en'). Defaults to 'ko'.
21
+ * @returns A formatted string: "YYYY.MM ~ YYYY.MM (Duration)" or "YYYY.MM ~ Present (Duration)".
22
+ *
23
+ * @example
24
+ * // 1. Ongoing role (Korean default)
25
+ * // Current date: 2024-02
26
+ * formatCareerPeriod({ startAt: new Date('2023-01-01') });
27
+ * // Output: "2023.01 ~ 현재 (1년 2개월)"
28
+ *
29
+ * @example
30
+ * // 2. Completed role with duration (English)
31
+ * formatCareerPeriod({
32
+ * startAt: new Date('2020-01-01'),
33
+ * endAt: new Date('2022-06-01'),
34
+ * lng: 'en'
35
+ * });
36
+ * // Output: "2020.01 ~ 2022.06 (2y 6m)"
37
+ *
38
+ * @example
39
+ * // 3. Hide duration
40
+ * formatCareerPeriod({
41
+ * startAt: new Date('2020-01-01'),
42
+ * endAt: new Date('2020-05-01'),
43
+ * showDuration: false
44
+ * });
45
+ * // Output: "2020.01 ~ 2020.05"
46
+ */
47
+ const formatCareerPeriod = ({ startAt, endAt, showDuration = true, lng = 'ko', }) => {
48
+ const lang = lng === 'en' ? 'en' : 'ko';
49
+ const LABELS = {
50
+ current: { ko: '현재', en: 'Present' },
51
+ year: { ko: '년', en: 'y' },
52
+ month: { ko: '개월', en: 'm' },
53
+ };
54
+ const formatYearMonth = (d) => {
55
+ const year = d.getFullYear();
56
+ const month = String(d.getMonth() + 1).padStart(2, '0');
57
+ return `${year}.${month}`;
58
+ };
59
+ const endDate = endAt || new Date();
60
+ const startText = formatYearMonth(startAt);
61
+ const endText = endAt ? formatYearMonth(endAt) : LABELS.current[lang];
62
+ if (!showDuration) {
63
+ return `${startText} ~ ${endText}`;
64
+ }
65
+ const totalMonths = (endDate.getFullYear() - startAt.getFullYear()) * 12 +
66
+ (endDate.getMonth() - startAt.getMonth()) +
67
+ 1;
68
+ if (totalMonths < 1) {
69
+ return `${startText} ~ ${endText}`;
70
+ }
71
+ const years = Math.floor(totalMonths / 12);
72
+ const months = totalMonths % 12;
73
+ const durationParts = [
74
+ years > 0 ? `${years}${LABELS.year[lang]}` : null,
75
+ months > 0 ? `${months}${LABELS.month[lang]}` : null,
76
+ ].filter(Boolean);
77
+ const durationString = durationParts.join(' ');
78
+ const durationSuffix = durationString ? ` (${durationString})` : '';
79
+ return `${startText} ~ ${endText}${durationSuffix}`;
80
+ };
81
+
12
82
  exports.classNames = classNames;
83
+ exports.formatCareerPeriod = formatCareerPeriod;
13
84
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/utils/classNames/index.ts"],"sourcesContent":["const classNames = (...args: (string | undefined)[]) => {\n\treturn args.reduce((acc, className) => {\n\t\tif (className) {\n\t\t\treturn acc ? `${acc} ${className}` : className;\n\t\t}\n\t\treturn acc;\n\t}, '');\n};\n\nexport default classNames;\n"],"names":[],"mappings":";;AAAA,MAAM,UAAU,GAAG,CAAC,GAAG,IAA4B,KAAI;IACtD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,KAAI;QACrC,IAAI,SAAS,EAAE;AACd,YAAA,OAAO,GAAG,GAAG,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,SAAS,CAAE,CAAA,GAAG,SAAS,CAAC;SAC/C;AACD,QAAA,OAAO,GAAG,CAAC;KACX,EAAE,EAAE,CAAC,CAAC;AACR;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/utils/classNames/index.ts","../../src/utils/formatCareerPeriod/index.ts"],"sourcesContent":["const classNames = (...args: (string | undefined)[]) => {\n\treturn args.reduce((acc, className) => {\n\t\tif (className) {\n\t\t\treturn acc ? `${acc} ${className}` : className;\n\t\t}\n\t\treturn acc;\n\t}, '');\n};\n\nexport default classNames;\n","type SupportedLang = 'ko' | 'en';\n\n/**\n * Formats the career duration between two dates into a readable string.\n * It handles internationalization (Korean/English) and the \"Present\" status for ongoing roles.\n *\n * @param props - The configuration object.\n * @param props.startAt - The start date of the period.\n * @param props.endAt - The end date. If undefined, it defaults to the current date (calculates duration up to now) and displays \"Present\" or \"현재\".\n * @param props.showDuration - Whether to append the calculated duration (e.g., \"(2y 6m)\"). Defaults to true.\n * @param props.lng - Language code ('ko' | 'en'). Defaults to 'ko'.\n * @returns A formatted string: \"YYYY.MM ~ YYYY.MM (Duration)\" or \"YYYY.MM ~ Present (Duration)\".\n *\n * @example\n * // 1. Ongoing role (Korean default)\n * // Current date: 2024-02\n * formatCareerPeriod({ startAt: new Date('2023-01-01') });\n * // Output: \"2023.01 ~ 현재 (1년 2개월)\"\n *\n * @example\n * // 2. Completed role with duration (English)\n * formatCareerPeriod({\n * startAt: new Date('2020-01-01'),\n * endAt: new Date('2022-06-01'),\n * lng: 'en'\n * });\n * // Output: \"2020.01 ~ 2022.06 (2y 6m)\"\n *\n * @example\n * // 3. Hide duration\n * formatCareerPeriod({\n * startAt: new Date('2020-01-01'),\n * endAt: new Date('2020-05-01'),\n * showDuration: false\n * });\n * // Output: \"2020.01 ~ 2020.05\"\n */\nconst formatCareerPeriod = ({\n\tstartAt,\n\tendAt,\n\tshowDuration = true,\n\tlng = 'ko',\n}: {\n\tstartAt: Date;\n\tendAt?: Date;\n\tshowDuration?: boolean;\n\tlng?: string;\n}): string => {\n\tconst lang: SupportedLang = lng === 'en' ? 'en' : 'ko';\n\n\tconst LABELS = {\n\t\tcurrent: { ko: '현재', en: 'Present' },\n\t\tyear: { ko: '년', en: 'y' },\n\t\tmonth: { ko: '개월', en: 'm' },\n\t} as const;\n\n\tconst formatYearMonth = (d: Date) => {\n\t\tconst year = d.getFullYear();\n\t\tconst month = String(d.getMonth() + 1).padStart(2, '0');\n\t\treturn `${year}.${month}`;\n\t};\n\n\tconst endDate = endAt || new Date();\n\n\tconst startText = formatYearMonth(startAt);\n\tconst endText = endAt ? formatYearMonth(endAt) : LABELS.current[lang];\n\n\tif (!showDuration) {\n\t\treturn `${startText} ~ ${endText}`;\n\t}\n\n\tconst totalMonths =\n\t\t(endDate.getFullYear() - startAt.getFullYear()) * 12 +\n\t\t(endDate.getMonth() - startAt.getMonth()) +\n\t\t1;\n\n\tif (totalMonths < 1) {\n\t\treturn `${startText} ~ ${endText}`;\n\t}\n\n\tconst years = Math.floor(totalMonths / 12);\n\tconst months = totalMonths % 12;\n\n\tconst durationParts = [\n\t\tyears > 0 ? `${years}${LABELS.year[lang]}` : null,\n\t\tmonths > 0 ? `${months}${LABELS.month[lang]}` : null,\n\t].filter(Boolean);\n\n\tconst durationString = durationParts.join(' ');\n\tconst durationSuffix = durationString ? ` (${durationString})` : '';\n\n\treturn `${startText} ~ ${endText}${durationSuffix}`;\n};\n\nexport default formatCareerPeriod;\n"],"names":[],"mappings":";;AAAA,MAAM,UAAU,GAAG,CAAC,GAAG,IAA4B,KAAI;IACtD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,KAAI;QACrC,IAAI,SAAS,EAAE;AACd,YAAA,OAAO,GAAG,GAAG,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,SAAS,CAAE,CAAA,GAAG,SAAS,CAAC;SAC/C;AACD,QAAA,OAAO,GAAG,CAAC;KACX,EAAE,EAAE,CAAC,CAAC;AACR;;ACLA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCG;AACH,MAAM,kBAAkB,GAAG,CAAC,EAC3B,OAAO,EACP,KAAK,EACL,YAAY,GAAG,IAAI,EACnB,GAAG,GAAG,IAAI,GAMV,KAAY;AACZ,IAAA,MAAM,IAAI,GAAkB,GAAG,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEvD,IAAA,MAAM,MAAM,GAAG;QACd,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE;QACpC,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;QAC1B,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE;KACnB,CAAC;AAEX,IAAA,MAAM,eAAe,GAAG,CAAC,CAAO,KAAI;AACnC,QAAA,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7B,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACxD,QAAA,OAAO,CAAG,EAAA,IAAI,CAAI,CAAA,EAAA,KAAK,EAAE,CAAC;AAC3B,KAAC,CAAC;AAEF,IAAA,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,IAAI,EAAE,CAAC;AAEpC,IAAA,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;AAC3C,IAAA,MAAM,OAAO,GAAG,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtE,IAAI,CAAC,YAAY,EAAE;AAClB,QAAA,OAAO,CAAG,EAAA,SAAS,CAAM,GAAA,EAAA,OAAO,EAAE,CAAC;KACnC;AAED,IAAA,MAAM,WAAW,GAChB,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE;SACnD,OAAO,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;AACzC,QAAA,CAAC,CAAC;AAEH,IAAA,IAAI,WAAW,GAAG,CAAC,EAAE;AACpB,QAAA,OAAO,CAAG,EAAA,SAAS,CAAM,GAAA,EAAA,OAAO,EAAE,CAAC;KACnC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;AAC3C,IAAA,MAAM,MAAM,GAAG,WAAW,GAAG,EAAE,CAAC;AAEhC,IAAA,MAAM,aAAa,GAAG;AACrB,QAAA,KAAK,GAAG,CAAC,GAAG,CAAA,EAAG,KAAK,CAAG,EAAA,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI;AACjD,QAAA,MAAM,GAAG,CAAC,GAAG,CAAA,EAAG,MAAM,CAAG,EAAA,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI;AACpD,KAAA,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElB,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,IAAA,MAAM,cAAc,GAAG,cAAc,GAAG,CAAK,EAAA,EAAA,cAAc,CAAG,CAAA,CAAA,GAAG,EAAE,CAAC;AAEpE,IAAA,OAAO,GAAG,SAAS,CAAA,GAAA,EAAM,OAAO,CAAG,EAAA,cAAc,EAAE,CAAC;AACrD;;;;;"}
@@ -33,9 +33,10 @@
33
33
  * });
34
34
  * // Output: "2020.01 ~ 2020.05"
35
35
  */
36
- export declare function formatCareerPeriod({ startAt, endAt, showDuration, lng, }: {
36
+ declare const formatCareerPeriod: ({ startAt, endAt, showDuration, lng, }: {
37
37
  startAt: Date;
38
- endAt?: Date;
39
- showDuration?: boolean;
40
- lng?: string;
41
- }): string;
38
+ endAt?: Date | undefined;
39
+ showDuration?: boolean | undefined;
40
+ lng?: string | undefined;
41
+ }) => string;
42
+ export default formatCareerPeriod;
@@ -1 +1,2 @@
1
1
  export { default as classNames } from './classNames/index';
2
+ export { default as formatCareerPeriod } from './formatCareerPeriod/index';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wonjin-dev/reacts",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "author": "wonjin-dev",
5
5
  "license": "MIT",
6
6
  "type": "module",