@zenkigen-inc/component-ui 1.22.0 → 1.23.1

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/dist/index.d.mts CHANGED
@@ -183,6 +183,8 @@ declare const Combobox: typeof ComboboxBase & {
183
183
  displayName: string;
184
184
  };
185
185
 
186
+ type DatePickerSize = 'small' | 'medium' | 'large' | 'x-large';
187
+
186
188
  /**
187
189
  * DatePicker のエラーメッセージを表示するコンポーネントのプロパティ
188
190
  *
@@ -220,8 +222,15 @@ type DatePickerProps = DatePickerButtonProps & {
220
222
  maxDate?: Date;
221
223
  /** 未選択時に表示されるプレースホルダーテキスト @default '日付を選択' */
222
224
  placeholder?: string;
223
- /** トリガーボタンのサイズ @default 'medium' */
224
- size?: 'small' | 'medium' | 'large';
225
+ /**
226
+ * トリガーボタンのサイズ。`'x-large'` はカレンダーも拡大される(342×437px)
227
+ *
228
+ * `'x-large'` はモバイル向け。カレンダーがスクロールしないため、ビューポート幅 358px 以上、
229
+ * かつトリガーの上下いずれかに 445px 以上の余白が確保できるレイアウトでのみ使用すること。
230
+ * 満たせない場合はフッターが画面外に出て操作できなくなるため `'large'` 以下を選ぶ。
231
+ * @default 'medium'
232
+ */
233
+ size?: DatePickerSize;
225
234
  /** 日付変換に使用するタイムゾーン。選択された日付は指定タイムゾーンの 00:00:00 として返される @default 'Asia/Tokyo' */
226
235
  timeZone?: DatePickerTimeZone;
227
236
  /** Compound Component(ErrorMessage 等) */
@@ -1122,33 +1131,47 @@ declare const TimePicker: TimePickerComponent;
1122
1131
  type ToastState = 'success' | 'error' | 'warning' | 'information';
1123
1132
 
1124
1133
  type Props$1 = {
1125
- /** 表示するメッセージの状態(色・アイコンを切り替えます) */
1134
+ /** トーストの状態を表す。表示するアイコンとタイトルの文字色が切り替わる。 */
1126
1135
  state?: ToastState;
1127
- /** トースト全体の幅。数値・文字列いずれも指定可能 */
1136
+ /** トースト全体の幅。数値・文字列いずれも指定できる。 */
1128
1137
  width?: CSSProperties['width'];
1129
- /** true 5 秒後に自動で閉じる */
1138
+ /** true のとき 5 秒後に自動で閉じ、onClickClose を呼ぶ。既定は false(ToastProvider 経由のトーストには既定で true が渡される)。 */
1130
1139
  isAutoClose?: boolean;
1131
- /** true でフェードイン/アウトのアニメーションを有効化 */
1140
+ /** true のときフェードイン / フェードアウトのアニメーションを有効にする。 */
1132
1141
  isAnimation?: boolean;
1133
- /** 表示する本文 */
1142
+ /** true のとき閉じるボタンを表示する。isAutoClose が false のときは指定に関わらず必ず表示される。 */
1143
+ hasCloseButton?: boolean;
1144
+ /** タイトルの下に表示する補足テキスト。 */
1145
+ description?: ReactNode;
1146
+ /** タイトルとして表示する本文。 */
1134
1147
  children?: ReactNode;
1135
- /** クローズボタンや自動クローズ完了時に呼び出されるコールバック */
1148
+ /** 閉じるボタン押下時および自動クローズ完了時に呼ばれる、トースト終了の通知コールバック。 */
1136
1149
  onClickClose: () => void;
1137
1150
  };
1138
- declare function Toast({ state, width, isAutoClose, isAnimation, children, onClickClose, }: Props$1): react.JSX.Element;
1151
+ declare function Toast({ state, width, isAutoClose, isAnimation, hasCloseButton, description, children, onClickClose, }: Props$1): react.JSX.Element;
1139
1152
 
1140
1153
  type AddToastArgs = {
1141
- /** 表示する本文 */
1154
+ /** タイトルとして表示する本文 */
1142
1155
  message: string;
1143
1156
  /** 表示ステート */
1144
1157
  state: ToastState;
1158
+ /** タイトルの下に表示する補足テキスト */
1159
+ description?: ReactNode;
1160
+ /** 閉じるボタンを表示するかどうか。ToastProvider の既定値を上書きする */
1161
+ hasCloseButton?: boolean;
1162
+ /** 5 秒後に自動で閉じるかどうか。既定は true */
1163
+ isAutoClose?: boolean;
1145
1164
  };
1146
- type ToastProviderProps = {
1165
+ type ToastContextValue = {
1147
1166
  addToast: (args: AddToastArgs) => void;
1148
1167
  removeToast: (id: number) => void;
1149
1168
  };
1150
- declare const ToastProvider: ({ children }: PropsWithChildren) => react.JSX.Element;
1151
- declare const useToast: () => ToastProviderProps;
1169
+ type ToastProviderProps = PropsWithChildren<{
1170
+ /** このプロバイダー配下で追加されるトーストの、閉じるボタン表示の既定値 */
1171
+ hasCloseButton?: boolean;
1172
+ }>;
1173
+ declare const ToastProvider: ({ children, hasCloseButton }: ToastProviderProps) => react.JSX.Element;
1174
+ declare const useToast: () => ToastContextValue;
1152
1175
 
1153
1176
  /** Toggle コンポーネントの公開 Props */
1154
1177
  type Props = {
package/dist/index.d.ts CHANGED
@@ -183,6 +183,8 @@ declare const Combobox: typeof ComboboxBase & {
183
183
  displayName: string;
184
184
  };
185
185
 
186
+ type DatePickerSize = 'small' | 'medium' | 'large' | 'x-large';
187
+
186
188
  /**
187
189
  * DatePicker のエラーメッセージを表示するコンポーネントのプロパティ
188
190
  *
@@ -220,8 +222,15 @@ type DatePickerProps = DatePickerButtonProps & {
220
222
  maxDate?: Date;
221
223
  /** 未選択時に表示されるプレースホルダーテキスト @default '日付を選択' */
222
224
  placeholder?: string;
223
- /** トリガーボタンのサイズ @default 'medium' */
224
- size?: 'small' | 'medium' | 'large';
225
+ /**
226
+ * トリガーボタンのサイズ。`'x-large'` はカレンダーも拡大される(342×437px)
227
+ *
228
+ * `'x-large'` はモバイル向け。カレンダーがスクロールしないため、ビューポート幅 358px 以上、
229
+ * かつトリガーの上下いずれかに 445px 以上の余白が確保できるレイアウトでのみ使用すること。
230
+ * 満たせない場合はフッターが画面外に出て操作できなくなるため `'large'` 以下を選ぶ。
231
+ * @default 'medium'
232
+ */
233
+ size?: DatePickerSize;
225
234
  /** 日付変換に使用するタイムゾーン。選択された日付は指定タイムゾーンの 00:00:00 として返される @default 'Asia/Tokyo' */
226
235
  timeZone?: DatePickerTimeZone;
227
236
  /** Compound Component(ErrorMessage 等) */
@@ -1122,33 +1131,47 @@ declare const TimePicker: TimePickerComponent;
1122
1131
  type ToastState = 'success' | 'error' | 'warning' | 'information';
1123
1132
 
1124
1133
  type Props$1 = {
1125
- /** 表示するメッセージの状態(色・アイコンを切り替えます) */
1134
+ /** トーストの状態を表す。表示するアイコンとタイトルの文字色が切り替わる。 */
1126
1135
  state?: ToastState;
1127
- /** トースト全体の幅。数値・文字列いずれも指定可能 */
1136
+ /** トースト全体の幅。数値・文字列いずれも指定できる。 */
1128
1137
  width?: CSSProperties['width'];
1129
- /** true 5 秒後に自動で閉じる */
1138
+ /** true のとき 5 秒後に自動で閉じ、onClickClose を呼ぶ。既定は false(ToastProvider 経由のトーストには既定で true が渡される)。 */
1130
1139
  isAutoClose?: boolean;
1131
- /** true でフェードイン/アウトのアニメーションを有効化 */
1140
+ /** true のときフェードイン / フェードアウトのアニメーションを有効にする。 */
1132
1141
  isAnimation?: boolean;
1133
- /** 表示する本文 */
1142
+ /** true のとき閉じるボタンを表示する。isAutoClose が false のときは指定に関わらず必ず表示される。 */
1143
+ hasCloseButton?: boolean;
1144
+ /** タイトルの下に表示する補足テキスト。 */
1145
+ description?: ReactNode;
1146
+ /** タイトルとして表示する本文。 */
1134
1147
  children?: ReactNode;
1135
- /** クローズボタンや自動クローズ完了時に呼び出されるコールバック */
1148
+ /** 閉じるボタン押下時および自動クローズ完了時に呼ばれる、トースト終了の通知コールバック。 */
1136
1149
  onClickClose: () => void;
1137
1150
  };
1138
- declare function Toast({ state, width, isAutoClose, isAnimation, children, onClickClose, }: Props$1): react.JSX.Element;
1151
+ declare function Toast({ state, width, isAutoClose, isAnimation, hasCloseButton, description, children, onClickClose, }: Props$1): react.JSX.Element;
1139
1152
 
1140
1153
  type AddToastArgs = {
1141
- /** 表示する本文 */
1154
+ /** タイトルとして表示する本文 */
1142
1155
  message: string;
1143
1156
  /** 表示ステート */
1144
1157
  state: ToastState;
1158
+ /** タイトルの下に表示する補足テキスト */
1159
+ description?: ReactNode;
1160
+ /** 閉じるボタンを表示するかどうか。ToastProvider の既定値を上書きする */
1161
+ hasCloseButton?: boolean;
1162
+ /** 5 秒後に自動で閉じるかどうか。既定は true */
1163
+ isAutoClose?: boolean;
1145
1164
  };
1146
- type ToastProviderProps = {
1165
+ type ToastContextValue = {
1147
1166
  addToast: (args: AddToastArgs) => void;
1148
1167
  removeToast: (id: number) => void;
1149
1168
  };
1150
- declare const ToastProvider: ({ children }: PropsWithChildren) => react.JSX.Element;
1151
- declare const useToast: () => ToastProviderProps;
1169
+ type ToastProviderProps = PropsWithChildren<{
1170
+ /** このプロバイダー配下で追加されるトーストの、閉じるボタン表示の既定値 */
1171
+ hasCloseButton?: boolean;
1172
+ }>;
1173
+ declare const ToastProvider: ({ children, hasCloseButton }: ToastProviderProps) => react.JSX.Element;
1174
+ declare const useToast: () => ToastContextValue;
1152
1175
 
1153
1176
  /** Toggle コンポーネントの公開 Props */
1154
1177
  type Props = {
package/dist/index.js CHANGED
@@ -1747,6 +1747,7 @@ var PopoverTrigger = (0, import_react24.forwardRef)(function PopoverTrigger2({ c
1747
1747
 
1748
1748
  // src/popover/popover.tsx
1749
1749
  var import_jsx_runtime22 = require("react/jsx-runtime");
1750
+ var FLOATING_VIEWPORT_PADDING2 = 8;
1750
1751
  function Popover({
1751
1752
  isOpen,
1752
1753
  children,
@@ -1756,6 +1757,14 @@ function Popover({
1756
1757
  anchorRef
1757
1758
  }) {
1758
1759
  const triggerRef = (0, import_react26.useRef)(null);
1760
+ const middleware = (0, import_react26.useMemo)(
1761
+ () => [
1762
+ (0, import_react25.offset)(offsetValue),
1763
+ (0, import_react25.flip)({ padding: FLOATING_VIEWPORT_PADDING2, flipAlignment: false }),
1764
+ (0, import_react25.shift)({ padding: FLOATING_VIEWPORT_PADDING2 })
1765
+ ],
1766
+ [offsetValue]
1767
+ );
1759
1768
  const floating = (0, import_react25.useFloating)({
1760
1769
  open: isOpen,
1761
1770
  onOpenChange: (open) => {
@@ -1764,7 +1773,7 @@ function Popover({
1764
1773
  }
1765
1774
  },
1766
1775
  placement,
1767
- middleware: [(0, import_react25.offset)(offsetValue)],
1776
+ middleware,
1768
1777
  whileElementsMounted: import_react25.autoUpdate,
1769
1778
  strategy: "fixed"
1770
1779
  });
@@ -1812,27 +1821,83 @@ var import_react_day_picker2 = require("react-day-picker");
1812
1821
  var import_clsx15 = require("clsx");
1813
1822
  var import_react_day_picker = require("react-day-picker");
1814
1823
  var defaultDayPickerClassNames = (0, import_react_day_picker.getDefaultClassNames)();
1815
- var DAY_PICKER_FONT_SIZE = "12px";
1816
- var dayPickerStyle = {
1817
- "--rdp-nav-height": "30px",
1818
- "--rdp-day-width": "30px",
1819
- "--rdp-day-height": "30px",
1820
- "--rdp-day_button-width": "28px",
1821
- "--rdp-day_button-height": "28px",
1822
- "--rdp-day_button-border": "1px solid transparent",
1823
- "--rdp-weekday-padding": "0px",
1824
- fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1825
- fontSize: DAY_PICKER_FONT_SIZE,
1826
- fontWeight: 700
1824
+ var BASE_TOKENS = {
1825
+ triggerIcon: "small",
1826
+ dayPickerStyle: {
1827
+ "--rdp-nav-height": "30px",
1828
+ "--rdp-day-width": "30px",
1829
+ "--rdp-day-height": "30px",
1830
+ "--rdp-day_button-width": "28px",
1831
+ "--rdp-day_button-height": "28px",
1832
+ "--rdp-day_button-border": "1px solid transparent",
1833
+ "--rdp-weekday-padding": "0px",
1834
+ fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1835
+ fontSize: "12px",
1836
+ fontWeight: 700
1837
+ },
1838
+ dayPickerClassNames: {
1839
+ month: (0, import_clsx15.clsx)(defaultDayPickerClassNames.month, "flex flex-col px-[7px] py-2")
1840
+ },
1841
+ dayButtonClass: "relative grid size-full place-items-center rounded-full !border !border-solid",
1842
+ dayButtonFontSize: "12px",
1843
+ monthCaptionClass: "flex items-center justify-between px-1 pb-0.5",
1844
+ monthCaptionTypography: "typography-label12bold",
1845
+ navIconButton: "small",
1846
+ weekdayClass: "m-0 size-7 p-0 text-center align-middle",
1847
+ footerIconButton: "medium",
1848
+ footerClearButton: "small",
1849
+ errorTypography: "typography-label11regular"
1850
+ };
1851
+ var LARGE_TOKENS = {
1852
+ ...BASE_TOKENS,
1853
+ triggerIcon: "medium",
1854
+ errorTypography: "typography-label12regular"
1827
1855
  };
1828
- var dayPickerClassNames = {
1829
- month: (0, import_clsx15.clsx)(defaultDayPickerClassNames.month, "flex flex-col px-[7px] py-2")
1856
+ var X_LARGE_TOKENS = {
1857
+ triggerIcon: "medium",
1858
+ dayPickerStyle: {
1859
+ "--rdp-nav-height": "40px",
1860
+ "--rdp-day-width": "48px",
1861
+ "--rdp-day-height": "48px",
1862
+ "--rdp-day_button-width": "40px",
1863
+ "--rdp-day_button-height": "40px",
1864
+ "--rdp-day_button-border": "1px solid transparent",
1865
+ "--rdp-weekday-padding": "0px",
1866
+ fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1867
+ fontSize: "16px",
1868
+ fontWeight: 700
1869
+ },
1870
+ dayPickerClassNames: {
1871
+ month: (0, import_clsx15.clsx)(defaultDayPickerClassNames.month, "flex flex-col px-[3px] pb-1 pt-2")
1872
+ },
1873
+ dayButtonClass: "relative grid size-10 place-items-center rounded-full !border !border-solid",
1874
+ dayButtonFontSize: "16px",
1875
+ // caption は height 固定(--rdp-nav-height: 40px)のため pb-2 は食い込みとして働き、
1876
+ // ナビボタンが上へ 4px はみ出して月ヘッダーと曜日行の視覚間隔が 8px になる(上部ブロックコメント参照)
1877
+ monthCaptionClass: "flex items-center justify-between px-1 pb-2",
1878
+ monthCaptionTypography: "typography-label16bold",
1879
+ // IconButton に x-large は無いが、large が 40px で Figma と一致する(内部アイコンも 24px になる)
1880
+ navIconButton: "large",
1881
+ weekdayClass: "m-0 size-12 p-0 text-center align-middle",
1882
+ footerIconButton: "large",
1883
+ footerClearButton: "large",
1884
+ errorTypography: "typography-label12regular"
1885
+ };
1886
+ var DATE_PICKER_SIZE_TOKENS = {
1887
+ small: BASE_TOKENS,
1888
+ medium: BASE_TOKENS,
1889
+ large: LARGE_TOKENS,
1890
+ "x-large": X_LARGE_TOKENS
1891
+ };
1892
+ var useDatePickerSizeTokens = (componentName = "DatePicker \u306E\u30AB\u30EC\u30F3\u30C0\u30FC") => {
1893
+ const context = useDatePickerCompoundContext(componentName);
1894
+ return { ...context, tokens: DATE_PICKER_SIZE_TOKENS[context.size] };
1830
1895
  };
1831
- var dayButtonBaseClass = "relative grid size-full place-items-center rounded-full !border !border-solid";
1832
1896
 
1833
1897
  // src/date-picker/date-picker-day-button.tsx
1834
1898
  var import_jsx_runtime23 = require("react/jsx-runtime");
1835
1899
  var CustomDayButton = ({ day, modifiers, className, style, ...buttonProps }) => {
1900
+ const { tokens } = useDatePickerSizeTokens();
1836
1901
  const isSelected = Boolean(modifiers.selected);
1837
1902
  const isOutside = Boolean(modifiers.outside);
1838
1903
  const isMinMaxDisabled = Boolean(modifiers.minMaxDisabled);
@@ -1845,10 +1910,10 @@ var CustomDayButton = ({ day, modifiers, className, style, ...buttonProps }) =>
1845
1910
  ...buttonProps,
1846
1911
  day,
1847
1912
  modifiers,
1848
- style: { ...style, fontSize: DAY_PICKER_FONT_SIZE },
1913
+ style: { ...style, fontSize: tokens.dayButtonFontSize },
1849
1914
  className: (0, import_clsx16.clsx)(
1850
1915
  className,
1851
- dayButtonBaseClass,
1916
+ tokens.dayButtonClass,
1852
1917
  // 共通: フォーカスリング(有効な日のみ)
1853
1918
  // react-day-picker の rdp-day_button クラスが outline: none を設定しているため、!important で上書き
1854
1919
  !isDisabledDay && import_component_theme6.focusVisible.normalImportant,
@@ -1874,8 +1939,8 @@ var import_react28 = require("react");
1874
1939
  var import_jsx_runtime24 = require("react/jsx-runtime");
1875
1940
  var DatePickerErrorMessage = (0, import_react28.forwardRef)(
1876
1941
  ({ "aria-live": ariaLive = "assertive", ...props }, ref) => {
1877
- const { size, isError } = useDatePickerCompoundContext("DatePicker.ErrorMessage");
1878
- const typographyClass = size === "large" ? "typography-label12regular" : "typography-label11regular";
1942
+ const { isError, tokens } = useDatePickerSizeTokens("DatePicker.ErrorMessage");
1943
+ const typographyClass = tokens.errorTypography;
1879
1944
  if (isError !== true) {
1880
1945
  return null;
1881
1946
  }
@@ -1956,11 +2021,12 @@ var import_jsx_runtime25 = require("react/jsx-runtime");
1956
2021
  var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...props }) => {
1957
2022
  void displayIndex;
1958
2023
  const { goToMonth, nextMonth, previousMonth } = (0, import_react_day_picker3.useDayPicker)();
2024
+ const { tokens } = useDatePickerSizeTokens();
1959
2025
  const captionMonth = calendarMonth.date;
1960
2026
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1961
2027
  "div",
1962
2028
  {
1963
- className: (0, import_clsx18.clsx)("flex items-center justify-between px-1 pb-0.5", className),
2029
+ className: (0, import_clsx18.clsx)(tokens.monthCaptionClass, className),
1964
2030
  style: { ...style, fontSize: "inherit", fontWeight: "inherit" },
1965
2031
  ...props,
1966
2032
  children: [
@@ -1968,19 +2034,19 @@ var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...pr
1968
2034
  IconButton,
1969
2035
  {
1970
2036
  icon: "angle-left",
1971
- size: "small",
2037
+ size: tokens.navIconButton,
1972
2038
  variant: "text",
1973
2039
  isDisabled: !previousMonth,
1974
2040
  "aria-label": "\u524D\u306E\u6708",
1975
2041
  onClick: () => previousMonth && goToMonth(previousMonth)
1976
2042
  }
1977
2043
  ),
1978
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "typography-label12bold text-text02", children: formatMonthLabel(captionMonth) }),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0, import_clsx18.clsx)(tokens.monthCaptionTypography, "text-text02"), children: formatMonthLabel(captionMonth) }),
1979
2045
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1980
2046
  IconButton,
1981
2047
  {
1982
2048
  icon: "angle-right",
1983
- size: "small",
2049
+ size: tokens.navIconButton,
1984
2050
  variant: "text",
1985
2051
  isDisabled: !nextMonth,
1986
2052
  "aria-label": "\u6B21\u306E\u6708",
@@ -1996,11 +2062,12 @@ var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...pr
1996
2062
  var import_clsx19 = require("clsx");
1997
2063
  var import_jsx_runtime26 = require("react/jsx-runtime");
1998
2064
  var CustomWeekday = ({ className, children, style, ...props }) => {
2065
+ const { tokens } = useDatePickerSizeTokens();
1999
2066
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2000
2067
  "th",
2001
2068
  {
2002
2069
  ...props,
2003
- className: (0, import_clsx19.clsx)(className, "m-0 size-7 p-0 text-center align-middle text-text02"),
2070
+ className: (0, import_clsx19.clsx)(className, tokens.weekdayClass, "text-text02"),
2004
2071
  style: { ...style, fontSize: "inherit", fontWeight: "bold" },
2005
2072
  children
2006
2073
  }
@@ -2135,7 +2202,7 @@ var DatePicker = ({
2135
2202
  formatWeekdayName: (date) => weekdayFormatter.format(date)
2136
2203
  };
2137
2204
  }, []);
2138
- const iconSize = size === "large" ? "medium" : "small";
2205
+ const tokens = DATE_PICKER_SIZE_TOKENS[size];
2139
2206
  const displayText = value ? formatDisplayDate(value, timeZone) : placeholder;
2140
2207
  const displayTextClasses = "min-w-0 truncate";
2141
2208
  const errorIds = [];
@@ -2183,7 +2250,7 @@ var DatePicker = ({
2183
2250
  size,
2184
2251
  variant: isError ? "outlineDanger" : "outline",
2185
2252
  isDisabled,
2186
- before: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Icon, { name: "calendar", size: iconSize }),
2253
+ before: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Icon, { name: "calendar", size: tokens.triggerIcon }),
2187
2254
  justifyContent: "start",
2188
2255
  onClick: handleTriggerClick,
2189
2256
  children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: displayTextClasses, children: displayText })
@@ -2197,7 +2264,7 @@ var DatePicker = ({
2197
2264
  showOutsideDays: true,
2198
2265
  hideNavigation: true,
2199
2266
  weekStartsOn: 0,
2200
- style: dayPickerStyle,
2267
+ style: tokens.dayPickerStyle,
2201
2268
  month: displayMonth,
2202
2269
  onMonthChange: setDisplayMonth,
2203
2270
  selected: selectedDate,
@@ -2205,7 +2272,7 @@ var DatePicker = ({
2205
2272
  today: todayForCalendar,
2206
2273
  disabled: disabledDays,
2207
2274
  modifiers: { minMaxDisabled: isMinMaxDisabled },
2208
- classNames: dayPickerClassNames,
2275
+ classNames: tokens.dayPickerClassNames,
2209
2276
  formatters,
2210
2277
  fixedWeeks: true,
2211
2278
  components: { MonthCaption: CustomMonthCaption, DayButton: CustomDayButton, Weekday: CustomWeekday }
@@ -2216,14 +2283,14 @@ var DatePicker = ({
2216
2283
  IconButton,
2217
2284
  {
2218
2285
  icon: "calendar-today",
2219
- size: "medium",
2286
+ size: tokens.footerIconButton,
2220
2287
  variant: "text",
2221
2288
  "aria-label": "\u4ECA\u65E5\u306B\u623B\u308B",
2222
2289
  iconAccentColor: "supportInfo",
2223
2290
  onClick: handleClickToday
2224
2291
  }
2225
2292
  ),
2226
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Button, { type: "button", size: "small", variant: "text", onClick: handleClear, children: "\u30AF\u30EA\u30A2" })
2293
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Button, { type: "button", size: tokens.footerClearButton, variant: "text", onClick: handleClear, children: "\u30AF\u30EA\u30A2" })
2227
2294
  ] })
2228
2295
  ] }) })
2229
2296
  ] });
@@ -5146,40 +5213,88 @@ TimePicker.ErrorMessage = TimePickerErrorMessage;
5146
5213
  TimePicker.displayName = "TimePicker";
5147
5214
 
5148
5215
  // src/toast/toast.tsx
5149
- var import_clsx56 = __toESM(require("clsx"));
5216
+ var import_clsx56 = require("clsx");
5150
5217
  var import_react73 = require("react");
5151
5218
  var import_jsx_runtime79 = require("react/jsx-runtime");
5152
5219
  var CLOSE_TIME_MSEC = 5e3;
5220
+ var REMOVAL_FALLBACK_MSEC = 1e3;
5153
5221
  function Toast({
5154
5222
  state = "information",
5155
5223
  width = "auto",
5224
+ // 既定 false は v1.22.0 までの互換維持のため据え置き(自動クローズしない既定では、安全弁により閉じるボタンが表示される)。
5225
+ // 「自動クローズ・閉じるボタンなし」の新しい既定は ToastProvider が isAutoClose を明示的に渡すことで実現している。
5156
5226
  isAutoClose = false,
5157
5227
  isAnimation = false,
5228
+ hasCloseButton = false,
5229
+ description,
5158
5230
  children,
5159
5231
  onClickClose
5160
5232
  }) {
5161
5233
  const [isRemoving, setIsRemoving] = (0, import_react73.useState)(false);
5234
+ const onClickCloseRef = (0, import_react73.useRef)(onClickClose);
5235
+ (0, import_react73.useEffect)(() => {
5236
+ onClickCloseRef.current = onClickClose;
5237
+ }, [onClickClose]);
5238
+ const hasNotifiedCloseRef = (0, import_react73.useRef)(false);
5239
+ const notifyClose = (0, import_react73.useCallback)(() => {
5240
+ if (hasNotifiedCloseRef.current) {
5241
+ return;
5242
+ }
5243
+ hasNotifiedCloseRef.current = true;
5244
+ onClickCloseRef.current();
5245
+ }, []);
5162
5246
  const handleClose = (0, import_react73.useCallback)(() => {
5163
5247
  if (isAnimation) {
5164
5248
  setIsRemoving(true);
5165
5249
  } else {
5166
- onClickClose();
5250
+ notifyClose();
5167
5251
  }
5168
- }, [isAnimation, onClickClose]);
5169
- const handleAnimationEnd = (e) => window.getComputedStyle(e.currentTarget).opacity === "0" && onClickClose();
5170
- const wrapperClasses = (0, import_clsx56.default)("pointer-events-auto flex items-start gap-1 bg-white p-4 shadow-floatingShadow", {
5171
- ["animate-toast-in"]: isAnimation && !isRemoving,
5172
- ["animate-toast-out opacity-0"]: isAnimation && isRemoving
5173
- });
5174
- const iconClasses = (0, import_clsx56.default)("flex items-center", {
5252
+ }, [isAnimation, notifyClose]);
5253
+ const handleAnimationEnd = (e) => {
5254
+ if (e.target !== e.currentTarget) {
5255
+ return;
5256
+ }
5257
+ if (window.getComputedStyle(e.currentTarget).opacity === "0") {
5258
+ notifyClose();
5259
+ }
5260
+ };
5261
+ (0, import_react73.useEffect)(() => {
5262
+ if (!isAutoClose) {
5263
+ return;
5264
+ }
5265
+ const timer = window.setTimeout(() => {
5266
+ if (isAnimation) {
5267
+ setIsRemoving(true);
5268
+ } else {
5269
+ notifyClose();
5270
+ }
5271
+ }, CLOSE_TIME_MSEC);
5272
+ return () => window.clearTimeout(timer);
5273
+ }, [isAutoClose, isAnimation, notifyClose]);
5274
+ (0, import_react73.useEffect)(() => {
5275
+ if (!isRemoving) {
5276
+ return;
5277
+ }
5278
+ const fallbackTimer = window.setTimeout(notifyClose, REMOVAL_FALLBACK_MSEC);
5279
+ return () => window.clearTimeout(fallbackTimer);
5280
+ }, [isRemoving, notifyClose]);
5281
+ const isCloseButtonShown = hasCloseButton || !isAutoClose;
5282
+ const wrapperClasses = (0, import_clsx56.clsx)(
5283
+ "pointer-events-auto flex items-center gap-3 rounded border border-solid border-uiBorder01 bg-uiBackground01 p-4 shadow-floatingShadow",
5284
+ {
5285
+ ["animate-toast-in"]: isAnimation && !isRemoving,
5286
+ ["animate-toast-out opacity-0"]: isAnimation && isRemoving
5287
+ }
5288
+ );
5289
+ const iconClasses = (0, import_clsx56.clsx)("flex shrink-0 items-center", {
5175
5290
  "fill-supportSuccess": state === "success",
5176
5291
  "fill-supportError": state === "error",
5177
5292
  "fill-supportWarning": state === "warning",
5178
5293
  "fill-supportInfo": state === "information"
5179
5294
  });
5180
- const textClasses = (0, import_clsx56.default)("typography-body13regular flex-1 pt-[3px]", {
5295
+ const titleClasses = (0, import_clsx56.clsx)("typography-body13regular break-words", {
5181
5296
  "text-supportError": state === "error",
5182
- "text-text01": state === "success" || state === "warning" || state === "information"
5297
+ "text-text01": state !== "error"
5183
5298
  });
5184
5299
  const iconName = {
5185
5300
  success: "success-filled",
@@ -5187,18 +5302,15 @@ function Toast({
5187
5302
  warning: "warning",
5188
5303
  information: "information-filled"
5189
5304
  };
5190
- (0, import_react73.useEffect)(() => {
5191
- const timer = window.setTimeout(() => {
5192
- if (isAutoClose) {
5193
- setIsRemoving(true);
5194
- }
5195
- }, CLOSE_TIME_MSEC);
5196
- return () => window.clearTimeout(timer);
5197
- }, [isAutoClose]);
5198
5305
  return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: wrapperClasses, style: { width }, onAnimationEnd: handleAnimationEnd, children: [
5199
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: iconClasses, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Icon, { name: iconName[state] }) }),
5200
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: textClasses, children }),
5201
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(IconButton, { icon: "close", size: "medium", variant: "text", onClick: handleClose, isNoPadding: true })
5306
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex min-w-0 flex-1 items-start gap-1", children: [
5307
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: iconClasses, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Icon, { name: iconName[state] }) }),
5308
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2 pt-[3px]", children: [
5309
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: titleClasses, children }),
5310
+ description != null && description !== "" && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "typography-label12regular break-words text-text01", children: description })
5311
+ ] })
5312
+ ] }),
5313
+ isCloseButtonShown && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "flex shrink-0 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(IconButton, { icon: "close", size: "medium", variant: "text", isNoPadding: true, "aria-label": "\u9589\u3058\u308B", onClick: handleClose }) })
5202
5314
  ] });
5203
5315
  }
5204
5316
 
@@ -5207,12 +5319,28 @@ var import_react74 = require("react");
5207
5319
  var import_react_dom3 = require("react-dom");
5208
5320
  var import_jsx_runtime80 = require("react/jsx-runtime");
5209
5321
  var ToastContext = (0, import_react74.createContext)({});
5210
- var ToastProvider = ({ children }) => {
5322
+ var ToastProvider = ({ children, hasCloseButton = false }) => {
5211
5323
  const [isClientRender, setIsClientRender] = (0, import_react74.useState)(false);
5212
5324
  const [toasts, setToasts] = (0, import_react74.useState)([]);
5213
- const addToast = (0, import_react74.useCallback)(({ message, state }) => {
5214
- setToasts((prev) => [...prev, { id: Math.trunc(Math.random() * 1e5), message, state }]);
5215
- }, []);
5325
+ const nextIdRef = (0, import_react74.useRef)(0);
5326
+ const addToast = (0, import_react74.useCallback)(
5327
+ (args) => {
5328
+ nextIdRef.current += 1;
5329
+ const id = nextIdRef.current;
5330
+ setToasts((prev) => [
5331
+ ...prev,
5332
+ {
5333
+ id,
5334
+ message: args.message,
5335
+ state: args.state,
5336
+ description: args.description,
5337
+ hasCloseButton: args.hasCloseButton ?? hasCloseButton,
5338
+ isAutoClose: args.isAutoClose ?? true
5339
+ }
5340
+ ]);
5341
+ },
5342
+ [hasCloseButton]
5343
+ );
5216
5344
  const removeToast = (0, import_react74.useCallback)((id) => {
5217
5345
  setToasts((prev) => prev.filter((snackbar) => snackbar.id !== id));
5218
5346
  }, []);
@@ -5222,7 +5350,27 @@ var ToastProvider = ({ children }) => {
5222
5350
  return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(ToastContext.Provider, { value: { addToast, removeToast }, children: [
5223
5351
  children,
5224
5352
  isClientRender && (0, import_react_dom3.createPortal)(
5225
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "pointer-events-none fixed bottom-0 left-0 z-toast mb-4 ml-4 flex w-full flex-col-reverse gap-[16px]", children: toasts.map(({ id, message, state }) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Toast, { state, isAutoClose: true, isAnimation: true, onClickClose: () => removeToast(id), width: 475, children: message }, id)) }),
5353
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
5354
+ "div",
5355
+ {
5356
+ role: "region",
5357
+ "aria-label": "\u901A\u77E5",
5358
+ className: "pointer-events-none fixed bottom-0 left-0 z-toast mb-4 ml-4 flex w-full flex-col-reverse gap-4",
5359
+ children: toasts.map((toast) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { role: toast.state === "error" ? "alert" : "status", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
5360
+ Toast,
5361
+ {
5362
+ state: toast.state,
5363
+ description: toast.description,
5364
+ hasCloseButton: toast.hasCloseButton,
5365
+ isAutoClose: toast.isAutoClose,
5366
+ isAnimation: true,
5367
+ width: 475,
5368
+ onClickClose: () => removeToast(toast.id),
5369
+ children: toast.message
5370
+ }
5371
+ ) }, toast.id))
5372
+ }
5373
+ ),
5226
5374
  document.body
5227
5375
  )
5228
5376
  ] });
package/dist/index.mjs CHANGED
@@ -1502,7 +1502,7 @@ import {
1502
1502
  import { DayPicker } from "react-day-picker";
1503
1503
 
1504
1504
  // src/popover/popover.tsx
1505
- import { autoUpdate as autoUpdate2, offset as offset2, useFloating as useFloating2, useId as useFloatingId } from "@floating-ui/react";
1505
+ import { autoUpdate as autoUpdate2, flip as flip2, offset as offset2, shift, useFloating as useFloating2, useId as useFloatingId } from "@floating-ui/react";
1506
1506
  import { useEffect as useEffect8, useMemo as useMemo4, useRef as useRef7 } from "react";
1507
1507
 
1508
1508
  // src/popover/popover-content.tsx
@@ -1672,6 +1672,7 @@ var PopoverTrigger = forwardRef7(function PopoverTrigger2({ children }, ref) {
1672
1672
 
1673
1673
  // src/popover/popover.tsx
1674
1674
  import { jsx as jsx21 } from "react/jsx-runtime";
1675
+ var FLOATING_VIEWPORT_PADDING2 = 8;
1675
1676
  function Popover({
1676
1677
  isOpen,
1677
1678
  children,
@@ -1681,6 +1682,14 @@ function Popover({
1681
1682
  anchorRef
1682
1683
  }) {
1683
1684
  const triggerRef = useRef7(null);
1685
+ const middleware = useMemo4(
1686
+ () => [
1687
+ offset2(offsetValue),
1688
+ flip2({ padding: FLOATING_VIEWPORT_PADDING2, flipAlignment: false }),
1689
+ shift({ padding: FLOATING_VIEWPORT_PADDING2 })
1690
+ ],
1691
+ [offsetValue]
1692
+ );
1684
1693
  const floating = useFloating2({
1685
1694
  open: isOpen,
1686
1695
  onOpenChange: (open) => {
@@ -1689,7 +1698,7 @@ function Popover({
1689
1698
  }
1690
1699
  },
1691
1700
  placement,
1692
- middleware: [offset2(offsetValue)],
1701
+ middleware,
1693
1702
  whileElementsMounted: autoUpdate2,
1694
1703
  strategy: "fixed"
1695
1704
  });
@@ -1737,27 +1746,83 @@ import { DayButton } from "react-day-picker";
1737
1746
  import { clsx as clsx15 } from "clsx";
1738
1747
  import { getDefaultClassNames } from "react-day-picker";
1739
1748
  var defaultDayPickerClassNames = getDefaultClassNames();
1740
- var DAY_PICKER_FONT_SIZE = "12px";
1741
- var dayPickerStyle = {
1742
- "--rdp-nav-height": "30px",
1743
- "--rdp-day-width": "30px",
1744
- "--rdp-day-height": "30px",
1745
- "--rdp-day_button-width": "28px",
1746
- "--rdp-day_button-height": "28px",
1747
- "--rdp-day_button-border": "1px solid transparent",
1748
- "--rdp-weekday-padding": "0px",
1749
- fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1750
- fontSize: DAY_PICKER_FONT_SIZE,
1751
- fontWeight: 700
1749
+ var BASE_TOKENS = {
1750
+ triggerIcon: "small",
1751
+ dayPickerStyle: {
1752
+ "--rdp-nav-height": "30px",
1753
+ "--rdp-day-width": "30px",
1754
+ "--rdp-day-height": "30px",
1755
+ "--rdp-day_button-width": "28px",
1756
+ "--rdp-day_button-height": "28px",
1757
+ "--rdp-day_button-border": "1px solid transparent",
1758
+ "--rdp-weekday-padding": "0px",
1759
+ fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1760
+ fontSize: "12px",
1761
+ fontWeight: 700
1762
+ },
1763
+ dayPickerClassNames: {
1764
+ month: clsx15(defaultDayPickerClassNames.month, "flex flex-col px-[7px] py-2")
1765
+ },
1766
+ dayButtonClass: "relative grid size-full place-items-center rounded-full !border !border-solid",
1767
+ dayButtonFontSize: "12px",
1768
+ monthCaptionClass: "flex items-center justify-between px-1 pb-0.5",
1769
+ monthCaptionTypography: "typography-label12bold",
1770
+ navIconButton: "small",
1771
+ weekdayClass: "m-0 size-7 p-0 text-center align-middle",
1772
+ footerIconButton: "medium",
1773
+ footerClearButton: "small",
1774
+ errorTypography: "typography-label11regular"
1775
+ };
1776
+ var LARGE_TOKENS = {
1777
+ ...BASE_TOKENS,
1778
+ triggerIcon: "medium",
1779
+ errorTypography: "typography-label12regular"
1752
1780
  };
1753
- var dayPickerClassNames = {
1754
- month: clsx15(defaultDayPickerClassNames.month, "flex flex-col px-[7px] py-2")
1781
+ var X_LARGE_TOKENS = {
1782
+ triggerIcon: "medium",
1783
+ dayPickerStyle: {
1784
+ "--rdp-nav-height": "40px",
1785
+ "--rdp-day-width": "48px",
1786
+ "--rdp-day-height": "48px",
1787
+ "--rdp-day_button-width": "40px",
1788
+ "--rdp-day_button-height": "40px",
1789
+ "--rdp-day_button-border": "1px solid transparent",
1790
+ "--rdp-weekday-padding": "0px",
1791
+ fontFamily: "Arial, 'Noto Sans JP', sans-serif",
1792
+ fontSize: "16px",
1793
+ fontWeight: 700
1794
+ },
1795
+ dayPickerClassNames: {
1796
+ month: clsx15(defaultDayPickerClassNames.month, "flex flex-col px-[3px] pb-1 pt-2")
1797
+ },
1798
+ dayButtonClass: "relative grid size-10 place-items-center rounded-full !border !border-solid",
1799
+ dayButtonFontSize: "16px",
1800
+ // caption は height 固定(--rdp-nav-height: 40px)のため pb-2 は食い込みとして働き、
1801
+ // ナビボタンが上へ 4px はみ出して月ヘッダーと曜日行の視覚間隔が 8px になる(上部ブロックコメント参照)
1802
+ monthCaptionClass: "flex items-center justify-between px-1 pb-2",
1803
+ monthCaptionTypography: "typography-label16bold",
1804
+ // IconButton に x-large は無いが、large が 40px で Figma と一致する(内部アイコンも 24px になる)
1805
+ navIconButton: "large",
1806
+ weekdayClass: "m-0 size-12 p-0 text-center align-middle",
1807
+ footerIconButton: "large",
1808
+ footerClearButton: "large",
1809
+ errorTypography: "typography-label12regular"
1810
+ };
1811
+ var DATE_PICKER_SIZE_TOKENS = {
1812
+ small: BASE_TOKENS,
1813
+ medium: BASE_TOKENS,
1814
+ large: LARGE_TOKENS,
1815
+ "x-large": X_LARGE_TOKENS
1816
+ };
1817
+ var useDatePickerSizeTokens = (componentName = "DatePicker \u306E\u30AB\u30EC\u30F3\u30C0\u30FC") => {
1818
+ const context = useDatePickerCompoundContext(componentName);
1819
+ return { ...context, tokens: DATE_PICKER_SIZE_TOKENS[context.size] };
1755
1820
  };
1756
- var dayButtonBaseClass = "relative grid size-full place-items-center rounded-full !border !border-solid";
1757
1821
 
1758
1822
  // src/date-picker/date-picker-day-button.tsx
1759
1823
  import { jsx as jsx22 } from "react/jsx-runtime";
1760
1824
  var CustomDayButton = ({ day, modifiers, className, style, ...buttonProps }) => {
1825
+ const { tokens } = useDatePickerSizeTokens();
1761
1826
  const isSelected = Boolean(modifiers.selected);
1762
1827
  const isOutside = Boolean(modifiers.outside);
1763
1828
  const isMinMaxDisabled = Boolean(modifiers.minMaxDisabled);
@@ -1770,10 +1835,10 @@ var CustomDayButton = ({ day, modifiers, className, style, ...buttonProps }) =>
1770
1835
  ...buttonProps,
1771
1836
  day,
1772
1837
  modifiers,
1773
- style: { ...style, fontSize: DAY_PICKER_FONT_SIZE },
1838
+ style: { ...style, fontSize: tokens.dayButtonFontSize },
1774
1839
  className: clsx16(
1775
1840
  className,
1776
- dayButtonBaseClass,
1841
+ tokens.dayButtonClass,
1777
1842
  // 共通: フォーカスリング(有効な日のみ)
1778
1843
  // react-day-picker の rdp-day_button クラスが outline: none を設定しているため、!important で上書き
1779
1844
  !isDisabledDay && focusVisible5.normalImportant,
@@ -1799,8 +1864,8 @@ import { forwardRef as forwardRef8 } from "react";
1799
1864
  import { jsx as jsx23 } from "react/jsx-runtime";
1800
1865
  var DatePickerErrorMessage = forwardRef8(
1801
1866
  ({ "aria-live": ariaLive = "assertive", ...props }, ref) => {
1802
- const { size, isError } = useDatePickerCompoundContext("DatePicker.ErrorMessage");
1803
- const typographyClass = size === "large" ? "typography-label12regular" : "typography-label11regular";
1867
+ const { isError, tokens } = useDatePickerSizeTokens("DatePicker.ErrorMessage");
1868
+ const typographyClass = tokens.errorTypography;
1804
1869
  if (isError !== true) {
1805
1870
  return null;
1806
1871
  }
@@ -1881,11 +1946,12 @@ import { jsx as jsx24, jsxs as jsxs7 } from "react/jsx-runtime";
1881
1946
  var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...props }) => {
1882
1947
  void displayIndex;
1883
1948
  const { goToMonth, nextMonth, previousMonth } = useDayPicker();
1949
+ const { tokens } = useDatePickerSizeTokens();
1884
1950
  const captionMonth = calendarMonth.date;
1885
1951
  return /* @__PURE__ */ jsxs7(
1886
1952
  "div",
1887
1953
  {
1888
- className: clsx18("flex items-center justify-between px-1 pb-0.5", className),
1954
+ className: clsx18(tokens.monthCaptionClass, className),
1889
1955
  style: { ...style, fontSize: "inherit", fontWeight: "inherit" },
1890
1956
  ...props,
1891
1957
  children: [
@@ -1893,19 +1959,19 @@ var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...pr
1893
1959
  IconButton,
1894
1960
  {
1895
1961
  icon: "angle-left",
1896
- size: "small",
1962
+ size: tokens.navIconButton,
1897
1963
  variant: "text",
1898
1964
  isDisabled: !previousMonth,
1899
1965
  "aria-label": "\u524D\u306E\u6708",
1900
1966
  onClick: () => previousMonth && goToMonth(previousMonth)
1901
1967
  }
1902
1968
  ),
1903
- /* @__PURE__ */ jsx24("span", { className: "typography-label12bold text-text02", children: formatMonthLabel(captionMonth) }),
1969
+ /* @__PURE__ */ jsx24("span", { className: clsx18(tokens.monthCaptionTypography, "text-text02"), children: formatMonthLabel(captionMonth) }),
1904
1970
  /* @__PURE__ */ jsx24(
1905
1971
  IconButton,
1906
1972
  {
1907
1973
  icon: "angle-right",
1908
- size: "small",
1974
+ size: tokens.navIconButton,
1909
1975
  variant: "text",
1910
1976
  isDisabled: !nextMonth,
1911
1977
  "aria-label": "\u6B21\u306E\u6708",
@@ -1921,11 +1987,12 @@ var CustomMonthCaption = ({ calendarMonth, className, displayIndex, style, ...pr
1921
1987
  import { clsx as clsx19 } from "clsx";
1922
1988
  import { jsx as jsx25 } from "react/jsx-runtime";
1923
1989
  var CustomWeekday = ({ className, children, style, ...props }) => {
1990
+ const { tokens } = useDatePickerSizeTokens();
1924
1991
  return /* @__PURE__ */ jsx25(
1925
1992
  "th",
1926
1993
  {
1927
1994
  ...props,
1928
- className: clsx19(className, "m-0 size-7 p-0 text-center align-middle text-text02"),
1995
+ className: clsx19(className, tokens.weekdayClass, "text-text02"),
1929
1996
  style: { ...style, fontSize: "inherit", fontWeight: "bold" },
1930
1997
  children
1931
1998
  }
@@ -2060,7 +2127,7 @@ var DatePicker = ({
2060
2127
  formatWeekdayName: (date) => weekdayFormatter.format(date)
2061
2128
  };
2062
2129
  }, []);
2063
- const iconSize = size === "large" ? "medium" : "small";
2130
+ const tokens = DATE_PICKER_SIZE_TOKENS[size];
2064
2131
  const displayText = value ? formatDisplayDate(value, timeZone) : placeholder;
2065
2132
  const displayTextClasses = "min-w-0 truncate";
2066
2133
  const errorIds = [];
@@ -2108,7 +2175,7 @@ var DatePicker = ({
2108
2175
  size,
2109
2176
  variant: isError ? "outlineDanger" : "outline",
2110
2177
  isDisabled,
2111
- before: /* @__PURE__ */ jsx26(Icon, { name: "calendar", size: iconSize }),
2178
+ before: /* @__PURE__ */ jsx26(Icon, { name: "calendar", size: tokens.triggerIcon }),
2112
2179
  justifyContent: "start",
2113
2180
  onClick: handleTriggerClick,
2114
2181
  children: /* @__PURE__ */ jsx26("span", { className: displayTextClasses, children: displayText })
@@ -2122,7 +2189,7 @@ var DatePicker = ({
2122
2189
  showOutsideDays: true,
2123
2190
  hideNavigation: true,
2124
2191
  weekStartsOn: 0,
2125
- style: dayPickerStyle,
2192
+ style: tokens.dayPickerStyle,
2126
2193
  month: displayMonth,
2127
2194
  onMonthChange: setDisplayMonth,
2128
2195
  selected: selectedDate,
@@ -2130,7 +2197,7 @@ var DatePicker = ({
2130
2197
  today: todayForCalendar,
2131
2198
  disabled: disabledDays,
2132
2199
  modifiers: { minMaxDisabled: isMinMaxDisabled },
2133
- classNames: dayPickerClassNames,
2200
+ classNames: tokens.dayPickerClassNames,
2134
2201
  formatters,
2135
2202
  fixedWeeks: true,
2136
2203
  components: { MonthCaption: CustomMonthCaption, DayButton: CustomDayButton, Weekday: CustomWeekday }
@@ -2141,14 +2208,14 @@ var DatePicker = ({
2141
2208
  IconButton,
2142
2209
  {
2143
2210
  icon: "calendar-today",
2144
- size: "medium",
2211
+ size: tokens.footerIconButton,
2145
2212
  variant: "text",
2146
2213
  "aria-label": "\u4ECA\u65E5\u306B\u623B\u308B",
2147
2214
  iconAccentColor: "supportInfo",
2148
2215
  onClick: handleClickToday
2149
2216
  }
2150
2217
  ),
2151
- /* @__PURE__ */ jsx26(Button, { type: "button", size: "small", variant: "text", onClick: handleClear, children: "\u30AF\u30EA\u30A2" })
2218
+ /* @__PURE__ */ jsx26(Button, { type: "button", size: tokens.footerClearButton, variant: "text", onClick: handleClear, children: "\u30AF\u30EA\u30A2" })
2152
2219
  ] })
2153
2220
  ] }) })
2154
2221
  ] });
@@ -5071,40 +5138,88 @@ TimePicker.ErrorMessage = TimePickerErrorMessage;
5071
5138
  TimePicker.displayName = "TimePicker";
5072
5139
 
5073
5140
  // src/toast/toast.tsx
5074
- import clsx56 from "clsx";
5075
- import { useCallback as useCallback15, useEffect as useEffect12, useState as useState15 } from "react";
5141
+ import { clsx as clsx56 } from "clsx";
5142
+ import { useCallback as useCallback15, useEffect as useEffect12, useRef as useRef15, useState as useState15 } from "react";
5076
5143
  import { jsx as jsx77, jsxs as jsxs35 } from "react/jsx-runtime";
5077
5144
  var CLOSE_TIME_MSEC = 5e3;
5145
+ var REMOVAL_FALLBACK_MSEC = 1e3;
5078
5146
  function Toast({
5079
5147
  state = "information",
5080
5148
  width = "auto",
5149
+ // 既定 false は v1.22.0 までの互換維持のため据え置き(自動クローズしない既定では、安全弁により閉じるボタンが表示される)。
5150
+ // 「自動クローズ・閉じるボタンなし」の新しい既定は ToastProvider が isAutoClose を明示的に渡すことで実現している。
5081
5151
  isAutoClose = false,
5082
5152
  isAnimation = false,
5153
+ hasCloseButton = false,
5154
+ description,
5083
5155
  children,
5084
5156
  onClickClose
5085
5157
  }) {
5086
5158
  const [isRemoving, setIsRemoving] = useState15(false);
5159
+ const onClickCloseRef = useRef15(onClickClose);
5160
+ useEffect12(() => {
5161
+ onClickCloseRef.current = onClickClose;
5162
+ }, [onClickClose]);
5163
+ const hasNotifiedCloseRef = useRef15(false);
5164
+ const notifyClose = useCallback15(() => {
5165
+ if (hasNotifiedCloseRef.current) {
5166
+ return;
5167
+ }
5168
+ hasNotifiedCloseRef.current = true;
5169
+ onClickCloseRef.current();
5170
+ }, []);
5087
5171
  const handleClose = useCallback15(() => {
5088
5172
  if (isAnimation) {
5089
5173
  setIsRemoving(true);
5090
5174
  } else {
5091
- onClickClose();
5175
+ notifyClose();
5092
5176
  }
5093
- }, [isAnimation, onClickClose]);
5094
- const handleAnimationEnd = (e) => window.getComputedStyle(e.currentTarget).opacity === "0" && onClickClose();
5095
- const wrapperClasses = clsx56("pointer-events-auto flex items-start gap-1 bg-white p-4 shadow-floatingShadow", {
5096
- ["animate-toast-in"]: isAnimation && !isRemoving,
5097
- ["animate-toast-out opacity-0"]: isAnimation && isRemoving
5098
- });
5099
- const iconClasses = clsx56("flex items-center", {
5177
+ }, [isAnimation, notifyClose]);
5178
+ const handleAnimationEnd = (e) => {
5179
+ if (e.target !== e.currentTarget) {
5180
+ return;
5181
+ }
5182
+ if (window.getComputedStyle(e.currentTarget).opacity === "0") {
5183
+ notifyClose();
5184
+ }
5185
+ };
5186
+ useEffect12(() => {
5187
+ if (!isAutoClose) {
5188
+ return;
5189
+ }
5190
+ const timer = window.setTimeout(() => {
5191
+ if (isAnimation) {
5192
+ setIsRemoving(true);
5193
+ } else {
5194
+ notifyClose();
5195
+ }
5196
+ }, CLOSE_TIME_MSEC);
5197
+ return () => window.clearTimeout(timer);
5198
+ }, [isAutoClose, isAnimation, notifyClose]);
5199
+ useEffect12(() => {
5200
+ if (!isRemoving) {
5201
+ return;
5202
+ }
5203
+ const fallbackTimer = window.setTimeout(notifyClose, REMOVAL_FALLBACK_MSEC);
5204
+ return () => window.clearTimeout(fallbackTimer);
5205
+ }, [isRemoving, notifyClose]);
5206
+ const isCloseButtonShown = hasCloseButton || !isAutoClose;
5207
+ const wrapperClasses = clsx56(
5208
+ "pointer-events-auto flex items-center gap-3 rounded border border-solid border-uiBorder01 bg-uiBackground01 p-4 shadow-floatingShadow",
5209
+ {
5210
+ ["animate-toast-in"]: isAnimation && !isRemoving,
5211
+ ["animate-toast-out opacity-0"]: isAnimation && isRemoving
5212
+ }
5213
+ );
5214
+ const iconClasses = clsx56("flex shrink-0 items-center", {
5100
5215
  "fill-supportSuccess": state === "success",
5101
5216
  "fill-supportError": state === "error",
5102
5217
  "fill-supportWarning": state === "warning",
5103
5218
  "fill-supportInfo": state === "information"
5104
5219
  });
5105
- const textClasses = clsx56("typography-body13regular flex-1 pt-[3px]", {
5220
+ const titleClasses = clsx56("typography-body13regular break-words", {
5106
5221
  "text-supportError": state === "error",
5107
- "text-text01": state === "success" || state === "warning" || state === "information"
5222
+ "text-text01": state !== "error"
5108
5223
  });
5109
5224
  const iconName = {
5110
5225
  success: "success-filled",
@@ -5112,32 +5227,45 @@ function Toast({
5112
5227
  warning: "warning",
5113
5228
  information: "information-filled"
5114
5229
  };
5115
- useEffect12(() => {
5116
- const timer = window.setTimeout(() => {
5117
- if (isAutoClose) {
5118
- setIsRemoving(true);
5119
- }
5120
- }, CLOSE_TIME_MSEC);
5121
- return () => window.clearTimeout(timer);
5122
- }, [isAutoClose]);
5123
5230
  return /* @__PURE__ */ jsxs35("div", { className: wrapperClasses, style: { width }, onAnimationEnd: handleAnimationEnd, children: [
5124
- /* @__PURE__ */ jsx77("div", { className: iconClasses, children: /* @__PURE__ */ jsx77(Icon, { name: iconName[state] }) }),
5125
- /* @__PURE__ */ jsx77("p", { className: textClasses, children }),
5126
- /* @__PURE__ */ jsx77(IconButton, { icon: "close", size: "medium", variant: "text", onClick: handleClose, isNoPadding: true })
5231
+ /* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 items-start gap-1", children: [
5232
+ /* @__PURE__ */ jsx77("div", { className: iconClasses, children: /* @__PURE__ */ jsx77(Icon, { name: iconName[state] }) }),
5233
+ /* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 flex-col gap-2 pt-[3px]", children: [
5234
+ /* @__PURE__ */ jsx77("p", { className: titleClasses, children }),
5235
+ description != null && description !== "" && /* @__PURE__ */ jsx77("p", { className: "typography-label12regular break-words text-text01", children: description })
5236
+ ] })
5237
+ ] }),
5238
+ isCloseButtonShown && /* @__PURE__ */ jsx77("div", { className: "flex shrink-0 items-center", children: /* @__PURE__ */ jsx77(IconButton, { icon: "close", size: "medium", variant: "text", isNoPadding: true, "aria-label": "\u9589\u3058\u308B", onClick: handleClose }) })
5127
5239
  ] });
5128
5240
  }
5129
5241
 
5130
5242
  // src/toast/toast-provider.tsx
5131
- import { createContext as createContext18, useCallback as useCallback16, useContext as useContext21, useEffect as useEffect13, useState as useState16 } from "react";
5243
+ import { createContext as createContext18, useCallback as useCallback16, useContext as useContext21, useEffect as useEffect13, useRef as useRef16, useState as useState16 } from "react";
5132
5244
  import { createPortal as createPortal3 } from "react-dom";
5133
5245
  import { jsx as jsx78, jsxs as jsxs36 } from "react/jsx-runtime";
5134
5246
  var ToastContext = createContext18({});
5135
- var ToastProvider = ({ children }) => {
5247
+ var ToastProvider = ({ children, hasCloseButton = false }) => {
5136
5248
  const [isClientRender, setIsClientRender] = useState16(false);
5137
5249
  const [toasts, setToasts] = useState16([]);
5138
- const addToast = useCallback16(({ message, state }) => {
5139
- setToasts((prev) => [...prev, { id: Math.trunc(Math.random() * 1e5), message, state }]);
5140
- }, []);
5250
+ const nextIdRef = useRef16(0);
5251
+ const addToast = useCallback16(
5252
+ (args) => {
5253
+ nextIdRef.current += 1;
5254
+ const id = nextIdRef.current;
5255
+ setToasts((prev) => [
5256
+ ...prev,
5257
+ {
5258
+ id,
5259
+ message: args.message,
5260
+ state: args.state,
5261
+ description: args.description,
5262
+ hasCloseButton: args.hasCloseButton ?? hasCloseButton,
5263
+ isAutoClose: args.isAutoClose ?? true
5264
+ }
5265
+ ]);
5266
+ },
5267
+ [hasCloseButton]
5268
+ );
5141
5269
  const removeToast = useCallback16((id) => {
5142
5270
  setToasts((prev) => prev.filter((snackbar) => snackbar.id !== id));
5143
5271
  }, []);
@@ -5147,7 +5275,27 @@ var ToastProvider = ({ children }) => {
5147
5275
  return /* @__PURE__ */ jsxs36(ToastContext.Provider, { value: { addToast, removeToast }, children: [
5148
5276
  children,
5149
5277
  isClientRender && createPortal3(
5150
- /* @__PURE__ */ jsx78("div", { className: "pointer-events-none fixed bottom-0 left-0 z-toast mb-4 ml-4 flex w-full flex-col-reverse gap-[16px]", children: toasts.map(({ id, message, state }) => /* @__PURE__ */ jsx78(Toast, { state, isAutoClose: true, isAnimation: true, onClickClose: () => removeToast(id), width: 475, children: message }, id)) }),
5278
+ /* @__PURE__ */ jsx78(
5279
+ "div",
5280
+ {
5281
+ role: "region",
5282
+ "aria-label": "\u901A\u77E5",
5283
+ className: "pointer-events-none fixed bottom-0 left-0 z-toast mb-4 ml-4 flex w-full flex-col-reverse gap-4",
5284
+ children: toasts.map((toast) => /* @__PURE__ */ jsx78("div", { role: toast.state === "error" ? "alert" : "status", children: /* @__PURE__ */ jsx78(
5285
+ Toast,
5286
+ {
5287
+ state: toast.state,
5288
+ description: toast.description,
5289
+ hasCloseButton: toast.hasCloseButton,
5290
+ isAutoClose: toast.isAutoClose,
5291
+ isAnimation: true,
5292
+ width: 475,
5293
+ onClickClose: () => removeToast(toast.id),
5294
+ children: toast.message
5295
+ }
5296
+ ) }, toast.id))
5297
+ }
5298
+ ),
5151
5299
  document.body
5152
5300
  )
5153
5301
  ] });
@@ -5213,7 +5361,7 @@ function Toggle({
5213
5361
  }
5214
5362
 
5215
5363
  // src/tooltip/tooltip.tsx
5216
- import { useCallback as useCallback18, useEffect as useEffect14, useRef as useRef15, useState as useState17 } from "react";
5364
+ import { useCallback as useCallback18, useEffect as useEffect14, useRef as useRef17, useState as useState17 } from "react";
5217
5365
  import { createPortal as createPortal4 } from "react-dom";
5218
5366
 
5219
5367
  // src/tooltip/tooltip-content.tsx
@@ -5384,7 +5532,7 @@ function Tooltip({
5384
5532
  translateX: "0",
5385
5533
  translateY: "0"
5386
5534
  });
5387
- const targetRef = useRef15(null);
5535
+ const targetRef = useRef17(null);
5388
5536
  const handleMouseOverWrapper = useCallback18(() => {
5389
5537
  if (isDisabledHover) {
5390
5538
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenkigen-inc/component-ui",
3
- "version": "1.22.0",
3
+ "version": "1.23.1",
4
4
  "repository": "https://github.com/zenkigen/zenkigen-component",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -37,10 +37,10 @@
37
37
  "react-dom": "^18.0.0 || ^19.0.0"
38
38
  },
39
39
  "dependencies": {
40
- "@floating-ui/react": "0.27.19",
41
- "@zenkigen-inc/component-config": "1.22.0",
42
- "@zenkigen-inc/component-icons": "1.22.0",
43
- "@zenkigen-inc/component-theme": "1.22.0",
40
+ "@floating-ui/react": "0.27.20",
41
+ "@zenkigen-inc/component-config": "1.23.1",
42
+ "@zenkigen-inc/component-icons": "1.23.1",
43
+ "@zenkigen-inc/component-theme": "1.23.1",
44
44
  "clsx": "2.1.1",
45
45
  "react-day-picker": "9.14.0"
46
46
  }