smarthr-ui 96.1.2 → 97.0.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/lib/components/Combobox/helper.cjs +29 -13
- package/lib/components/Combobox/helper.cjs.map +1 -1
- package/lib/components/Combobox/helper.d.ts +1 -1
- package/lib/components/Combobox/helper.js +29 -13
- package/lib/components/Combobox/helper.js.map +1 -1
- package/lib/components/Combobox/useOptions.cjs +21 -17
- package/lib/components/Combobox/useOptions.cjs.map +1 -1
- package/lib/components/Combobox/useOptions.js +21 -17
- package/lib/components/Combobox/useOptions.js.map +1 -1
- package/lib/components/Dialog/DialogContentInner.cjs +8 -1
- package/lib/components/Dialog/DialogContentInner.cjs.map +1 -1
- package/lib/components/Dialog/DialogContentInner.js +9 -2
- package/lib/components/Dialog/DialogContentInner.js.map +1 -1
- package/lib/components/Dialog/ModelessDialog/ModelessDialog.cjs +13 -11
- package/lib/components/Dialog/ModelessDialog/ModelessDialog.cjs.map +1 -1
- package/lib/components/Dialog/ModelessDialog/ModelessDialog.js +13 -11
- package/lib/components/Dialog/ModelessDialog/ModelessDialog.js.map +1 -1
- package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs +5 -2
- package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs.map +1 -1
- package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js +5 -2
- package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js.map +1 -1
- package/lib/components/Disclosure/DisclosureTrigger.cjs +39 -18
- package/lib/components/Disclosure/DisclosureTrigger.cjs.map +1 -1
- package/lib/components/Disclosure/DisclosureTrigger.js +40 -19
- package/lib/components/Disclosure/DisclosureTrigger.js.map +1 -1
- package/lib/components/Disclosure/useDisclosure.cjs +8 -14
- package/lib/components/Disclosure/useDisclosure.cjs.map +1 -1
- package/lib/components/Disclosure/useDisclosure.js +8 -14
- package/lib/components/Disclosure/useDisclosure.js.map +1 -1
- package/lib/components/DropZone/DropZone.cjs +3 -0
- package/lib/components/DropZone/DropZone.cjs.map +1 -1
- package/lib/components/DropZone/DropZone.js +3 -0
- package/lib/components/DropZone/DropZone.js.map +1 -1
- package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.cjs +4 -2
- package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.cjs.map +1 -1
- package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.js +4 -2
- package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.js.map +1 -1
- package/lib/components/Dropdown/DropdownTrigger.cjs +3 -0
- package/lib/components/Dropdown/DropdownTrigger.cjs.map +1 -1
- package/lib/components/Dropdown/DropdownTrigger.js +3 -0
- package/lib/components/Dropdown/DropdownTrigger.js.map +1 -1
- package/lib/components/InputFile/InputFileMultiplyAppendable.cjs +12 -17
- package/lib/components/InputFile/InputFileMultiplyAppendable.cjs.map +1 -1
- package/lib/components/InputFile/InputFileMultiplyAppendable.js +12 -17
- package/lib/components/InputFile/InputFileMultiplyAppendable.js.map +1 -1
- package/lib/components/LineClamp/LineClamp.cjs +14 -3
- package/lib/components/LineClamp/LineClamp.cjs.map +1 -1
- package/lib/components/LineClamp/LineClamp.js +14 -3
- package/lib/components/LineClamp/LineClamp.js.map +1 -1
- package/lib/components/Select/Select.cjs +11 -11
- package/lib/components/Select/Select.cjs.map +1 -1
- package/lib/components/Select/Select.js +12 -12
- package/lib/components/Select/Select.js.map +1 -1
- package/lib/components/TabBar/TabItem.cjs +11 -9
- package/lib/components/TabBar/TabItem.cjs.map +1 -1
- package/lib/components/TabBar/TabItem.d.ts +2 -2
- package/lib/components/TabBar/TabItem.js +13 -11
- package/lib/components/TabBar/TabItem.js.map +1 -1
- package/lib/hooks/useHandleEscape.cjs +4 -4
- package/lib/hooks/useHandleEscape.cjs.map +1 -1
- package/lib/hooks/useHandleEscape.d.ts +1 -1
- package/lib/hooks/useHandleEscape.js +4 -4
- package/lib/hooks/useHandleEscape.js.map +1 -1
- package/lib/intl/Localizer.d.ts +3 -3
- package/lib/intl/locales/en_us.json.cjs +133 -0
- package/lib/intl/locales/en_us.json.cjs.map +1 -0
- package/lib/intl/locales/en_us.json.js +131 -0
- package/lib/intl/locales/en_us.json.js.map +1 -0
- package/lib/intl/locales/id_id.json.cjs +133 -0
- package/lib/intl/locales/id_id.json.cjs.map +1 -0
- package/lib/intl/locales/id_id.json.js +131 -0
- package/lib/intl/locales/id_id.json.js.map +1 -0
- package/lib/intl/locales/index.cjs +24 -18
- package/lib/intl/locales/index.cjs.map +1 -1
- package/lib/intl/locales/index.d.ts +1135 -1136
- package/lib/intl/locales/index.js +25 -19
- package/lib/intl/locales/index.js.map +1 -1
- package/lib/intl/locales/ja.json.cjs +133 -0
- package/lib/intl/locales/ja.json.cjs.map +1 -0
- package/lib/intl/locales/ja.json.js +131 -0
- package/lib/intl/locales/ja.json.js.map +1 -0
- package/lib/intl/locales/ja_easy.json.cjs +133 -0
- package/lib/intl/locales/ja_easy.json.cjs.map +1 -0
- package/lib/intl/locales/ja_easy.json.js +131 -0
- package/lib/intl/locales/ja_easy.json.js.map +1 -0
- package/lib/intl/locales/ko_kr.json.cjs +133 -0
- package/lib/intl/locales/ko_kr.json.cjs.map +1 -0
- package/lib/intl/locales/ko_kr.json.js +131 -0
- package/lib/intl/locales/ko_kr.json.js.map +1 -0
- package/lib/intl/locales/pt_br.json.cjs +133 -0
- package/lib/intl/locales/pt_br.json.cjs.map +1 -0
- package/lib/intl/locales/pt_br.json.js +131 -0
- package/lib/intl/locales/pt_br.json.js.map +1 -0
- package/lib/intl/locales/vi_vn.json.cjs +133 -0
- package/lib/intl/locales/vi_vn.json.cjs.map +1 -0
- package/lib/intl/locales/vi_vn.json.js +131 -0
- package/lib/intl/locales/vi_vn.json.js.map +1 -0
- package/lib/intl/locales/zh_hans_cn.json.cjs +133 -0
- package/lib/intl/locales/zh_hans_cn.json.cjs.map +1 -0
- package/lib/intl/locales/zh_hans_cn.json.js +131 -0
- package/lib/intl/locales/zh_hans_cn.json.js.map +1 -0
- package/lib/intl/locales/zh_hant_tw.json.cjs +133 -0
- package/lib/intl/locales/zh_hant_tw.json.cjs.map +1 -0
- package/lib/intl/locales/zh_hant_tw.json.js +131 -0
- package/lib/intl/locales/zh_hant_tw.json.js.map +1 -0
- package/lib/intl/useIntl.cjs.map +1 -1
- package/lib/intl/useIntl.d.ts +3 -3
- package/lib/intl/useIntl.js.map +1 -1
- package/metadata.json +1 -1
- package/package.json +2 -1
- package/lib/intl/locales/en_us.cjs +0 -135
- package/lib/intl/locales/en_us.cjs.map +0 -1
- package/lib/intl/locales/en_us.d.ts +0 -128
- package/lib/intl/locales/en_us.js +0 -133
- package/lib/intl/locales/en_us.js.map +0 -1
- package/lib/intl/locales/id_id.cjs +0 -135
- package/lib/intl/locales/id_id.cjs.map +0 -1
- package/lib/intl/locales/id_id.d.ts +0 -128
- package/lib/intl/locales/id_id.js +0 -133
- package/lib/intl/locales/id_id.js.map +0 -1
- package/lib/intl/locales/ja_easy.cjs +0 -135
- package/lib/intl/locales/ja_easy.cjs.map +0 -1
- package/lib/intl/locales/ja_easy.d.ts +0 -128
- package/lib/intl/locales/ja_easy.js +0 -133
- package/lib/intl/locales/ja_easy.js.map +0 -1
- package/lib/intl/locales/ko_kr.cjs +0 -135
- package/lib/intl/locales/ko_kr.cjs.map +0 -1
- package/lib/intl/locales/ko_kr.d.ts +0 -128
- package/lib/intl/locales/ko_kr.js +0 -133
- package/lib/intl/locales/ko_kr.js.map +0 -1
- package/lib/intl/locales/pt_br.cjs +0 -135
- package/lib/intl/locales/pt_br.cjs.map +0 -1
- package/lib/intl/locales/pt_br.d.ts +0 -128
- package/lib/intl/locales/pt_br.js +0 -133
- package/lib/intl/locales/pt_br.js.map +0 -1
- package/lib/intl/locales/vi_vn.cjs +0 -135
- package/lib/intl/locales/vi_vn.cjs.map +0 -1
- package/lib/intl/locales/vi_vn.d.ts +0 -128
- package/lib/intl/locales/vi_vn.js +0 -133
- package/lib/intl/locales/vi_vn.js.map +0 -1
- package/lib/intl/locales/zh_hans_cn.cjs +0 -135
- package/lib/intl/locales/zh_hans_cn.cjs.map +0 -1
- package/lib/intl/locales/zh_hans_cn.d.ts +0 -128
- package/lib/intl/locales/zh_hans_cn.js +0 -133
- package/lib/intl/locales/zh_hans_cn.js.map +0 -1
- package/lib/intl/locales/zh_hant_tw.cjs +0 -135
- package/lib/intl/locales/zh_hant_tw.cjs.map +0 -1
- package/lib/intl/locales/zh_hant_tw.d.ts +0 -128
- package/lib/intl/locales/zh_hant_tw.js +0 -133
- package/lib/intl/locales/zh_hant_tw.js.map +0 -1
package/lib/intl/useIntl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIntl.js","sources":["../../src/intl/useIntl.ts"],"sourcesContent":["'use client'\n\nimport { useCallback } from 'react'\nimport {\n type PrimitiveType,\n type MessageDescriptor as ReactIntlMessageDescriptor,\n useIntl as useReactIntl,\n} from 'react-intl'\n\nimport { useAvailableLocales } from './IntlProvider'\nimport { locales } from './locales'\n\nimport type { FormatXMLElementFn, Options as IntlMessageFormatOptions } from 'intl-messageformat'\n\ntype Messages = Record<keyof typeof locales.ja, string>\n\ntype MessageDescriptor<T extends keyof Messages> = Omit<ReactIntlMessageDescriptor, 'id'> & {\n id: T\n defaultText: (typeof locales.ja)[T]\n}\n\ntype DatePart = 'year' | 'month' | 'day' | 'weekday'\n\ntype TimePart = 'hour' | 'minute' | 'second'\n\nexport type FormatDateProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する日付のパーツ。指定しない場合は全て表示\n */\n parts?: readonly [DatePart, ...DatePart[]]\n\n /**\n * フォーマットオプション\n */\n options?: Intl.DateTimeFormatOptions & {\n /**\n * 日本語ロケールでスラッシュを無効化し、月を長形式で表示する\n * @example\n * // 通常: \"2025/01\"\n * // disableSlashInJa: true の場合: \"2025年1月\"\n */\n disableSlashInJa?: boolean\n\n /**\n * 最初の文字を大文字化する\n * @example\n * // 通常: \"seg.\" (pt)\n * // capitalizeFirstLetter: true の場合: \"Seg.\" (pt)\n */\n capitalizeFirstLetter?: boolean\n }\n}\n\nexport type FormatTimeProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する時刻のパーツ。指定しない場合は ['hour', 'minute'] がデフォルト\n */\n parts?: readonly [TimePart, ...TimePart[]]\n\n /**\n * フォーマットオプション\n */\n options?: Intl.DateTimeFormatOptions\n}\n\nexport type FormatTimestampProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する時刻のパーツ。指定しない場合は ['hour', 'minute'] がデフォルト\n */\n timeParts?: readonly [TimePart, ...TimePart[]]\n}\n\n/**\n * useIntlフックの戻り値の型定義\n */\nexport type UseIntlReturn = {\n /** 利用可能なロケールのリスト */\n availableLocales: string[]\n /** メッセージのローカライズ関数 */\n localize: <T extends keyof Messages>(\n descriptor: MessageDescriptor<T>,\n values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,\n opts?: IntlMessageFormatOptions,\n ) => string\n\n /**\n * 日付をロケールに応じた形式でフォーマットする関数\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.parts - 表示する日付のパーツ。デフォルトは ['year', 'month', 'day', 'weekday']\n * @param props.options - フォーマットオプション\n * @param props.options.disableSlashInJa - 日本語ロケールでスラッシュを無効化し、月を長形式で表示する\n * @param props.options.capitalizeFirstLetter - 最初の文字を大文字化する\n * @returns フォーマットされた日付文字列\n * @example\n * // 基本的な使用法(ロケールのデフォルト形式:曜日なし)\n * formatDate({ date: new Date() }) // \"2024/01/15\" (ja)\n *\n * // 日付を曜日ありで表示\n * formatDate({ date: new Date(), parts: ['year', 'month', 'day', 'weekday'] }) // \"2024/01/15(水)\" (ja)\n *\n * // 特定のフィールドのみ表示\n * formatDate({ date: new Date(), parts: ['year', 'month'] }) // \"2024/01\" (ja)\n * formatDate({ date: new Date(), parts: ['weekday'] }) // \"月\" (ja)\n *\n * // 日本語でスラッシュを無効化(月を長形式で表示)\n * formatDate({ date: new Date(), parts: ['year', 'month'], options: { disableSlashInJa: true } }) // \"2024年1月\" (ja)\n *\n * // 最初の文字を大文字化\n * formatDate({ date: new Date(), parts: ['weekday'], options: { capitalizeFirstLetter: true } }) // \"Seg.\" (pt)(指定しなければ \"seg.\")\n */\n formatDate(props: FormatDateProps): string\n\n /**\n * 時刻をロケールに応じた形式でフォーマットする関数\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.parts - 表示する時刻のパーツ。デフォルトは ['hour', 'minute']\n * @param props.options - フォーマットオプション\n * @returns フォーマットされた時刻文字列\n * @example\n * // 基本的な使用法(ロケールのデフォルト形式)\n * formatTime({ date: new Date() }) // \"10:30\" (ja)\n *\n * // 秒を含めて表示\n * formatTime({ date: new Date(), parts: ['hour', 'minute', 'second'] }) // \"10:30:45\" (ja)\n *\n * // 時のみ表示\n * formatTime({ date: new Date(), parts: ['hour'] }) // \"10\" (ja)\n *\n * // 12時間形式で表示\n * formatTime({ date: new Date(), options: { hour12: true } }) // \"午前10:30\" (ja)\n */\n formatTime(props: FormatTimeProps): string\n\n /**\n * タイムスタンプ(日付+時刻)をフォーマットする関数\n * 日付はスラッシュ形式、時刻は24時間形式で表示されます\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.timeParts - 表示する時刻のパーツ。デフォルトは ['hour', 'minute']\n * @returns フォーマットされたタイムスタンプ文字列\n * @example\n * // 基本的な使用法\n * formatTimestamp({ date: new Date() }) // \"2024/01/15 10:30\" (ja)\n *\n * // 秒を含めて表示\n * formatTimestamp({ date: new Date(), timeParts: ['hour', 'minute', 'second'] }) // \"2024/01/15 10:30:45\" (ja)\n */\n formatTimestamp(props: FormatTimestampProps): string\n\n /**\n * 現在のロケールに基づいて週の開始日を決定する関数\n * Intl.Locale.prototype.getWeekInfo()の動作を再現\n * getWeekInfo()を使わない理由は、Firefoxでは動作しないため\n *\n * @returns 週の開始日(0 = 日曜日, 1 = 月曜日, ..., 6 = 土曜日)\n */\n getWeekStartDay: () => number\n /** 現在のロケール */\n locale: keyof typeof locales\n}\n\nconst WEEK_START_DAYS = {\n SUNDAY: 0,\n MONDAY: 1,\n TUESDAY: 2,\n WEDNESDAY: 3,\n THURSDAY: 4,\n FRIDAY: 5,\n SATURDAY: 6,\n} as const\n\nconst DATE_FORMATS: Record<\n keyof typeof locales,\n Intl.DateTimeFormatOptions & { weekStartDay: number }\n> = {\n // localeがja, ja-easyの場合、フォーマットを YYYY/MM/DD 形式にする\n // 曜日が含まれている場合は括弧を追加する\n // 参考: https://smarthr.design/products/contents/idiomatic-usage/count/#h2-3\n ja: {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'ja-easy': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'en-us': {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'id-id': {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n ko: {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n pt: {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n vi: {\n year: 'numeric',\n month: 'long',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n 'zh-cn': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'zh-tw': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n} as const\n\n/**\n * 各ロケールの括弧設定マップ\n * ロケールに応じて適切な括弧スタイル(半角/全角)と配置を定義\n */\nconst WEEKDAY_FORMATS: Record<keyof typeof locales, { replacer: (base: string) => string }> = {\n ja: { replacer: (base) => base.replace(/(.+?)\\(([月火水木金土日])\\)$/, '$1($2)') },\n 'ja-easy': { replacer: (base) => base.replace(/(.+?)\\(([月火水木金土日])\\)$/, '$1($2)') },\n 'en-us': { replacer: (base) => base.replace(/^([A-Za-z]{3}), (.+)$/, '$2 ($1)') },\n 'id-id': { replacer: (base) => base.replace(/^([A-Za-z]{3}), (.+)$/, '$2 ($1)') },\n ko: {\n replacer: (base) => base.replace(/\\s{2,}/g, ' ').replace(/([월화수목금토일])$/, '($1)'),\n },\n pt: { replacer: (base) => base.replace(/^([A-Za-z]{3}\\.), (.+)$/, '$2 ($1)') },\n vi: { replacer: (base) => base.replace(/^(\\S+ \\d+), (.+)$/, '$2 ($1)') },\n 'zh-cn': { replacer: (base) => base.replace(/(.+?)\\s*([周][一二三四五六日])$/, '$1($2)') },\n 'zh-tw': { replacer: (base) => base.replace(/(.+?)\\s*([週][一二三四五六日])$/, '$1($2)') },\n} as const\n\nconst COMMON_TIME_FORMAT: Intl.DateTimeFormatOptions = {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n}\n\nconst TIME_FORMATS: Record<keyof typeof locales, Intl.DateTimeFormatOptions> = {\n ja: COMMON_TIME_FORMAT,\n 'ja-easy': COMMON_TIME_FORMAT,\n 'en-us': {\n ...COMMON_TIME_FORMAT,\n hour: 'numeric',\n hour12: true,\n },\n 'id-id': COMMON_TIME_FORMAT,\n ko: COMMON_TIME_FORMAT,\n pt: COMMON_TIME_FORMAT,\n vi: COMMON_TIME_FORMAT,\n 'zh-cn': COMMON_TIME_FORMAT,\n 'zh-tw': COMMON_TIME_FORMAT,\n} as const\n\nconst isValidLocale = (locale: string): locale is keyof typeof locales => locale in locales\n\nconst applyCapitalization = (text: string, shouldCapitalize: boolean) =>\n shouldCapitalize ? text.charAt(0).toUpperCase() + text.slice(1) : text\n\n/**\n * 多言語化機能を提供するフック\n * react-intlをベースにした国際化機能を提供します\n *\n * @returns {UseIntlReturn} 国際化に関連する関数とプロパティを含むオブジェクト\n * @example\n * // 基本的な使用法(メッセージのローカライズ)\n * const Component = () => {\n * const { localize } = useIntl()\n * return <span>{localize({ id: 'smarthr-ui/common/language', defaultText: '日本語' })}</span>\n * }\n *\n * @example\n * // 日付のフォーマット\n * const Component = () => {\n * const { formatDate } = useIntl()\n * return <span>{formatDate({ date: new Date(2024, 1 - 1, 15) })}</span> // \"2024/01/15\" (ja)\n * }\n *\n * @example\n * // 時刻のフォーマット\n * const Component = () => {\n * const { formatTime } = useIntl()\n * return <span>{formatTime({ date: new Date(2024, 1 - 1, 15, 10, 30, 0) })}</span> // \"10:30\" (ja)\n * }\n *\n * @example\n * // 利用可能なロケールの確認\n * const Component = () => {\n * const { availableLocales, locale } = useIntl()\n * return <div>現在のロケール: {locale}</div>\n * }\n */\nexport const useIntl = (): UseIntlReturn => {\n const intl = useReactIntl()\n const locale = isValidLocale(intl.locale) ? intl.locale : 'ja'\n const availableLocales = useAvailableLocales()\n\n const localize = useCallback(\n <T extends keyof Messages>(\n descriptor: MessageDescriptor<T>,\n values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,\n opts?: IntlMessageFormatOptions,\n ): string =>\n intl.formatMessage({ ...descriptor, defaultMessage: descriptor.defaultText }, values, opts),\n [intl],\n )\n\n const formatDate = useCallback(\n ({ date, parts = ['year', 'month', 'day'], options }: FormatDateProps): string => {\n const {\n disableSlashInJa = false,\n capitalizeFirstLetter = false,\n year,\n month,\n day,\n weekday,\n ...rest\n } = options || {}\n\n // パーツの存在を事前に計算\n const hasPart = parts.reduce(\n (prev, part) => {\n prev[part] = true\n return prev\n },\n { year: false, month: false, day: false, weekday: false } as {\n year: boolean\n month: boolean\n day: boolean\n weekday: boolean\n },\n )\n\n // ロケールのデフォルト形式を取得\n const isJaKanjiFormat = disableSlashInJa && locale === 'ja'\n const defaultFormats = DATE_FORMATS[locale]\n\n // local が 'ja' で漢字表記の場合はゼロ埋めをしないようにする\n const defaultMonth = isJaKanjiFormat ? 'long' : defaultFormats.month\n const defaultDay = isJaKanjiFormat ? 'numeric' : defaultFormats.day\n\n const actualFormatOptions: Intl.DateTimeFormatOptions = {\n ...rest,\n year: year ?? (hasPart.year ? defaultFormats.year : undefined),\n month: month ?? (hasPart.month ? defaultMonth : undefined),\n day: day ?? (hasPart.day ? defaultDay : undefined),\n weekday: weekday ?? (hasPart.weekday ? defaultFormats.weekday : undefined),\n }\n\n const formattedDate = intl.formatDate(date, actualFormatOptions)\n\n // 曜日をロケールに応じてフォーマットする\n let formattedResult = formattedDate\n const config = WEEKDAY_FORMATS[locale]\n // 曜日が含まれており、かつ曜日のみの表示でない場合は括弧を追加\n // 例: \"2025/01/01(水)\" → 括弧あり, \"水\" → 括弧なし\n if (config && hasPart.weekday && (parts.length !== 1 || parts[0] !== 'weekday')) {\n formattedResult = config.replacer(formattedDate)\n }\n\n return applyCapitalization(formattedResult, capitalizeFirstLetter)\n },\n [intl, locale],\n )\n\n const formatTime = useCallback(\n ({ date, parts = ['hour', 'minute'], options }: FormatTimeProps): string => {\n const formatOptions = options || {}\n\n const hasPart = parts.reduce(\n (prev, part) => {\n prev[part] = true\n return prev\n },\n { hour: false, minute: false, second: false } as {\n hour: boolean\n minute: boolean\n second: boolean\n },\n )\n\n const actualFormatOptions: Intl.DateTimeFormatOptions = {\n ...formatOptions,\n hour: formatOptions.hour ?? (hasPart.hour ? TIME_FORMATS[locale].hour : undefined),\n minute: formatOptions.minute ?? (hasPart.minute ? TIME_FORMATS[locale].minute : undefined),\n second: formatOptions.second ?? (hasPart.second ? '2-digit' : undefined),\n hour12: formatOptions.hour12 ?? TIME_FORMATS[locale].hour12,\n }\n\n return intl.formatDate(date, actualFormatOptions)\n },\n [intl, locale],\n )\n\n const formatTimestamp = useCallback(\n ({ date, timeParts = ['hour', 'minute'] }: FormatTimestampProps): string => {\n const formattedDate = formatDate({ date, parts: ['year', 'month', 'day'] })\n const formattedTime = formatTime({ date, parts: timeParts })\n return `${formattedDate} ${formattedTime}`\n },\n [formatDate, formatTime],\n )\n\n const getWeekStartDay = (): number => DATE_FORMATS[locale].weekStartDay\n\n return {\n availableLocales,\n localize,\n formatDate,\n formatTime,\n formatTimestamp,\n locale,\n getWeekStartDay,\n }\n}\n"],"names":[],"mappings":";;;;;;AAkLA;AACE;AACA;AAQF;;;;AAOE;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;;AAGH;;;AAGG;AACH;AACE;AACA;AACA;AACA;AACA;;AAEC;AACD;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;AACE;AACA;AACA;AACD;AACD;AACA;AACA;AACA;AACA;AACA;;AAGF;AAEA;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI;AACL;AACA;AACA;AAEA;;;;;AAyBQ;AACA;AACF;;AAUF;AACA;;AAGA;AACA;AAEA;AACE;AACA;AACA;AACA;AACA;;;;;AAOF;;;;AAIE;;AAGF;AACF;AAIF;AAEI;;AAII;AACA;AACF;AAQF;AACE;;;AAGA;;;;AAKJ;AAIF;AAEI;AACA;AACA;AACF;;;;;;;;;;;AAeJ;;"}
|
|
1
|
+
{"version":3,"file":"useIntl.js","sources":["../../src/intl/useIntl.ts"],"sourcesContent":["'use client'\n\nimport { useCallback } from 'react'\nimport {\n type PrimitiveType,\n type MessageDescriptor as ReactIntlMessageDescriptor,\n useIntl as useReactIntl,\n} from 'react-intl'\n\nimport { useAvailableLocales } from './IntlProvider'\nimport { locales, type typedJa } from './locales'\n\nimport type { FormatXMLElementFn, Options as IntlMessageFormatOptions } from 'intl-messageformat'\n\ntype Messages = Record<keyof typeof typedJa, string>\n\ntype MessageDescriptor<T extends keyof Messages> = Omit<ReactIntlMessageDescriptor, 'id'> & {\n id: T\n defaultText: (typeof typedJa)[T]\n}\n\ntype DatePart = 'year' | 'month' | 'day' | 'weekday'\n\ntype TimePart = 'hour' | 'minute' | 'second'\n\nexport type FormatDateProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する日付のパーツ。指定しない場合は全て表示\n */\n parts?: readonly [DatePart, ...DatePart[]]\n\n /**\n * フォーマットオプション\n */\n options?: Intl.DateTimeFormatOptions & {\n /**\n * 日本語ロケールでスラッシュを無効化し、月を長形式で表示する\n * @example\n * // 通常: \"2025/01\"\n * // disableSlashInJa: true の場合: \"2025年1月\"\n */\n disableSlashInJa?: boolean\n\n /**\n * 最初の文字を大文字化する\n * @example\n * // 通常: \"seg.\" (pt)\n * // capitalizeFirstLetter: true の場合: \"Seg.\" (pt)\n */\n capitalizeFirstLetter?: boolean\n }\n}\n\nexport type FormatTimeProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する時刻のパーツ。指定しない場合は ['hour', 'minute'] がデフォルト\n */\n parts?: readonly [TimePart, ...TimePart[]]\n\n /**\n * フォーマットオプション\n */\n options?: Intl.DateTimeFormatOptions\n}\n\nexport type FormatTimestampProps = {\n /**\n * フォーマット対象の日付\n */\n date: Date\n\n /**\n * 表示する時刻のパーツ。指定しない場合は ['hour', 'minute'] がデフォルト\n */\n timeParts?: readonly [TimePart, ...TimePart[]]\n}\n\n/**\n * useIntlフックの戻り値の型定義\n */\nexport type UseIntlReturn = {\n /** 利用可能なロケールのリスト */\n availableLocales: string[]\n /** メッセージのローカライズ関数 */\n localize: <T extends keyof Messages>(\n descriptor: MessageDescriptor<T>,\n values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,\n opts?: IntlMessageFormatOptions,\n ) => string\n\n /**\n * 日付をロケールに応じた形式でフォーマットする関数\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.parts - 表示する日付のパーツ。デフォルトは ['year', 'month', 'day', 'weekday']\n * @param props.options - フォーマットオプション\n * @param props.options.disableSlashInJa - 日本語ロケールでスラッシュを無効化し、月を長形式で表示する\n * @param props.options.capitalizeFirstLetter - 最初の文字を大文字化する\n * @returns フォーマットされた日付文字列\n * @example\n * // 基本的な使用法(ロケールのデフォルト形式:曜日なし)\n * formatDate({ date: new Date() }) // \"2024/01/15\" (ja)\n *\n * // 日付を曜日ありで表示\n * formatDate({ date: new Date(), parts: ['year', 'month', 'day', 'weekday'] }) // \"2024/01/15(水)\" (ja)\n *\n * // 特定のフィールドのみ表示\n * formatDate({ date: new Date(), parts: ['year', 'month'] }) // \"2024/01\" (ja)\n * formatDate({ date: new Date(), parts: ['weekday'] }) // \"月\" (ja)\n *\n * // 日本語でスラッシュを無効化(月を長形式で表示)\n * formatDate({ date: new Date(), parts: ['year', 'month'], options: { disableSlashInJa: true } }) // \"2024年1月\" (ja)\n *\n * // 最初の文字を大文字化\n * formatDate({ date: new Date(), parts: ['weekday'], options: { capitalizeFirstLetter: true } }) // \"Seg.\" (pt)(指定しなければ \"seg.\")\n */\n formatDate(props: FormatDateProps): string\n\n /**\n * 時刻をロケールに応じた形式でフォーマットする関数\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.parts - 表示する時刻のパーツ。デフォルトは ['hour', 'minute']\n * @param props.options - フォーマットオプション\n * @returns フォーマットされた時刻文字列\n * @example\n * // 基本的な使用法(ロケールのデフォルト形式)\n * formatTime({ date: new Date() }) // \"10:30\" (ja)\n *\n * // 秒を含めて表示\n * formatTime({ date: new Date(), parts: ['hour', 'minute', 'second'] }) // \"10:30:45\" (ja)\n *\n * // 時のみ表示\n * formatTime({ date: new Date(), parts: ['hour'] }) // \"10\" (ja)\n *\n * // 12時間形式で表示\n * formatTime({ date: new Date(), options: { hour12: true } }) // \"午前10:30\" (ja)\n */\n formatTime(props: FormatTimeProps): string\n\n /**\n * タイムスタンプ(日付+時刻)をフォーマットする関数\n * 日付はスラッシュ形式、時刻は24時間形式で表示されます\n * @param props - フォーマットのオプション\n * @param props.date - フォーマット対象の日付\n * @param props.timeParts - 表示する時刻のパーツ。デフォルトは ['hour', 'minute']\n * @returns フォーマットされたタイムスタンプ文字列\n * @example\n * // 基本的な使用法\n * formatTimestamp({ date: new Date() }) // \"2024/01/15 10:30\" (ja)\n *\n * // 秒を含めて表示\n * formatTimestamp({ date: new Date(), timeParts: ['hour', 'minute', 'second'] }) // \"2024/01/15 10:30:45\" (ja)\n */\n formatTimestamp(props: FormatTimestampProps): string\n\n /**\n * 現在のロケールに基づいて週の開始日を決定する関数\n * Intl.Locale.prototype.getWeekInfo()の動作を再現\n * getWeekInfo()を使わない理由は、Firefoxでは動作しないため\n *\n * @returns 週の開始日(0 = 日曜日, 1 = 月曜日, ..., 6 = 土曜日)\n */\n getWeekStartDay: () => number\n /** 現在のロケール */\n locale: keyof typeof locales\n}\n\nconst WEEK_START_DAYS = {\n SUNDAY: 0,\n MONDAY: 1,\n TUESDAY: 2,\n WEDNESDAY: 3,\n THURSDAY: 4,\n FRIDAY: 5,\n SATURDAY: 6,\n} as const\n\nconst DATE_FORMATS: Record<\n keyof typeof locales,\n Intl.DateTimeFormatOptions & { weekStartDay: number }\n> = {\n // localeがja, ja-easyの場合、フォーマットを YYYY/MM/DD 形式にする\n // 曜日が含まれている場合は括弧を追加する\n // 参考: https://smarthr.design/products/contents/idiomatic-usage/count/#h2-3\n ja: {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'ja-easy': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'en-us': {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'id-id': {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n ko: {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n pt: {\n year: 'numeric',\n month: 'short',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n vi: {\n year: 'numeric',\n month: 'long',\n day: '2-digit',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.MONDAY,\n },\n 'zh-cn': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n 'zh-tw': {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'short',\n weekStartDay: WEEK_START_DAYS.SUNDAY,\n },\n} as const\n\n/**\n * 各ロケールの括弧設定マップ\n * ロケールに応じて適切な括弧スタイル(半角/全角)と配置を定義\n */\nconst WEEKDAY_FORMATS: Record<keyof typeof locales, { replacer: (base: string) => string }> = {\n ja: { replacer: (base) => base.replace(/(.+?)\\(([月火水木金土日])\\)$/, '$1($2)') },\n 'ja-easy': { replacer: (base) => base.replace(/(.+?)\\(([月火水木金土日])\\)$/, '$1($2)') },\n 'en-us': { replacer: (base) => base.replace(/^([A-Za-z]{3}), (.+)$/, '$2 ($1)') },\n 'id-id': { replacer: (base) => base.replace(/^([A-Za-z]{3}), (.+)$/, '$2 ($1)') },\n ko: {\n replacer: (base) => base.replace(/\\s{2,}/g, ' ').replace(/([월화수목금토일])$/, '($1)'),\n },\n pt: { replacer: (base) => base.replace(/^([A-Za-z]{3}\\.), (.+)$/, '$2 ($1)') },\n vi: { replacer: (base) => base.replace(/^(\\S+ \\d+), (.+)$/, '$2 ($1)') },\n 'zh-cn': { replacer: (base) => base.replace(/(.+?)\\s*([周][一二三四五六日])$/, '$1($2)') },\n 'zh-tw': { replacer: (base) => base.replace(/(.+?)\\s*([週][一二三四五六日])$/, '$1($2)') },\n} as const\n\nconst COMMON_TIME_FORMAT: Intl.DateTimeFormatOptions = {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n}\n\nconst TIME_FORMATS: Record<keyof typeof locales, Intl.DateTimeFormatOptions> = {\n ja: COMMON_TIME_FORMAT,\n 'ja-easy': COMMON_TIME_FORMAT,\n 'en-us': {\n ...COMMON_TIME_FORMAT,\n hour: 'numeric',\n hour12: true,\n },\n 'id-id': COMMON_TIME_FORMAT,\n ko: COMMON_TIME_FORMAT,\n pt: COMMON_TIME_FORMAT,\n vi: COMMON_TIME_FORMAT,\n 'zh-cn': COMMON_TIME_FORMAT,\n 'zh-tw': COMMON_TIME_FORMAT,\n} as const\n\nconst isValidLocale = (locale: string): locale is keyof typeof locales => locale in locales\n\nconst applyCapitalization = (text: string, shouldCapitalize: boolean) =>\n shouldCapitalize ? text.charAt(0).toUpperCase() + text.slice(1) : text\n\n/**\n * 多言語化機能を提供するフック\n * react-intlをベースにした国際化機能を提供します\n *\n * @returns {UseIntlReturn} 国際化に関連する関数とプロパティを含むオブジェクト\n * @example\n * // 基本的な使用法(メッセージのローカライズ)\n * const Component = () => {\n * const { localize } = useIntl()\n * return <span>{localize({ id: 'smarthr-ui/common/language', defaultText: '日本語' })}</span>\n * }\n *\n * @example\n * // 日付のフォーマット\n * const Component = () => {\n * const { formatDate } = useIntl()\n * return <span>{formatDate({ date: new Date(2024, 1 - 1, 15) })}</span> // \"2024/01/15\" (ja)\n * }\n *\n * @example\n * // 時刻のフォーマット\n * const Component = () => {\n * const { formatTime } = useIntl()\n * return <span>{formatTime({ date: new Date(2024, 1 - 1, 15, 10, 30, 0) })}</span> // \"10:30\" (ja)\n * }\n *\n * @example\n * // 利用可能なロケールの確認\n * const Component = () => {\n * const { availableLocales, locale } = useIntl()\n * return <div>現在のロケール: {locale}</div>\n * }\n */\nexport const useIntl = (): UseIntlReturn => {\n const intl = useReactIntl()\n const locale = isValidLocale(intl.locale) ? intl.locale : 'ja'\n const availableLocales = useAvailableLocales()\n\n const localize = useCallback(\n <T extends keyof Messages>(\n descriptor: MessageDescriptor<T>,\n values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,\n opts?: IntlMessageFormatOptions,\n ): string =>\n intl.formatMessage({ ...descriptor, defaultMessage: descriptor.defaultText }, values, opts),\n [intl],\n )\n\n const formatDate = useCallback(\n ({ date, parts = ['year', 'month', 'day'], options }: FormatDateProps): string => {\n const {\n disableSlashInJa = false,\n capitalizeFirstLetter = false,\n year,\n month,\n day,\n weekday,\n ...rest\n } = options || {}\n\n // パーツの存在を事前に計算\n const hasPart = parts.reduce(\n (prev, part) => {\n prev[part] = true\n return prev\n },\n { year: false, month: false, day: false, weekday: false } as {\n year: boolean\n month: boolean\n day: boolean\n weekday: boolean\n },\n )\n\n // ロケールのデフォルト形式を取得\n const isJaKanjiFormat = disableSlashInJa && locale === 'ja'\n const defaultFormats = DATE_FORMATS[locale]\n\n // local が 'ja' で漢字表記の場合はゼロ埋めをしないようにする\n const defaultMonth = isJaKanjiFormat ? 'long' : defaultFormats.month\n const defaultDay = isJaKanjiFormat ? 'numeric' : defaultFormats.day\n\n const actualFormatOptions: Intl.DateTimeFormatOptions = {\n ...rest,\n year: year ?? (hasPart.year ? defaultFormats.year : undefined),\n month: month ?? (hasPart.month ? defaultMonth : undefined),\n day: day ?? (hasPart.day ? defaultDay : undefined),\n weekday: weekday ?? (hasPart.weekday ? defaultFormats.weekday : undefined),\n }\n\n const formattedDate = intl.formatDate(date, actualFormatOptions)\n\n // 曜日をロケールに応じてフォーマットする\n let formattedResult = formattedDate\n const config = WEEKDAY_FORMATS[locale]\n // 曜日が含まれており、かつ曜日のみの表示でない場合は括弧を追加\n // 例: \"2025/01/01(水)\" → 括弧あり, \"水\" → 括弧なし\n if (config && hasPart.weekday && (parts.length !== 1 || parts[0] !== 'weekday')) {\n formattedResult = config.replacer(formattedDate)\n }\n\n return applyCapitalization(formattedResult, capitalizeFirstLetter)\n },\n [intl, locale],\n )\n\n const formatTime = useCallback(\n ({ date, parts = ['hour', 'minute'], options }: FormatTimeProps): string => {\n const formatOptions = options || {}\n\n const hasPart = parts.reduce(\n (prev, part) => {\n prev[part] = true\n return prev\n },\n { hour: false, minute: false, second: false } as {\n hour: boolean\n minute: boolean\n second: boolean\n },\n )\n\n const actualFormatOptions: Intl.DateTimeFormatOptions = {\n ...formatOptions,\n hour: formatOptions.hour ?? (hasPart.hour ? TIME_FORMATS[locale].hour : undefined),\n minute: formatOptions.minute ?? (hasPart.minute ? TIME_FORMATS[locale].minute : undefined),\n second: formatOptions.second ?? (hasPart.second ? '2-digit' : undefined),\n hour12: formatOptions.hour12 ?? TIME_FORMATS[locale].hour12,\n }\n\n return intl.formatDate(date, actualFormatOptions)\n },\n [intl, locale],\n )\n\n const formatTimestamp = useCallback(\n ({ date, timeParts = ['hour', 'minute'] }: FormatTimestampProps): string => {\n const formattedDate = formatDate({ date, parts: ['year', 'month', 'day'] })\n const formattedTime = formatTime({ date, parts: timeParts })\n return `${formattedDate} ${formattedTime}`\n },\n [formatDate, formatTime],\n )\n\n const getWeekStartDay = (): number => DATE_FORMATS[locale].weekStartDay\n\n return {\n availableLocales,\n localize,\n formatDate,\n formatTime,\n formatTimestamp,\n locale,\n getWeekStartDay,\n }\n}\n"],"names":[],"mappings":";;;;;;AAkLA;AACE;AACA;AAQF;;;;AAOE;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;AACD;AACE;AACA;AACA;AACA;;AAED;;AAGH;;;AAGG;AACH;AACE;AACA;AACA;AACA;AACA;;AAEC;AACD;AACA;AACA;AACA;;AAGF;AACE;AACA;AACA;;AAGF;AACE;AACA;AACA;AACE;AACA;AACA;AACD;AACD;AACA;AACA;AACA;AACA;AACA;;AAGF;AAEA;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI;AACL;AACA;AACA;AAEA;;;;;AAyBQ;AACA;AACF;;AAUF;AACA;;AAGA;AACA;AAEA;AACE;AACA;AACA;AACA;AACA;;;;;AAOF;;;;AAIE;;AAGF;AACF;AAIF;AAEI;;AAII;AACA;AACF;AAQF;AACE;;;AAGA;;;;AAKJ;AAIF;AAEI;AACA;AACA;AACF;;;;;;;;;;;AAeJ;;"}
|