@insession/design-system 1.3.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/CHANGELOG.md +84 -0
- package/README.md +108 -0
- package/dist/index.d.ts +501 -0
- package/dist/index.js +1962 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
- package/theme.css +325 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../avatar.tsx","../icons/icon.tsx","../badge.tsx","../bottom-sheet.tsx","../breakpoints.ts","../spinner.tsx","../button.tsx","../checkbox.tsx","../chip.tsx","../composer.tsx","../modal.tsx","../confirm-modal.tsx","../empty-note.tsx","../icon-button.tsx","../icons/google-icon.tsx","../icons/person-icon.tsx","../input.tsx","../link.tsx","../logo-mark.tsx","../lozenge.tsx","../menu.tsx","../popover.tsx","../use-dismiss.ts","../profile-modal.tsx","../radio.tsx","../ring-timer.tsx","../search-field.tsx","../split-modal.tsx","../status.tsx","../step-flow.tsx","../stepper.tsx","../tabs.tsx","../toast.tsx","../toggle.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\n\n// アバター(純粋 leaf UI)。DS(claude design \"INSESSION Design System\" #663)の Avatar 仕様へ寄せる。\n// 画像があれば <img>、無ければ名前先頭1文字(label 指定時はその文字列)の fallback 円を出す。\n//\n// 後方互換: 既存消費側(presence バー・space-card・account 等)は className / fallbackClassName で\n// legacy の .avatar / .auth-avatar を注入して見た目・スタック重ね・アニメを得ているため、\n// status / ring を使わない呼び出しは従来どおり素の img/span を返す(見た目を変えない)。\n// DS 化: name→label / bgColor→color を別名として受け、status(右下の状態点)/ ring(surface 枠)を\n// 追加。status/ring を使う(=新 API)の呼び出しは token/props ベースの自己完結した DS 円を描く。\nexport type AvatarStatus = 'live' | 'offline';\n\nexport type AvatarProps = {\n // 表示ラベル(DS 名)。文字列ならそのまま円内に描く(呼び出し側が頭文字を渡す想定)。旧 `name` の別名。\n label?: ReactNode;\n // 表示名(旧名)。label が無ければ先頭1文字を fallback 円に使う。\n name?: string | null;\n // アバター画像 URL。あれば画像を優先。\n src?: string | null;\n // name が空のときのフォールバック文字ソース(例: email)。\n fallback?: string | null;\n // 円の背景色(DS 名。CSS 色)。旧 `bgColor` の別名。DS 経路で省略時は info(blue)。\n color?: string;\n // 円の背景色(旧名)。color が無ければこちらを使う。\n bgColor?: string;\n // 円の寸法(px)。省略時はクラス側の寸法(legacy)または 40(DS)。\n size?: number;\n // 右下の状態点。'live'=success / それ以外=text-dim。指定時は DS 円で描画する。\n status?: AvatarStatus;\n // surface 色の 2px 枠(スタック等での重なりの縁取り)。指定時は DS 円で描画する。\n ring?: boolean;\n // 文脈クラス('avatar' / 'auth-avatar' など)。img/fallback 両方に付く(legacy 経路)。\n className?: string;\n // fallback 円だけに足すクラス(例 'auth-avatar-fallback' で既定背景を供給)。\n fallbackClassName?: string;\n alt?: string;\n};\n\nfunction initialOf(name?: string | null, fallback?: string | null): string {\n return [...(name || fallback || '?')][0].toUpperCase();\n}\n\nexport default function Avatar({\n label,\n name,\n src,\n fallback,\n color,\n bgColor,\n size,\n status,\n ring,\n className = '',\n fallbackClassName = '',\n alt = '',\n}: AvatarProps) {\n const bg = color ?? bgColor;\n const content = label != null ? label : initialOf(name, fallback);\n const ds = status != null || ring === true;\n\n // DS 経路: token/props ベースの自己完結した円(新 API 専用。legacy CSS に依存しない)。\n if (ds) {\n const dim = size ?? 40;\n const circleStyle: CSSProperties = {\n width: dim,\n height: dim,\n fontSize: dim * 0.4,\n ...(!src && bg ? { background: bg } : undefined),\n };\n return (\n <span\n className={`relative inline-flex shrink-0 ${className}`.trim()}\n style={{ width: dim, height: dim }}\n >\n <span\n className={`inline-flex items-center justify-center overflow-hidden rounded-pill font-bold text-white ${\n src ? 'bg-transparent' : bg ? '' : 'bg-info'\n } ${ring ? 'border-2 border-solid border-surface' : ''}`.trim()}\n style={circleStyle}\n >\n {src ? (\n <img\n src={src}\n alt={alt || (typeof label === 'string' ? label : name || '')}\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full object-cover\"\n />\n ) : (\n content\n )}\n </span>\n {status != null && (\n <span\n aria-hidden=\"true\"\n className={`absolute right-0 bottom-0 rounded-pill border-2 border-solid border-surface ${\n status === 'live' ? 'bg-success' : 'bg-text-dim'\n }`}\n style={{ width: dim * 0.28, height: dim * 0.28 }}\n />\n )}\n </span>\n );\n }\n\n // legacy 経路: 見た目は className / fallbackClassName(.avatar 等)が供給する。従来と同一。\n const dim = size != null ? { width: size, height: size } : undefined;\n if (src) {\n return (\n <img className={className} src={src} alt={alt} referrerPolicy=\"no-referrer\" style={dim} />\n );\n }\n return (\n <span\n className={`${className} ${fallbackClassName}`.trim()}\n style={bg ? { ...dim, background: bg } : dim}\n >\n {content}\n </span>\n );\n}\n\n// DS の AvatarStack(+N overflow)。people を size*0.3 だけ重ね、max を超えた分は +N の中立トークンで示す。\n// presence 表示などの将来集約先(token/props ベース。legacy .avatar-stack CSS には依存しない)。\nexport type AvatarStackPerson = {\n label?: ReactNode;\n name?: string | null;\n src?: string | null;\n color?: string;\n bgColor?: string;\n};\n\nexport type AvatarStackProps = {\n people?: AvatarStackPerson[];\n max?: number;\n size?: number;\n className?: string;\n};\n\nexport function AvatarStack({ people = [], max = 4, size = 40, className = '' }: AvatarStackProps) {\n const shown = people.slice(0, max);\n const extra = people.length - shown.length;\n const overlap = -(size * 0.3);\n return (\n <span className={`inline-flex items-center ${className}`.trim()}>\n {shown.map((p, i) => (\n <span key={i} style={{ marginLeft: i ? overlap : 0 }} className=\"inline-flex rounded-pill\">\n <Avatar {...p} size={size} ring />\n </span>\n ))}\n {extra > 0 && (\n <span\n style={{ marginLeft: overlap, width: size, height: size, fontSize: size * 0.32 }}\n className=\"inline-flex items-center justify-center rounded-pill border-2 border-solid border-surface bg-surface-3 font-bold text-text-dim\"\n >\n +{extra}\n </span>\n )}\n </span>\n );\n}\n","// Google Material Icons 由来の path data を使った汎用アイコン(絵文字の置き換え先)。\n// 純粋 leaf UI(props 不要な GoogleIcon/PersonIcon と同じ流儀)。currentColor で親のテキスト色を継承する。\nconst PATHS = {\n menu: 'M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z',\n // サイドナビ用(#463。DS SideNav の home / graphic_eq / history)\n home: 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z',\n graphic_eq: 'M7 18h2V6H7v12zm4 4h2V2h-2v20zm-8-8h2v-4H3v4zm12 4h2V6h-2v12zm4-4h2v-4h-2v4z',\n history:\n 'M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z',\n settings:\n 'M19.14 12.94c.04-.3.06-.61.06-.94s-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z',\n check: 'M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z',\n check_circle:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',\n warning: 'M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z',\n edit: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z',\n link: 'M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z',\n volume_off:\n 'M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3 3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06a8.99 8.99 0 0 0 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4 9.91 6.09 12 8.18V4z',\n // 音量スライダーのアイコン(レコードプレーヤービュー。#406)\n volume_up:\n 'M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.26 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z',\n extension:\n 'M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7s2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z',\n // ステージスイッチャーのトリガー(#235。3x3グリッドの「アプリ一覧」アイコン)\n apps: 'M4 8h4V4H4v4zm6 12h4v-4h-4v4zM4 20h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z',\n timer:\n 'M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61 1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z',\n movie:\n 'M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z',\n group:\n 'M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z',\n sports_esports:\n 'M15 7.5H9c-2.76 0-5 2.24-5 5v3c0 1.66 1.34 3 3 3 .58 0 1.11-.24 1.5-.62L10.5 16h3l2 1.88c.39.38.92.62 1.5.62 1.66 0 3-1.34 3-3v-3c0-2.76-2.24-5-5-5zM10 13H8.5v1.5H7V13H5.5v-1.5H7V10h1.5v1.5H10V13zm5.5 1c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2-2.5c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z',\n auto_awesome:\n 'M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zM11.5 9.5 9 4l-2.5 5.5L1 12l5.5 2.5L9 20l2.5-5.5L17 12l-5.5-2.5zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z',\n // 入室拒否画面(#845。スペースの公開範囲で弾かれたときの空状態アイコン)\n lock: 'M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM9 6c0-1.66 1.34-3 3-3s3 1.34 3 3v2H9V6zm3 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z',\n play_arrow: 'M8 5v14l11-7z',\n // スペース内キュー(モバイル下部ナビ #572)。Material Symbols queue_music 由来。\n queue_music:\n 'M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z',\n // モバイル下部タブバーのマイページ(#580)。Material Symbols account_circle 由来。\n account_circle:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z',\n pause: 'M6 19h4V5H6v14zm8-14v14h4V5h-4z',\n fast_forward: 'M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z',\n videocam:\n 'M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z',\n videocam_off:\n 'M21 6.5l-4 4V7c0-.55-.45-1-1-1H9.82L21 17.18V6.5zM3.27 2 2 3.27 4.73 6H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73 3.27 2zM7.73 8l6 6H6V8h1.73z',\n mic: 'M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5-3c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z',\n mic_off:\n 'M19 11h-1.7c0 .74-.16 1.43-.43 2.05l1.23 1.23c.56-.98.9-2.09.9-3.28zm-4.02.17c0-.06.02-.11.02-.17V5c0-1.66-1.34-3-3-3S9 3.34 9 5v.18l5.98 5.99zM4.27 3 3 4.27l6.01 6.01V11c0 1.66 1.33 3 2.99 3 .22 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.27c.91-.13 1.77-.45 2.54-.9L19.73 21 21 19.73 4.27 3z',\n call_end:\n 'M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.7l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.51-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z',\n // 受話器アイコン(発信/参加ボタン用。#187フォローアップ)\n call: 'M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z',\n help: 'M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z',\n // 画面共有(#180)。モニター枠 + 上向き矢印(共有中)/× (共有停止)。\n screen_share:\n 'M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 16V6h16v10H4zm7-4h2V9h2.5L12 5.5 8.5 9H11v3z',\n stop_screen_share:\n 'M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 16V6h16v10H4zm3.4-8.6L12 11.6l4.6-4.2 1.4 1.4L13.4 13l4.6 4.2-1.4 1.4L12 14.4l-4.6 4.2-1.4-1.4L10.6 13 6 8.8z',\n // ログアウト(#219 ユーザーメニューのドロップダウン用)\n logout:\n 'M17 7l-1.41 1.41L18.17 11H8v2h10.17l-2.58 2.59L17 17l5-5zM4 5h8V3H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8v-2H4V5z',\n // 追加(+)。チャットメッセージへのリアクション追加トリガー等(#236)。\n add: 'M19 13H13V19H11V13H5V11H11V5H13V11H19V13Z',\n // URL/動画ID追加トグル(モバイルの+収納。#581)。Material Symbols add_link 由来。\n add_link:\n 'M8 11h8v2H8zm12.1 1c0-1.71-1.39-3.1-3.1-3.1h-4V7h4c2.76 0 5 2.24 5 5s-2.24 5-5 5h-4v-1.9h4c1.71 0 3.1-1.39 3.1-3.1zM3.9 12c0 1.71 1.39 3.1 3.1 3.1h4V17H7c-2.76 0-5-2.24-5-5s2.24-5 5-5h4v1.9H7c-1.71 0-3.1 1.39-3.1 3.1z',\n // リアクション追加(顔+マーク)。チャットメッセージへのリアクション追加トリガー専用アイコン(#262)。\n add_reaction:\n 'M7,9.5C7,8.67,7.67,8,8.5,8S10,8.67,10,9.5c0,0.83-0.67,1.5-1.5,1.5S7,10.33,7,9.5z M12,17.5c2.33,0,4.31-1.46,5.11-3.5 H6.89C7.69,16.04,9.67,17.5,12,17.5z M15.5,11c0.83,0,1.5-0.67,1.5-1.5C17,8.67,16.33,8,15.5,8S14,8.67,14,9.5 C14,10.33,14.67,11,15.5,11z M22,1h-2v2h-2v2h2v2h2V5h2V3h-2V1z M20,12c0,4.42-3.58,8-8,8s-8-3.58-8-8c0-4.42,3.58-8,8-8 c1.46,0,2.82,0.4,4,1.08V2.84C14.77,2.3,13.42,2,11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12 c0-1.05-0.17-2.05-0.47-3h-2.13C19.78,9.93,20,10.94,20,12z',\n // 別タブで開くリンク。参加者一覧の簡易プロフィール→詳細プロフィールへの導線(#254)。\n open_in_new:\n 'M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z',\n // 参加者一覧の行展開トグル(簡易プロフィール開閉。#254)。\n expand_more: 'M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z',\n expand_less: 'M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z',\n // モバイルBottom Navのチャット導線用の吹き出しアイコン(#284)\n chat: 'M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z',\n // チャットメッセージの「返信」アクション(#324)\n reply: 'M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z',\n // 汎用の閉じる(×)。返信プレビューバーのキャンセルボタン等(#324)\n close:\n 'M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',\n // フィードバック送信フォームの常設フローティングボタン(#329)。吹き出し+感嘆符。\n feedback:\n 'M20 2H4c-1.1 0-2 .89-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.11-.9-2-2-2zM13 14h-2v-2h2v2zm0-4h-2V6h2v4z',\n // レコード盤(プレーヤーのレコードビュー切替ボタン用。#376)\n album:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z',\n // 画像スタンプ添付ボタン(チャットの画像アップロード。#394)\n image:\n 'M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86-3 3.87L9 13.14 6 17h12l-3.86-5.14z',\n // チャット送信ボタン(#430。message-input-action-area 整理でテキストラベルからアイコン化)\n send: 'M2.01 21 23 12 2.01 3 2 10l15 2-15 2z',\n // 削除ボタン(ゴミ箱。スタンプ一覧からの削除等。#416フォローアップ)\n delete: 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z',\n // My Playlist(#452)への追加ボタン。塗り星(追加済み)/枠線星(未追加)。\n star: 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z',\n star_outline:\n 'M22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z',\n // 人物+追加。フォローボタン(未フォロー状態)用。(#397)\n person_add:\n 'M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z',\n // 通知ベル(ヘッダーのin-appお知らせ通知アイコン。#390)\n notifications:\n 'M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z',\n // CDプレーヤービュー切替(#421)。円盤+小さなスピンドル穴(レコードの album より穴を小さくして\n // 実物のCDに近い比率にする)。非零巻き数ルールで外側円(時計回り)と内側円(反時計回り)を\n // 重ねて穴を開ける(album アイコンと同じ手法)。\n cd: 'M2,12A10,10 0 1,1 22,12A10,10 0 1,1 2,12Z M10.4,12A1.6,1.6 0 1,0 13.6,12A1.6,1.6 0 1,0 10.4,12Z',\n // カセットプレーヤービュー切替(#421)。外枠(フレーム状に穴抜き)+2つのリール窓(各々小さな\n // スピンドル穴つき)+中央のテープ帯。cd と同じ非零巻き数の穴あけ手法を入れ子で使う。\n cassette:\n 'M3,5H21V19H3Z M5,7V17H19V7Z M6.3,12A2.2,2.2 0 1,1 10.7,12A2.2,2.2 0 1,1 6.3,12Z M7.6,12A0.9,0.9 0 1,0 9.4,12A0.9,0.9 0 1,0 7.6,12Z M13.3,12A2.2,2.2 0 1,1 17.7,12A2.2,2.2 0 1,1 13.3,12Z M14.6,12A0.9,0.9 0 1,0 16.4,12A0.9,0.9 0 1,0 14.6,12Z M10.5,11.4H13.5V12.6H10.5Z',\n // コミュニティ機能(#579)で使う追加アイコン。標準 Material Icons(0 0 24 24)。\n search:\n 'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z',\n more_horiz:\n 'M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z',\n info: 'M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z',\n music_note:\n 'M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z',\n schedule:\n 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z',\n chevron_right: 'M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z',\n tag: 'M20 10V8h-4V4h-2v4h-4V4H8v4H4v2h4v4H4v2h4v4h2v-4h4v4h2v-4h4v-2h-4v-4h4zm-6 4h-4v-4h4v4z',\n play_circle:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z',\n login:\n 'M11 7 9.6 8.4l2.6 2.6H2v2h10.2l-2.6 2.6L11 17l5-5-5-5zm9 12h-8v2h8c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-8v2h8v14z',\n add_photo_alternate:\n 'M18 20H4V6h9V4H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-9h-2v9zm-7.79-3.17-1.96-2.36L5.5 18h11l-3.54-4.71zM20 4V1h-2v3h-3c.01.01 0 2 0 2h3v2.99c.01.01 2 0 2 0V6h3V4h-3z',\n mood: 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z',\n diversity_3:\n 'M12 2C10.34 2 9 3.34 9 5s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-7 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm14 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM12 13c-2.67 0-4 1.34-4 3v2h8v-2c0-1.66-1.33-3-4-3z',\n waving_hand:\n 'M2.24 11.19 1 12.43l6.36 6.37a5.997 5.997 0 0 0 8.49 0l4.24-4.25c.78-.78.78-2.05 0-2.83a2.01 2.01 0 0 0-1.68-.57 2 2 0 0 0-1.9-2.35c-.24 0-.47.05-.68.13a2 2 0 0 0-2.83-1.11l-1.42-1.42a2.007 2.007 0 0 0-2.83 0l-.71.71 4.6 4.6-.71.71-6.36-6.37-1.24 1.24 1.42 1.42-2.29 2.66z',\n // 運営管理画面(Operator Console。#625)のアイコンレール/各画面で使う Material Icons(0 0 24 24)。\n dashboard: 'M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z',\n forum:\n 'M15 4v7H5.17L4 12.17V4h11m1-2H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm5 4h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1z',\n table_view:\n 'M10 10.02h5V21h-5zM17 21h3c1.1 0 2-.9 2-2v-9h-5v11zm3-18H5c-1.1 0-2 .9-2 2v3h19V5c0-1.1-.9-2-2-2zM3 19c0 1.1.9 2 2 2h3V10H3v9z',\n campaign:\n 'M18 11v2h4v-2h-4zm-2 6.61c.96.71 2.21 1.65 3.2 2.39.4-.53.8-1.07 1.2-1.6-.99-.74-2.24-1.68-3.2-2.4-.4.54-.8 1.08-1.2 1.61zM20.4 5.6c-.4-.53-.8-1.07-1.2-1.6-.99.74-2.24 1.68-3.2 2.4.4.53.8 1.07 1.2 1.6.96-.72 2.21-1.65 3.2-2.4zM4 9c-1.1 0-2 .9-2 2v2c0 1.1.9 2 2 2h1v4h2v-4h1l5 3V6L8 9H4zm11.5 3c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z',\n inbox:\n 'M19 3H4.99c-1.11 0-1.98.9-1.98 2L3 19c0 1.1.88 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V5H19v10z',\n arrow_forward: 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z',\n arrow_downward: 'M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z',\n filter_list: 'M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z',\n swap_vert: 'M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z',\n view_column: 'M14.67 6v12H9.33V6h5.34zm1 12H21V6h-5.33v12zm-7.34 0V6H3v12h5.33z',\n download: 'M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z',\n upload: 'M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z',\n drag_indicator:\n 'M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z',\n chevron_left: 'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z',\n flag: 'M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z',\n // UGCモデレーション(#1056): チャットメニューの「このユーザーをブロック」用アイコン。\n block:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z',\n meeting_room: 'M14 6v15H3v-2h2V3h9v1h5v15h2v2h-4V6h-3zm-4 5v2h2v-2h-2z',\n pending:\n 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-5 11c-.83 0-1.5-.67-1.5-1.5S6.17 10 7 10s1.5.67 1.5 1.5S7.83 13 7 13zm5 0c-.83 0-1.5-.67-1.5-1.5S11.17 10 12 10s1.5.67 1.5 1.5S12.83 13 12 13zm5 0c-.83 0-1.5-.67-1.5-1.5S16.17 10 17 10s1.5.67 1.5 1.5S17.83 13 17 13z',\n // 自動 Picture-in-Picture(#909)のトップバー開閉ボタン用。Material Icons picture_in_picture_alt 由来。\n picture_in_picture:\n 'M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14z',\n // レスポンシブ拡張PiP(#926)の「ルームに戻る」ボタン用。Material Icons open_in_full 由来。\n open_in_full: 'M3 3h7v2H5v5H3V3zm18 0v7h-2V5h-5V3h7zM3 21v-7h2v5h5v2H3zm18 0h-7v-2h5v-5h2v7z',\n // ホワイトボード「ギャラリーへ保存」ボタン用(#962)。フロッピーディスク(保存の定番アイコン)。\n // Material Icons save 由来。\n save: 'M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z',\n // チャットメッセージのピン留め(#1052)。Material Icons push_pin 由来。\n push_pin: 'M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z',\n};\n\n// 通常の Material Icons(0 0 24 24)とは異なる viewBox を持つアイコン(Material Symbols由来。\n// #416フォローアップ: 絵文字ピッカーと誤解されないよう「にっこり顔」(mood)から実際のシール型\n// アイコン(sticker)へ変更。Material Symbolsは 0 -960 960 960 のグリッドを使う)。\nconst CUSTOM_VIEWBOX: Record<string, string> = {\n sticker: '0 -960 960 960',\n};\n\n// スタンプピッカーのトリガー(シール型。#416)\nconst EXTRA_PATHS = {\n sticker:\n 'M460-360q69 0 120-45t60-113l-320 90q26 32 62 50t78 18ZM294-510l106-30q4-28-14-49t-46-21q-25 0-42.5 17.5T280-550q0 11 4 21t10 19Zm240-70 106-30q5-28-13.5-49T580-680q-25 0-42.5 17.5T520-620q0 11 4 21t10 19Zm106 460H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v440L640-120Zm-40-80v-80q0-33 23.5-56.5T680-360h80v-400H200v560h400Zm0 0Zm-400 0v-560 560Z',\n};\n\nconst ALL_PATHS = { ...PATHS, ...EXTRA_PATHS };\n\nexport type IconName = keyof typeof ALL_PATHS;\n\nexport type IconProps = {\n name: IconName;\n size?: number;\n className?: string;\n};\n\nexport default function Icon({ name, size = 20, className }: IconProps) {\n return (\n <svg\n viewBox={CUSTOM_VIEWBOX[name] ?? '0 0 24 24'}\n width={size}\n height={size}\n fill=\"currentColor\"\n aria-hidden=\"true\"\n className={className}\n >\n <path d={ALL_PATHS[name]} />\n </svg>\n );\n}\n","import type { ReactNode } from 'react';\nimport Icon, { type IconName } from './icons/icon.tsx';\n\n// Badge(非対話の status/meta ラベル。純粋 leaf UI)。claude design \"INSESSION Design System\" 準拠(#463 / #663)。\n// タップできる要素は Chip、継続的な状態の点+枠は StatusBadge、mono-caps の状態タグは Lozenge を使う\n// (役割分離。Lozenge は tone 名が別語彙のため統合はせず併存させる)。\n// TONES: live(green) / warn(amber) / danger(coral=accent。DS 定義) / info(blue) /\n// neutral(text-dim + surface-3) / pro(on-fill + fill)。colored tone は pill、neutral/pro は radius-sm の角丸矩形。\n// mono / 11px / 600。props: tone / dot(6px 色点) / icon(13) / shape('pill'|'rounded' で上書き)。\n// 後方互換: 旧 `variant`('new'|'live') を temporarily 受ける('new'=live tone の uppercase 小バッジ、\n// 'live'=live tone + dot)。パルス点や絶対配置は space-card 側の演出へ切り離した(legacy .live-badge 廃止)。\nexport type BadgeTone = 'live' | 'warn' | 'danger' | 'info' | 'neutral' | 'pro';\n\n// 件数チップ(旧 .count-chip / .tab-badge)。tab 側は出現アニメを持つので animated で切替。\nexport type CountChipProps = {\n children: ReactNode;\n animated?: boolean;\n // 配置場所ごとの位置調整(例: Bottom Navアイコンへの絶対配置重ね)用の追加クラス。\n className?: string;\n};\n\nexport function CountChip({ children, animated = false, className = '' }: CountChipProps) {\n return (\n <span\n className={`inline-flex items-center justify-center min-w-[20px] h-[20px] px-1.5 rounded-pill bg-success-surface-strong text-success text-xs font-extrabold tracking-normal${\n animated ? ' animate-[pop-in_0.3s_var(--ease-spring)]' : ''\n } ${className}`.trim()}\n >\n {children}\n </span>\n );\n}\n\nconst TONE: Record<BadgeTone, string> = {\n live: 'text-success bg-success-surface',\n warn: 'text-warning bg-warning-surface',\n danger: 'text-accent bg-tint-12',\n info: 'text-info bg-info-surface',\n neutral: 'text-text-dim bg-surface-3',\n pro: 'text-on-fill bg-fill',\n};\nconst DOT: Record<BadgeTone, string> = {\n live: 'bg-success',\n warn: 'bg-warning',\n danger: 'bg-accent',\n info: 'bg-info',\n neutral: 'bg-text-faint',\n pro: 'bg-on-fill',\n};\n// colored tone は pill、neutral/pro は角丸矩形(DS)。\nconst PILL_TONES: BadgeTone[] = ['live', 'warn', 'danger', 'info'];\n\nexport type BadgeProps = {\n children: ReactNode;\n tone?: BadgeTone;\n // 先頭に同色のドットを出す(LIVE 等の含意)。\n dot?: boolean;\n // 先頭のアイコン(IconName なら size13、ReactNode はそのまま)。\n icon?: IconName | ReactNode;\n // 形状の上書き(既定は tone から導出)。\n shape?: 'pill' | 'rounded';\n className?: string;\n // 後方互換: 旧 API('new'=新着 / 'live'=配信中)。tone 指定があればそちらを優先。\n variant?: 'new' | 'live';\n};\n\nexport function Badge({\n children,\n tone,\n dot = false,\n icon,\n shape,\n className = '',\n variant,\n}: BadgeProps) {\n // 旧 variant → tone/装飾の導出。'new' と 'live' はどちらも live(green) tone。\n const resolvedTone: BadgeTone = tone ?? 'neutral';\n const legacyTone: BadgeTone = variant ? 'live' : resolvedTone;\n const showDot = dot || variant === 'live';\n const legacyNew = variant === 'new';\n const isPill = shape ? shape === 'pill' : PILL_TONES.includes(legacyTone);\n const shapeClass = isPill ? 'rounded-pill' : 'rounded-chip';\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1.5 px-2.5 py-1 font-mono text-xs font-semibold ${TONE[legacyTone]} ${shapeClass}${\n legacyNew ? ' uppercase tracking-tag' : ''\n } ${className}`.trim()}\n >\n {showDot && (\n <span className={`h-1.5 w-1.5 rounded-pill ${DOT[legacyTone]}`} aria-hidden=\"true\" />\n )}\n {icon != null &&\n (typeof icon === 'string' ? <Icon name={icon as IconName} size={13} /> : icon)}\n {children}\n </span>\n );\n}\n","import { type ReactNode, useEffect, useRef, useState } from 'react';\n\n// 汎用Bottom Sheet(純粋 leaf UI。#284)。モバイルのChat/Participants導線のために新設。\n// Modal(modal.tsx)と同じ「backdrop + 本体 + Esc/背景クリックで閉じる」の方針を\n// 踏襲しつつ、下からせり出す・ドラッグで高さを変えられる点が異なるため別コンポーネントにする。\n// 開いた直後は中途高さ(MID_RATIO)、上ドラッグでフルハイト(FULL_RATIO)まで拡張できる。\n// 下ドラッグで一定以下まで縮めると close する。i18n はこのパッケージに持たないため、\n// 閉じるラベル等は props で注入する(Modal と同じ方針)。\nconst MID_RATIO = 0.68;\nconst FULL_RATIO = 0.94;\nconst CLOSE_RATIO = 0.32;\n\nexport type BottomSheetProps = {\n open: boolean;\n onClose: () => void;\n children: ReactNode;\n // ダイアログの aria-label。\n ariaLabel?: string;\n // × 閉じるボタンの aria ラベル(i18n は props 注入)。渡したときだけ×を表示する。\n closeLabel?: string;\n // Esc キーで閉じる。既定 true。\n closeOnEsc?: boolean;\n};\n\nexport default function BottomSheet({\n open,\n onClose,\n children,\n ariaLabel,\n closeLabel,\n closeOnEsc = true,\n}: BottomSheetProps) {\n const [mode, setMode] = useState<'mid' | 'full'>('mid');\n const sheetRef = useRef<HTMLDivElement | null>(null);\n\n // 開くたびに中途高さから始める(前回フルハイトのまま閉じても次回はリセットする)\n useEffect(() => {\n if (open) setMode('mid');\n }, [open]);\n\n useEffect(() => {\n if (!open || !closeOnEsc) return undefined;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [open, onClose, closeOnEsc]);\n\n // ドラッグハンドルのPointer Events実装(use-queue-dnd.tsと同じ方針: 可変データはdragRefに\n // 集約し、要素へ直接setPointerCaptureしてリスナーもその要素に張る)。ドラッグ中はCSS\n // transitionを切ってinline heightで直接追従させ、離した時だけ2つの高さのどちらか(または\n // close)にスナップする。\n function onHandlePointerDown(e: any) {\n const sheet = sheetRef.current;\n if (!sheet) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n const handle = e.currentTarget;\n handle.setPointerCapture(e.pointerId);\n const startHeight = sheet.getBoundingClientRect().height;\n const vh = window.innerHeight;\n const drag = { pointerId: e.pointerId, startY: e.clientY, startHeight, vh };\n sheet.style.transition = 'none';\n\n const onMove = (ev: PointerEvent) => {\n if (ev.pointerId !== drag.pointerId) return;\n const delta = drag.startY - ev.clientY;\n const next = Math.min(\n drag.vh * FULL_RATIO,\n Math.max(drag.vh * 0.18, drag.startHeight + delta),\n );\n sheet.style.height = `${next}px`;\n };\n const onUp = (ev: PointerEvent) => {\n if (ev.pointerId !== drag.pointerId) return;\n handle.removeEventListener('pointermove', onMove);\n handle.removeEventListener('pointerup', onUp);\n handle.removeEventListener('pointercancel', onUp);\n sheet.style.transition = '';\n const finalHeight = sheet.getBoundingClientRect().height;\n sheet.style.height = '';\n if (finalHeight < drag.vh * CLOSE_RATIO) {\n onClose();\n return;\n }\n const midPx = drag.vh * MID_RATIO;\n const fullPx = drag.vh * FULL_RATIO;\n setMode(Math.abs(finalHeight - fullPx) < Math.abs(finalHeight - midPx) ? 'full' : 'mid');\n };\n handle.addEventListener('pointermove', onMove);\n handle.addEventListener('pointerup', onUp);\n handle.addEventListener('pointercancel', onUp);\n }\n\n if (!open) return null;\n\n return (\n <div className=\"bottom-sheet-backdrop\" onClick={onClose}>\n <div\n ref={sheetRef}\n className={`bottom-sheet bottom-sheet--${mode}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"bottom-sheet-handle-area\"\n onPointerDown={onHandlePointerDown}\n aria-hidden=\"true\"\n >\n <span className=\"bottom-sheet-handle\" />\n </div>\n {closeLabel && (\n <button\n type=\"button\"\n className=\"bottom-sheet-close\"\n aria-label={closeLabel}\n title={closeLabel}\n onClick={onClose}\n >\n ×\n </button>\n )}\n <div className=\"bottom-sheet-body\">{children}</div>\n </div>\n </div>\n );\n}\n","// 共有ブレークポイント定数。純粋な文字列定数のみ(leaf。他 foundation パッケージに依存しない)。\n\n// タッチ端末/狭幅レイアウトの判定に使う複合メディアクエリ。「ホバー無し/タッチポインタ/狭幅」の\n// いずれかに一致すればモバイル相当のレイアウトとみなす(pointer:coarse ベースの判定を正とする)。\n// SplitModal のドリルダウン閾値(768px。widthのみの判定)とは意図的に別物。こちらは「D&Dが使えるか」\n// 「タッチ主体のコンパクトUIにするか」の判定で、幅だけでなくポインタ種別も見る。\nexport const MOBILE_LAYOUT_MQ = '(hover: none), (pointer: coarse), (max-width: 560px)';\n","// サイズ可変のローディングインジケータ(純粋 leaf UI)。\n// 旧来 feature ごとに散っていた回転スピナー(voice-chat-connecting-spinner /\n// playlist の読み込み中表示等)を DS に集約する。トンマナに合わせ、薄いミントのリングに\n// ミントの先頭という控えめな見た目。回転は Tailwind の animate-spin(prefers-reduced-motion は\n// style.css 末尾の legacy ルールが全体に効く)。\nexport type SpinnerProps = {\n // 直径(px)。既定 16。\n size?: number;\n // リングの太さ(px)。既定は size に応じて 2。\n thickness?: number;\n // スクリーンリーダー向けラベル(i18n は props 注入)。省略時は aria-hidden。\n label?: string;\n className?: string;\n};\n\nexport default function Spinner({ size = 16, thickness, label, className = '' }: SpinnerProps) {\n const border = thickness ?? Math.max(2, Math.round(size / 8));\n return (\n <span\n role={label ? 'status' : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n className={`inline-block shrink-0 rounded-pill border-solid border-border-strong animate-spin ${className}`.trim()}\n style={{\n width: size,\n height: size,\n borderWidth: border,\n borderTopColor: 'var(--color-mint)',\n }}\n />\n );\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport Icon, { type IconName } from './icons/icon.tsx';\nimport Spinner from './spinner.tsx';\n\n// DS のボタン(純粋 leaf UI)。claude design \"INSESSION Design System\" のボタン仕様に準拠(#463 / #663)。\n// variant: primary=中立塗り(fill) / accent=コーラル / secondary=2px アウトライン / ghost=テキスト(info) /\n// live=ライブ緑の pill + 先頭ドット(Join session。DS の正名) / danger=危険(アプリ固有・DS外だが必要)。\n// `join` は歴史的別名として live にマップする(後方互換。消費側は当面そのまま動く)。\n// radius は既定 DS の md(10px)。pill prop で rounded-pill、live/join は常に pill。font 15px、\n// weight は primary/accent/secondary/danger/live=700・ghost=600。disabled は DS の沈んだ面(surface-3 + text-dim)。\n// hover は DS へ準拠: soft(secondary/ghost)=surface-hover の面変化 / filled(primary/accent/live/danger)=brightness(.93)。\n// press=scale(.97)。フォーカスは shadow-focus。i18n は持たない(ラベルは children)。\n// icon / iconRight は名前(IconName)なら fontSize+2 の Icon を、ReactNode ならそのまま先頭/末尾に置く。\nexport type ButtonVariant =\n | 'primary'\n | 'accent'\n | 'secondary'\n | 'ghost'\n | 'danger'\n | 'live'\n | 'join';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type ButtonProps = {\n variant?: ButtonVariant;\n size?: ButtonSize;\n // 読み込み中。スピナーを表示し操作不可にする(disabled と同様に押せない)。\n loading?: boolean;\n // pill 形状(rounded-pill)にする。既定は DS の md(rounded-md)。ポップオーバー内の\n // コンパクトなアップロード導線など丸い体裁が欲しい箇所で使う(#517)。live/join は歴史的に常に pill。\n pill?: boolean;\n // 先頭に白い小ドットを出す(DS の dot)。live/join では既定で出る。\n dot?: boolean;\n // 先頭/末尾のアイコン。IconName(文字列)なら Icon をサイズ自動で描画、ReactNode ならそのまま。\n icon?: IconName | ReactNode;\n iconRight?: IconName | ReactNode;\n children: ReactNode;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> & { className?: string };\n\n// border-2 を基底に置き、secondary(2px 枠)と他(透明枠)で外形を揃える(box-border)。\n// 角丸(rounded-md / rounded-pill)は同一ユーティリティの競合を避けるため BASE に含めず\n// radius として一方だけを組み立てて付与する(#517)。\nconst BASE =\n 'inline-flex items-center justify-center gap-2 border-2 border-solid border-transparent box-border font-display cursor-pointer select-none transition-[transform,filter,background,color,box-shadow] duration-(--dur-fast) ease-spring enabled:active:scale-[0.97] disabled:bg-surface-3 disabled:text-text-dim disabled:border-transparent disabled:cursor-not-allowed disabled:shadow-none focus-visible:shadow-focus focus-visible:outline-none';\n\nconst VARIANT: Record<ButtonVariant, string> = {\n primary: 'bg-fill text-on-fill font-bold enabled:hover:brightness-[.93]',\n accent: 'bg-accent text-on-accent font-bold enabled:hover:brightness-[.93]',\n secondary: 'bg-transparent border-text text-text font-bold enabled:hover:bg-surface-hover',\n ghost: 'bg-transparent text-info font-semibold enabled:hover:bg-surface-hover',\n danger:\n 'bg-danger-surface border-danger-border text-danger font-bold enabled:hover:brightness-[.93]',\n live: 'bg-success text-white font-bold enabled:hover:brightness-[.93]',\n // 後方互換: join は live と同一。\n join: 'bg-success text-white font-bold enabled:hover:brightness-[.93]',\n};\n\n// DS の padding。primary/accent/danger/live は 12/22。ghost は横を詰める(テキストボタン)。\n// xs はポップオーバー/モバイル向けのコンパクト(#517)。DS の xs 仕様(px-3/py-1.5, text-xs)に準拠(#854)。\nconst SIZE: Record<ButtonSize, string> = {\n xs: 'text-xs px-3 py-1.5',\n sm: 'text-sm px-4 py-2',\n md: 'text-md px-[22px] py-3',\n lg: 'text-md px-7 py-3.5',\n};\nconst GHOST_PAD = 'px-3.5';\n\nconst SPINNER_SIZE: Record<ButtonSize, number> = { xs: 12, sm: 13, md: 15, lg: 16 };\n// DS: Icon は fontSize+2。size ごとの実 px(11/12/15/16 → +2)。\nconst ICON_SIZE: Record<ButtonSize, number> = { xs: 13, sm: 14, md: 17, lg: 18 };\n\nfunction renderIcon(icon: IconName | ReactNode, px: number): ReactNode {\n if (icon == null) return null;\n if (typeof icon === 'string') return <Icon name={icon as IconName} size={px} />;\n return icon;\n}\n\nexport default function Button({\n variant = 'primary',\n size = 'md',\n loading = false,\n disabled = false,\n pill = false,\n dot = false,\n icon,\n iconRight,\n type = 'button',\n children,\n className = '',\n ...rest\n}: ButtonProps) {\n const pad = variant === 'ghost' ? `${SIZE[size]} ${GHOST_PAD}` : SIZE[size];\n const isLive = variant === 'live' || variant === 'join';\n // live/join は歴史的に常に pill 形状。それ以外は pill prop に従う。\n const radius = pill || isLive ? 'rounded-pill' : 'rounded-md';\n const showDot = (dot || isLive) && !loading;\n const iconPx = ICON_SIZE[size];\n return (\n <button\n type={type}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={`${BASE} ${radius} ${VARIANT[variant]} ${pad} ${className}`.trim()}\n {...rest}\n >\n {showDot && <span className=\"h-2 w-2 rounded-pill bg-white\" aria-hidden=\"true\" />}\n {loading && <Spinner size={SPINNER_SIZE[size]} />}\n {!loading && renderIcon(icon, iconPx)}\n {children}\n {!loading && renderIcon(iconRight, iconPx)}\n </button>\n );\n}\n","import type { InputHTMLAttributes, ReactNode } from 'react';\nimport { useId } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// DS のチェックボックス(純粋 leaf UI)。claude design \"INSESSION Design System\" の Controls 仕様に準拠(#463)。\n// 22x22 / radius 6(chip)。off=2px 枠、on=fill 塗り + on-fill のチェック。ネイティブ input を視覚的に隠し\n// (a11y/フォーカス維持)、隣の span を状態で描画する。i18n は持たない(label は children 相当の prop)。\nexport type CheckboxProps = {\n checked: boolean;\n label?: ReactNode;\n className?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'type'>;\n\nexport default function Checkbox({ checked, label, id, className = '', ...rest }: CheckboxProps) {\n const autoId = useId();\n const inputId = id ?? autoId;\n return (\n <label\n htmlFor={inputId}\n className={`inline-flex cursor-pointer select-none items-center gap-3 ${className}`.trim()}\n >\n <input id={inputId} type=\"checkbox\" checked={checked} className=\"peer sr-only\" {...rest} />\n <span\n className={`grid h-[22px] w-[22px] place-items-center rounded-chip border-2 border-solid transition-colors peer-focus-visible:shadow-focus ${\n checked\n ? 'border-fill bg-fill text-on-fill'\n : 'border-border-strong bg-transparent text-transparent'\n }`}\n >\n <Icon name=\"check\" size={15} />\n </span>\n {label != null && <span className=\"text-md text-text\">{label}</span>}\n </label>\n );\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// DS の Chip(純粋 leaf UI)。claude design \"INSESSION Design System\" の Chip 仕様に準拠(#463 / #663)。\n// タップできる要素(クイック返信・フィルター・タグ・入力トークン)。非対話の status ラベルは Badge を使う。\n// 既定=surface-2 + border-strong、selected=accent tint(12%) + accent 枠(55%) + accent 文字 + check。\n// pill、12.5px、weight は selected?700:600。pad は DS の3系統(removable / avatar / 既定)。\n// avatar は 22x22 の円(label + color。既定は success green)。removable は末尾に close(text-dim)。\n// i18n は持たない(ラベルは children)。\nexport type ChipAvatar = {\n // 円内の1〜2文字。\n label: ReactNode;\n // 円の背景色(CSS 色。省略時は success green)。\n color?: string;\n};\n\nexport type ChipProps = {\n // 選択状態。true で accent tint + 枠 + チェックになる。\n selected?: boolean;\n // 行頭アイコン(任意。selected 時は check が優先されるため出さない)。\n icon?: ReactNode;\n // 行頭のアバター円(任意)。\n avatar?: ChipAvatar;\n // 末尾に × を出し、クリックで onRemove を呼ぶ(入力トークン用)。\n removable?: boolean;\n onRemove?: () => void;\n children: ReactNode;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> & { className?: string };\n\nconst BASE =\n 'inline-flex items-center gap-1.5 rounded-pill border border-solid text-[12.5px] cursor-pointer select-none transition-colors duration-(--dur-fast)';\n// DS の3系統の pad。removable=6/10/6/14、avatar=5/13/5/5、既定=7/14。\nconst PAD_DEFAULT = 'px-3.5 py-[7px]';\nconst PAD_REMOVABLE = 'pl-[14px] pr-2.5 py-1.5';\nconst PAD_AVATAR = 'pl-[5px] pr-[13px] py-[5px]';\n// 既定の面は surface-2 を維持する。surface-3 はライトで #ebe7dc とページ背景(#e9e9e6)にほぼ\n// 埋もれるため、濃くするつもりで下げると逆にコントラストが落ちる(#765)。\nconst DEFAULT =\n 'bg-surface-2 border-border-strong text-text font-semibold enabled:hover:bg-surface-hover';\n// selected 枠は DS の accent 55%。tint は視認性確保のため bg-tint-22 に強化(#765)。\nconst SELECTED =\n 'bg-tint-22 border-[color-mix(in_srgb,var(--color-accent)_55%,transparent)] text-accent font-bold';\n\nexport default function Chip({\n selected = false,\n icon,\n avatar,\n removable = false,\n onRemove,\n children,\n type = 'button',\n className = '',\n ...rest\n}: ChipProps) {\n const pad = removable ? PAD_REMOVABLE : avatar ? PAD_AVATAR : PAD_DEFAULT;\n return (\n <button\n type={type}\n aria-pressed={selected}\n className={`${BASE} ${pad} ${selected ? SELECTED : DEFAULT} ${className}`.trim()}\n {...rest}\n >\n {avatar && (\n <span\n className=\"inline-flex h-[22px] w-[22px] items-center justify-center rounded-pill bg-success text-xs font-bold text-white\"\n style={avatar.color ? { background: avatar.color } : undefined}\n aria-hidden=\"true\"\n >\n {avatar.label}\n </span>\n )}\n {selected ? <Icon name=\"check\" size={16} /> : icon}\n {children}\n {removable && (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"remove\"\n className=\"inline-flex text-text-dim\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove?.();\n }}\n >\n <Icon name=\"close\" size={15} />\n </span>\n )}\n </button>\n );\n}\n","import type { FormEvent, KeyboardEvent, MutableRefObject, ReactNode } from 'react';\nimport { useEffect, useRef } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// メッセージ入力フォーム(純粋 leaf UI)。space のチャット入力とコミュニティの投稿入力の共通化\n// (#1027)。textarea + 下段アクション行(左: actions props / 右: 送信アイコンボタン)の構成で、\n// 呼び出し側は controlled(value/onChange)で使う。i18n は持たない(placeholder / sendLabel は\n// 呼び出し側が文字列を渡す)。\n//\n// 挙動:\n// - Enter で送信 / Shift+Enter で改行 / IME変換確定のEnterは送信しない(isComposing ガード)\n// - textarea は rows=1 から内容に応じて自動で伸びる(max-height到達でスクロール可能に切替)。\n// PiP(別ドキュメントへcreatePortal)でCSSが未適用のままautoGrowが走るケースに備え、\n// getComputedStyle().maxHeightが解決するまで短い間隔でリトライする(space-core chat-panel の\n// 実装をそのまま移設。挙動は変えない)。\n// - onSubmit は trim 後に非空のときだけ呼ぶ。value のクリアは呼び出し側の責務(controlled なので\n// このコンポーネントは value を保持しない)。\nexport type ComposerProps = {\n value: string;\n onChange: (text: string) => void;\n onSubmit: (text: string) => void;\n placeholder?: string;\n maxLength?: number;\n disabled?: boolean;\n // 送信ボタンの aria-label / title(表示ラベルではない。送信ボタンはアイコンのみ)。\n sendLabel: string;\n // 送信ボタンの左に置くアクション領域(スタンプピッカー・定型文ボタン等)。\n actions?: ReactNode;\n // 送信直後の一瞬の強調(呼び出し側が setTimeout で false に戻す想定)。\n flash?: boolean;\n // 外部から textarea へ focus するための ref。\n textareaRef?: MutableRefObject<HTMLTextAreaElement | null>;\n // コンパクト表示(コミュニティの返信欄等、狭い行内に馴染ませたい場合)。\n size?: 'default' | 'compact';\n className?: string;\n};\n\nconst AUTO_GROW_RETRY_MS = 200;\nconst AUTO_GROW_RETRY_LIMIT = 25;\n\nexport default function Composer({\n value,\n onChange,\n onSubmit,\n placeholder,\n maxLength,\n disabled = false,\n sendLabel,\n actions,\n flash = false,\n textareaRef,\n size = 'default',\n className = '',\n}: ComposerProps) {\n const ownRef = useRef<HTMLTextAreaElement | null>(null);\n const ref = textareaRef ?? ownRef;\n const autoGrowRetryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const autoGrowRetryCountRef = useRef(0);\n\n function clearAutoGrowRetry() {\n if (autoGrowRetryTimerRef.current !== null) {\n clearTimeout(autoGrowRetryTimerRef.current);\n autoGrowRetryTimerRef.current = null;\n }\n }\n\n // 入力欄(textarea)は複数行入力に合わせて自動で伸びる。最大高さはCSS側(max-h-*)で制御する。\n // scrollHeightがmax-height未満の間はoverflow-yをhiddenにし、内容が収まっているのに\n // スクロールバーが出てしまうのを防ぐ(max-heightに達したときだけauto化してスクロール可能にする)。\n // PiP(別ドキュメントへcreatePortal)ではCSSが<link>の非同期再フェッチで届くため、適用前に\n // autoGrowが走るとgetComputedStyle().maxHeightが'none'のまま(未解決)になり得る。未解決の間は\n // 安全側としてoverflow-yをhiddenに固定し(スクロールバーを出さない)、CSS適用後に再計測できるよう\n // 短い間隔(200ms)でリトライする(上限25回=5秒で打ち切り)。\n function autoGrow() {\n // 前回スケジュールしたリトライが残っていれば必ず先にclearする(多重スケジュール防止)\n clearAutoGrowRetry();\n const el = ref.current;\n if (!el) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n const maxHeight = Number.parseFloat(getComputedStyle(el).maxHeight);\n if (!Number.isFinite(maxHeight) || maxHeight <= 0) {\n el.style.overflowY = 'hidden';\n if (autoGrowRetryCountRef.current < AUTO_GROW_RETRY_LIMIT) {\n autoGrowRetryCountRef.current += 1;\n autoGrowRetryTimerRef.current = setTimeout(autoGrow, AUTO_GROW_RETRY_MS);\n }\n return;\n }\n autoGrowRetryCountRef.current = 0;\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: autoGrowは毎レンダー作り直す純粋な関数(state更新なし)なので依存に含めない\n useEffect(() => {\n autoGrow();\n // unmount時・次のautoGrow実行(value変化での再実行)時のいずれもクリーンアップで確実にclearする\n return () => clearAutoGrowRetry();\n }, [value]);\n\n function trySubmit() {\n const text = value.trim();\n if (!text) return;\n onSubmit(text);\n }\n\n function handleFormSubmit(e: FormEvent) {\n e.preventDefault();\n trySubmit();\n }\n\n // Enterで送信、Shift+Enterで改行(複数行入力対応)。IME変換確定のEnterでは送信しない。\n function handleKeyDown(e: KeyboardEvent<HTMLTextAreaElement>) {\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n trySubmit();\n }\n }\n\n const canSubmit = !disabled && value.trim().length > 0;\n const textareaPad = size === 'compact' ? 'px-3.5 pt-2 pb-0.5' : 'px-4.5 pt-2.5 pb-1';\n const actionsPad = size === 'compact' ? 'px-2 py-1.5' : 'px-2 py-2.5';\n const iconSize = size === 'compact' ? 14 : 16;\n const btnSize = size === 'compact' ? 'h-6.5 w-6.5' : 'h-7.5 w-7.5';\n\n return (\n <form\n onSubmit={handleFormSubmit}\n className={`flex flex-col rounded-card border-[1.5px] border-solid bg-surface transition-[border-color,box-shadow] duration-(--dur-fast) ${\n flash ? 'border-mint shadow-focus' : 'border-border'\n } ${className}`.trim()}\n >\n <textarea\n ref={ref}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n rows={1}\n autoComplete=\"off\"\n className={`max-h-[120px] resize-none border-none bg-transparent font-body text-md leading-snug text-text outline-none placeholder:text-text-faint ${textareaPad}`}\n />\n <div className={`flex items-center justify-between gap-2 ${actionsPad}`}>\n <div className=\"flex items-center gap-0.5\">{actions}</div>\n <button\n type=\"submit\"\n aria-label={sendLabel}\n title={sendLabel}\n disabled={!canSubmit}\n className={`inline-flex shrink-0 cursor-pointer items-center justify-center rounded-pill border-none bg-transparent p-0 transition-colors duration-(--dur-fast) ${btnSize} ${\n canSubmit ? 'text-mint-soft' : 'text-text-dim'\n } enabled:hover:bg-tint-5 enabled:hover:text-mint-soft disabled:cursor-not-allowed disabled:opacity-35`}\n >\n <Icon name=\"send\" size={iconSize} />\n </button>\n </div>\n </form>\n );\n}\n","import { type ReactNode, useEffect, useRef } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// 汎用モーダルの外殻(純粋 leaf UI)。backdrop・本体・×閉じボタン・Esc・背景クリックで閉じる、を\n// 一箇所にまとめる。i18n はこのパッケージに持たないため、閉じるラベルは props で注入する。\n//\n// 2つの体裁を持つ(#663):\n// - 既定(children のみ): legacy .modal / .modal-backdrop / .modal-close の共有プリミティブを使う\n// 従来経路(中央寄せ h2 / submit ボタン装飾に依存する多数の消費側をそのまま動かす)。\n// - DS 構造(title / footer を渡したとき): claude design \"INSESSION Design System\" の Modal に準拠し、\n// トークンのユーティリティで title 行(border-bottom + × アイコン)/ body(pad18) / footer 行\n// (border-top + surface-2)を組む。既存 API(children + width + closeLabel + as/onSubmit + closeOnEsc)は維持。\n//\n// 幅は `width`(CSS 長さ)を inline style で当てる。\nexport type ModalProps = {\n onClose: () => void;\n children: ReactNode;\n // 基底 .modal の幅を上書きする CSS 長さ(例 'min(760px, 94vw)')。省略時は基底幅。\n width?: string;\n // 本体(.modal)に足す追加クラス。\n className?: string;\n // ダイアログの aria-label。\n ariaLabel?: string;\n // × 閉じるボタンの aria ラベル(i18n は props 注入)。渡したときだけ×を表示する。\n closeLabel?: string;\n // 本体要素。フォーム型モーダルは 'form'。既定 'div'。\n as?: 'div' | 'form';\n // as='form' のときの submit ハンドラ。\n onSubmit?: (e: any) => void;\n // Esc キーで閉じる。既定 true。\n closeOnEsc?: boolean;\n // DS 構造のタイトル行(指定すると DS 構造で描画する)。\n title?: ReactNode;\n // DS 構造のフッター行(アクション群。指定すると DS 構造で描画する)。\n footer?: ReactNode;\n};\n\nexport default function Modal({\n onClose,\n children,\n width,\n className = '',\n ariaLabel,\n closeLabel,\n as = 'div',\n onSubmit,\n closeOnEsc = true,\n title,\n footer,\n}: ModalProps) {\n // PiP(Document Picture-in-Picture)等、別ドキュメントへ createPortal されるケースに対応するため、\n // Esc リスナーは自身の描画先(backdropRef の ownerDocument)の window から張る(メインドキュメントの\n // 消費側は ownerDocument が常に main document なので挙動は従来と完全に同一)。\n const backdropRef = useRef<HTMLDivElement | null>(null);\n useEffect(() => {\n if (!closeOnEsc) return undefined;\n const win = backdropRef.current?.ownerDocument?.defaultView ?? window;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n win.addEventListener('keydown', onKey);\n return () => win.removeEventListener('keydown', onKey);\n }, [onClose, closeOnEsc]);\n\n const Box: any = as;\n const ds = title != null || footer != null;\n\n return (\n <div className=\"modal-backdrop\" ref={backdropRef} onClick={onClose}>\n {ds ? (\n // DS 構造(トークンのユーティリティ)。\n <Box\n className={`relative flex w-full flex-col overflow-hidden rounded-card border border-solid border-border bg-surface shadow-overlay animate-[card-in_0.4s_var(--ease-spring)_both] ${className}`.trim()}\n style={width ? { width } : { width: 'min(420px, 92vw)' }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n onClick={(e: any) => e.stopPropagation()}\n onSubmit={onSubmit}\n >\n {title != null && (\n <div className=\"flex items-center justify-between gap-3 border-b border-solid border-border px-[18px] py-4\">\n <span className=\"text-lg font-extrabold text-text\">{title}</span>\n {closeLabel && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n title={closeLabel}\n onClick={onClose}\n className=\"inline-flex h-[30px] w-[30px] items-center justify-center rounded-chip border-none bg-transparent text-text-dim cursor-pointer enabled:hover:bg-surface-hover enabled:hover:text-text\"\n >\n <Icon name=\"close\" size={19} />\n </button>\n )}\n </div>\n )}\n <div className=\"p-[18px]\">{children}</div>\n {footer != null && (\n <div className=\"flex justify-end gap-2.5 border-t border-solid border-border bg-surface-2 px-[18px] py-3.5\">\n {footer}\n </div>\n )}\n </Box>\n ) : (\n // 既定(legacy 共有プリミティブ)。従来経路と完全同一。\n <Box\n className={`modal ${className}`.trim()}\n style={width ? { width } : undefined}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n onClick={(e: any) => e.stopPropagation()}\n onSubmit={onSubmit}\n >\n {closeLabel && (\n <button\n type=\"button\"\n className=\"modal-close\"\n aria-label={closeLabel}\n title={closeLabel}\n onClick={onClose}\n >\n ×\n </button>\n )}\n {children}\n </Box>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport Button, { type ButtonVariant } from './button.tsx';\nimport Icon, { type IconName } from './icons/icon.tsx';\nimport Modal from './modal.tsx';\n\n// 確認ダイアログ(純粋 leaf UI)。Modal を土台に DS(claude design \"INSESSION Design System\" #663)の\n// Confirm 体裁「tone のアイコン円 + 見出し + 本文 + キャンセル/実行の2ボタン」を標準化する。\n// 破壊的操作は confirmVariant='danger'(tone も自動で danger)で実行ボタン/アイコンを危険色にする。\n// i18n は持たない(文言は注入)。\nexport type ConfirmTone = 'danger' | 'warn' | 'info';\n\nexport type ConfirmModalProps = {\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n children: ReactNode;\n confirmLabel: string;\n cancelLabel: string;\n // 実行ボタンの見た目。破壊的操作は 'danger'。既定 'primary'。\n confirmVariant?: ButtonVariant;\n // アイコン円の tone。省略時は confirmVariant==='danger' なら danger、他は info。\n tone?: ConfirmTone;\n // アイコン円のアイコン。既定 'warning'。\n icon?: IconName;\n // 実行処理中(ボタンをローディング表示にする)。\n loading?: boolean;\n ariaLabel?: string;\n // Modal 本体(.modal)に足す追加クラス(幅など)。\n className?: string;\n};\n\nconst TONE_CIRCLE: Record<ConfirmTone, string> = {\n danger: 'text-danger bg-danger-surface',\n warn: 'text-warning bg-warning-surface',\n info: 'text-info bg-info-surface',\n};\n\nexport default function ConfirmModal({\n onClose,\n onConfirm,\n title,\n children,\n confirmLabel,\n cancelLabel,\n confirmVariant = 'primary',\n tone,\n icon = 'warning',\n loading = false,\n ariaLabel,\n className = '',\n}: ConfirmModalProps) {\n const resolvedTone: ConfirmTone = tone ?? (confirmVariant === 'danger' ? 'danger' : 'info');\n return (\n <Modal onClose={onClose} ariaLabel={ariaLabel ?? title} className={className}>\n <span\n className={`mx-auto inline-flex h-[46px] w-[46px] items-center justify-center rounded-pill ${TONE_CIRCLE[resolvedTone]}`}\n aria-hidden=\"true\"\n >\n <Icon name={icon} size={24} />\n </span>\n <h2>{title}</h2>\n <p className=\"break-words text-center text-base leading-[1.55] text-text-dim\">{children}</p>\n <div className=\"mt-2 flex gap-2.5\">\n <Button variant=\"ghost\" className=\"flex-1\" onClick={onClose}>\n {cancelLabel}\n </Button>\n <Button variant={confirmVariant} className=\"flex-1\" loading={loading} onClick={onConfirm}>\n {confirmLabel}\n </Button>\n </div>\n </Modal>\n );\n}\n","import type { ReactNode } from 'react';\n\n// 空リスト/エラー時の一行メッセージ(純粋 leaf UI)。文言は t() 済みを children で渡す。\n// 旧 .empty-note(+ .media-tabs / .search-dropdown コンテキスト上書き)を @theme トークン\n// 経由のユーティリティへ移行した。padding/揃えは文脈ごとに competing utility を出さないよう\n// variant で切り替える(class 文字列の後付けでは Tailwind の生成順に負ける落とし穴を避ける)。\nexport type EmptyNoteProps = {\n children: ReactNode;\n // 'default'=中央寄せ・広め(既定)/ 'compact'=中央寄せ・詰め(キュー/履歴タブ)/\n // 'dropdown'=中央寄せ・検索候補ドロップダウン内。いずれも水平・垂直とも中央(#202)。\n variant?: 'default' | 'compact' | 'dropdown';\n};\n\nconst VARIANT: Record<NonNullable<EmptyNoteProps['variant']>, string> = {\n default: 'px-4 py-5 text-center',\n compact: 'flex min-h-32 items-center justify-center px-1 py-3.5 text-center',\n dropdown: 'flex min-h-28 items-center justify-center px-4 py-[18px] text-center',\n};\n\nexport default function EmptyNote({ children, variant = 'default' }: EmptyNoteProps) {\n return (\n <p className={`${VARIANT[variant]} text-base leading-[1.7] text-text-faint`}>{children}</p>\n );\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\n\n// アイコンのみの正方形ボタン(純粋 leaf UI)。claude design \"INSESSION Design System\" 準拠(loophub #682)。\n// variant: surface(既定。surface-2 面 + border + hover surface-hover) / accent(coral 塗り) /\n// ghost(透明地・hover のみ面が付く)。icon は呼び出し側が `.mi` span か Icon(icons/icon.tsx) を渡す\n// (Material Symbols の ligature 名を使う箇所があるため、Button と違い IconName 限定にしない)。\n// aria-label は必須(label prop)。i18n は持たない。\nexport type IconButtonVariant = 'surface' | 'accent' | 'ghost';\n\nexport type IconButtonProps = {\n label: string;\n icon: ReactNode;\n variant?: IconButtonVariant;\n // 一辺の長さ(px)。既定 36。\n size?: number;\n className?: string;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'>;\n\nconst VARIANT: Record<IconButtonVariant, string> = {\n surface:\n 'bg-surface-2 border border-solid border-border text-text-dim enabled:hover:bg-surface-hover enabled:hover:text-text',\n accent:\n 'bg-accent border border-solid border-transparent text-on-accent enabled:hover:brightness-[.93]',\n ghost:\n 'bg-transparent border border-solid border-transparent text-text-dim enabled:hover:bg-surface-hover',\n};\n\nexport default function IconButton({\n label,\n icon,\n variant = 'surface',\n size = 36,\n type = 'button',\n className = '',\n disabled,\n ...rest\n}: IconButtonProps) {\n return (\n <button\n type={type}\n aria-label={label}\n disabled={disabled}\n style={{ width: size, height: size }}\n className={`inline-flex shrink-0 items-center justify-center rounded-md cursor-pointer transition-colors duration-(--dur-fast) disabled:cursor-not-allowed disabled:opacity-(--disabled-opacity) focus-visible:shadow-focus focus-visible:outline-none ${VARIANT[variant]} ${className}`.trim()}\n {...rest}\n >\n {icon}\n </button>\n );\n}\n","// Google ブランドカラーのロゴアイコン(純粋 SVG・props 不要)。Google ログインボタンに使う。\n// ブランド指定色のため、この SVG に限り生 hex を許容する(トークン化対象外の外部ブランド資産)。\nexport default function GoogleIcon() {\n return (\n <svg className=\"google-icon\" viewBox=\"0 0 18 18\" width=\"18\" height=\"18\" aria-hidden=\"true\">\n <path\n fill=\"#4285F4\"\n d=\"M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z\"\n />\n <path\n fill=\"#34A853\"\n d=\"M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z\"\n />\n <path\n fill=\"#FBBC05\"\n d=\"M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33Z\"\n />\n <path\n fill=\"#EA4335\"\n d=\"M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58C13.46.89 11.42 0 9 0A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z\"\n />\n </svg>\n );\n}\n","// 人型アイコン(純粋 SVG・props 不要)。未ログイン時のユーザーメニュートリガー等に使う。\nexport default function PersonIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" aria-hidden=\"true\" fill=\"none\">\n <circle cx=\"12\" cy=\"8\" r=\"4\" stroke=\"currentColor\" strokeWidth=\"1.8\" />\n <path\n d=\"M4 20c0-3.3 3.6-6 8-6s8 2.7 8 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n","import type { InputHTMLAttributes, ReactNode } from 'react';\nimport { useId, useState } from 'react';\n\n// DS のテキスト入力(純粋 leaf UI)。claude design \"INSESSION Design System\" の Inputs 仕様に準拠(#463 / #663)。\n// ラベルは mono・大文字(Label caps)。DS どおり focused を state 追跡し、label/border/ring を切替える:\n// error → accent(枠 + ラベル + 下メッセージ)、focused → info(枠 + ラベル + リング)、default → text-dim / border。\n// field は surface-2 / border 1.5px / radius md(10) / pad 12/14 / font 15。prefix は field 内・input 左に\n// mono の接頭辞(例 insession.app/r/)を text-dim で置く。i18n は持たない(label / error は文字列を受け取る)。\nexport type InputProps = {\n label?: ReactNode;\n // エラーメッセージ。指定すると error 状態(accent 枠 + 下にメッセージ)になる。\n error?: ReactNode;\n // field 内・input の左に置く mono の接頭辞(任意)。例: 'insession.app/r/'。\n prefix?: ReactNode;\n className?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'className'>;\n\nconst LABEL = 'font-mono text-xs font-semibold tracking-widest uppercase transition-colors';\n// field(ラッパー)。surface-2 / border 1.5px / radius md / pad 12x14。focus リング/枠色は状態で足す。\nconst FIELD =\n 'flex items-center w-full bg-surface-2 border-[1.5px] border-solid rounded-md px-3.5 py-3 transition-[border-color,box-shadow] duration-(--dur-fast)';\nconst CONTROL =\n 'flex-1 min-w-0 border-none outline-none bg-transparent text-md text-text placeholder:text-text-faint';\n\nexport default function Input({\n label,\n error,\n prefix,\n id,\n onFocus,\n onBlur,\n className = '',\n ...rest\n}: InputProps) {\n const autoId = useId();\n const inputId = id ?? autoId;\n const invalid = error != null && error !== false;\n const [focused, setFocused] = useState(false);\n // 状態の優先度: error > focused > default。\n const labelColor = invalid ? 'text-accent' : focused ? 'text-info' : 'text-text-dim';\n const fieldState = invalid\n ? 'border-accent'\n : focused\n ? 'border-info shadow-focus'\n : 'border-border';\n return (\n <div className={`flex flex-col gap-[7px] ${className}`.trim()}>\n {label != null && (\n <label htmlFor={inputId} className={`${LABEL} ${labelColor}`}>\n {label}\n </label>\n )}\n <div className={`${FIELD} ${fieldState}`}>\n {prefix != null && (\n <span className=\"mr-0.5 shrink-0 font-mono text-md text-text-dim\">{prefix}</span>\n )}\n <input\n id={inputId}\n aria-invalid={invalid || undefined}\n className={CONTROL}\n onFocus={(e) => {\n setFocused(true);\n onFocus?.(e);\n }}\n onBlur={(e) => {\n setFocused(false);\n onBlur?.(e);\n }}\n {...rest}\n />\n </div>\n {invalid && <span className=\"text-xs text-accent\">{error}</span>}\n </div>\n );\n}\n","import {\n type AnchorHTMLAttributes,\n cloneElement,\n isValidElement,\n type ReactElement,\n type ReactNode,\n} from 'react';\n\n// DS のテキストリンク(純粋 leaf UI)。#633。下線は全 variant で使わず、ボタンのラベルのように\n// 「色 + フォントウェイト(+ hover の色/面変化)」で区別する。用途で3種に整理する:\n// inline = 本文中リンク。静止=link 色 + semibold、hover で link-hover 色。\n// subtle = リスト脇の弱い誘導(旧 `text-accent text-sm` の置換先)。inline の小サイズ版。\n// pill = セクション見出し脇や「戻る」導線などの独立リンク(旧 `.section-link` / `.list-back` を統合)。\n// wrapper = カード等のブロック全体をリンクにする器(#795)。中身のタイポは呼び出し側が持つので\n// 色・ウェイト・サイズを一切持たず(`text-inherit`)、UA 既定の下線だけを確実に消す。\n// 面/境界/角丸/影などのカード表現は呼び出し側の className で足す。\n//\n// 色は必ずセマンティックトークン(--color-link / --color-link-hover。生 hex を書かない)。\n// focus リングはアプリ横断のグローバル `:focus-visible`(--color-focus-ring / --focus-ring-*)に\n// 一任する = 全リンクで共通。ここでは outline を上書きしない。\n//\n// react-router の `Link` / `NavLink` と 生 `<a>` の両方を吸収するため:\n// - 生 `<a>` なら `<Link variant=\"inline\" href=\"…\">` をそのまま使う。\n// - react-router 等の別コンポーネントには `asChild` で子要素へクラスだけを注入する\n// (`<Link asChild variant=\"pill\"><RouterLink to=\"/\">…</RouterLink></Link>`)。\n// - className だけ欲しい場合は `linkClass(variant)` を直接 className に渡す\n// (react-router `Link` の className に載せる用途で最も手軽)。\nexport type LinkVariant = 'inline' | 'subtle' | 'pill' | 'wrapper';\n\n// 下線は使わない(ボタンテキスト調)。色・ウェイトはトークン経由。arbitrary は 4/8px リズムに\n// 載らない値のみ(py-[7px] 等)。\nconst VARIANT: Record<LinkVariant, string> = {\n inline:\n 'text-link font-semibold no-underline cursor-pointer transition-colors duration-(--dur-fast) hover:text-link-hover',\n subtle:\n 'text-link text-sm font-semibold no-underline cursor-pointer transition-colors duration-(--dur-fast) hover:text-link-hover',\n pill: 'inline-flex items-center gap-1.5 self-start px-4 py-2.5 rounded-pill border border-solid border-border bg-surface text-text text-sm font-bold tracking-pill uppercase no-underline cursor-pointer transition-[background,color,transform] duration-(--dur-base) ease-spring hover:bg-surface-hover hover:text-accent hover:-translate-y-px',\n wrapper: 'text-inherit no-underline cursor-pointer',\n};\n\n// variant のクラス文字列。react-router `Link`/`NavLink` の className にそのまま渡せる。\nexport function linkClass(variant: LinkVariant = 'inline', className = ''): string {\n return `${VARIANT[variant]} ${className}`.trim();\n}\n\nexport type LinkProps = {\n variant?: LinkVariant;\n // 子要素(react-router の Link/NavLink 等)へクラスだけを注入して DS 化する。\n asChild?: boolean;\n className?: string;\n children: ReactNode;\n} & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'>;\n\nexport default function Link({\n variant = 'inline',\n asChild = false,\n className = '',\n children,\n ...rest\n}: LinkProps) {\n const cls = linkClass(variant, className);\n if (asChild && isValidElement(children)) {\n const child = children as ReactElement<{ className?: string }>;\n return cloneElement(child, {\n ...rest,\n className: `${cls} ${child.props.className ?? ''}`.trim(),\n });\n }\n return (\n <a className={cls} {...rest}>\n {children}\n </a>\n );\n}\n","// ロゴマーク(純粋 leaf UI)。LOOPHUB ブランドの「リング+3 ドット」マークに準拠(loophub #724)。\n// リング(ストローク)は @theme の text トークン(var(--color-text)=currentColor)を参照し、ライト/ダークで\n// 自動的に色が切り替わる。3 ドットの配色はデザイン指定 hex(coral/amber/blue)を使う(ブランド固定色)。\n// variant='row' は横並びマーク + showWordmark で \"LOOPHUB\" ワードマーク(Archivo/font-display)を並べる。\n// variant='cluster' は単体マーク(プロダクト切替チップ等の小さな箇所向け)。\nexport type LogoMarkVariant = 'row' | 'cluster';\n\nexport type LogoMarkProps = {\n variant?: LogoMarkVariant;\n // マークの一辺(px)。既定 20。\n size?: number;\n showWordmark?: boolean;\n // ワードマークの文字サイズ(px)。省略時は size から比例算出。\n wordmarkSize?: number;\n className?: string;\n};\n\n// デザイン指定のドット配色(coral / amber / blue)。ブランド固定色のため生 hex を使う。\nconst DOT_CORAL = '#FF5A36';\nconst DOT_AMBER = '#F5A524';\nconst DOT_BLUE = '#3B6FE0';\n\n// リング+3 ドットの単体マーク。stroke は currentColor(=var(--color-text))でテーマ追従する。\nfunction Mark({ size }: { size: number }) {\n return (\n <svg\n aria-hidden=\"true\"\n width={size}\n height={size}\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"text-text\"\n >\n <circle cx=\"24\" cy=\"24\" r=\"13\" stroke=\"currentColor\" strokeWidth=\"4\" fill=\"none\" />\n <circle cx=\"24\" cy=\"11\" r=\"6.5\" fill={DOT_CORAL} />\n <circle cx=\"35.3\" cy=\"30.5\" r=\"6.5\" fill={DOT_AMBER} />\n <circle cx=\"12.7\" cy=\"30.5\" r=\"6.5\" fill={DOT_BLUE} />\n </svg>\n );\n}\n\nexport default function LogoMark({\n variant = 'row',\n size = 20,\n showWordmark = false,\n wordmarkSize,\n className = '',\n}: LogoMarkProps) {\n if (variant === 'cluster') {\n return (\n <span className={`inline-flex ${className}`.trim()}>\n <Mark size={size} />\n </span>\n );\n }\n\n const wordmarkPx = wordmarkSize ?? Math.round(size * 0.85);\n\n return (\n <span className={`inline-flex items-center gap-2 ${className}`.trim()}>\n <Mark size={size} />\n {showWordmark && (\n <span\n className=\"font-display font-extrabold uppercase tracking-tight text-text\"\n style={{ fontSize: wordmarkPx }}\n >\n LOOPHUB\n </span>\n )}\n </span>\n );\n}\n","import type { ReactNode } from 'react';\n\n// DS の Lozenge(純粋 leaf UI)。claude design \"INSESSION Design System\" の Lozenge 仕様に準拠(#463)。\n// 状態やメタ情報の小ラベル(LIVE / PENDING / REC / BETA 等)。モノスペース大文字・塗り控えめ・非操作。\n// StatusBadge(点 + ラベルの枠付きピル。継続的な状態)とは用途が別で、こちらは mono の状態タグ。\n// tone でセマンティック色を切替える。dot で先頭に同色ドットを出す。i18n は持たない。\n// 塗りは視認性確保のため -surface-strong 系トークンを使う(#765)。\nexport type LozengeTone = 'success' | 'warning' | 'accent' | 'info' | 'neutral';\n\nconst TONE: Record<LozengeTone, string> = {\n success: 'text-success bg-success-surface-strong',\n warning: 'text-warning bg-warning-surface-strong',\n accent: 'text-accent bg-tint-22',\n info: 'text-info bg-info-surface-strong',\n // neutral は tint(accent 色相)ではなく中立の面を使う。tint を濃くすると accent tone と\n // 見分けが付かなくなるため、面は surface-3・文字は text-text で濃度を確保する(#765)。\n neutral: 'text-text bg-surface-3',\n};\nconst DOT: Record<LozengeTone, string> = {\n success: 'bg-success',\n warning: 'bg-warning',\n accent: 'bg-accent',\n info: 'bg-info',\n neutral: 'bg-text-faint',\n};\n\nexport type LozengeProps = {\n tone?: LozengeTone;\n // 先頭に同色のドットを出す(LIVE 等の含意)。\n dot?: boolean;\n children: ReactNode;\n className?: string;\n};\n\nexport default function Lozenge({\n tone = 'neutral',\n dot = false,\n children,\n className = '',\n}: LozengeProps) {\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-pill px-2.5 py-1 font-mono text-xs font-semibold uppercase tracking-pill ${TONE[tone]} ${className}`.trim()}\n >\n {dot && <span className={`h-1.5 w-1.5 rounded-pill ${DOT[tone]}`} aria-hidden=\"true\" />}\n {children}\n </span>\n );\n}\n","import type { ReactNode } from 'react';\n\n// ポップオーバーの上に載せるメニュー(純粋 leaf UI)。space-topbar のステージ切替 /\n// notification-item / user-menu 等で重複していたメニュー行を DS に集約する。\n// Popover(面・外側クリック・Esc)と組み合わせて使う想定。i18n は持たない。\n\nexport type MenuProps = {\n children: ReactNode;\n ariaLabel?: string;\n className?: string;\n};\n\n// 行のコンテナ。ul をリセットして縦積みにする。\nexport function Menu({ children, ariaLabel, className = '' }: MenuProps) {\n return (\n <ul\n role=\"menu\"\n aria-label={ariaLabel}\n className={`m-0 flex list-none flex-col gap-0.5 p-0 ${className}`.trim()}\n >\n {children}\n </ul>\n );\n}\n\nexport type MenuItemProps = {\n onSelect: () => void;\n children: ReactNode;\n // 行頭のアイコン等。\n icon?: ReactNode;\n // 行末の付随要素(チェック・実行中ドット等)。\n trailing?: ReactNode;\n // 選択中(アクセント色 + aria-checked)。radio/checkbox 的なメニューで使う。\n active?: boolean;\n // 破壊的操作(ログアウト・削除等)。危険色で表示する。\n danger?: boolean;\n disabled?: boolean;\n // 既定 'menuitem'。選択状態を持つなら 'menuitemradio' / 'menuitemcheckbox'。\n role?: 'menuitem' | 'menuitemradio' | 'menuitemcheckbox';\n};\n\n// 新 DS(#463) Menu 行: radius-md / gap 13 / padding 11x13 / font 15。hover は surface-hover、\n// 選択中は live(green) の tint 面 + green テキスト。\nconst ROW =\n 'flex w-full items-center gap-[13px] rounded-md border-none bg-transparent px-[13px] py-[11px] text-left text-[15px] shadow-none transition-colors duration-(--dur-fast) cursor-pointer disabled:opacity-(--disabled-opacity) disabled:cursor-not-allowed';\n\nexport function MenuItem({\n onSelect,\n children,\n icon,\n trailing,\n active = false,\n danger = false,\n disabled = false,\n role = 'menuitem',\n}: MenuItemProps) {\n const tone = danger\n ? 'text-danger enabled:hover:bg-danger-surface'\n : active\n ? 'text-success bg-[color-mix(in_srgb,var(--color-success)_10%,transparent)]'\n : 'text-text enabled:hover:bg-surface-hover';\n return (\n <li>\n <button\n type=\"button\"\n role={role}\n aria-checked={role === 'menuitem' ? undefined : active}\n disabled={disabled}\n className={`${ROW} ${tone}`}\n onClick={onSelect}\n >\n {icon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n {trailing && <span className=\"shrink-0\">{trailing}</span>}\n </button>\n </li>\n );\n}\n","import {\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { useDismiss } from './use-dismiss.ts';\n\n// ポップオーバーの共通基盤(純粋 leaf UI)。トリガーとフローティングパネルを相対配置でまとめ、\n// 外側クリック / Escape での close を内包する(useDismiss)。個別に mousedown+keydown を張って\n// いた space-topbar / notification-bell / message-action-bar / sticker-picker / video-search-box を\n// 将来この一本へ寄せられる API にする。open 制御は呼び出し側(controlled)。i18n は持たない。\nexport type PopoverPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';\n\nexport type PopoverProps = {\n open: boolean;\n onClose: () => void;\n // 開閉トリガー(呼び出し側が open をトグルするボタン等)。相対配置の基準にもなる。\n trigger: ReactNode;\n children: ReactNode;\n placement?: PopoverPlacement;\n ariaLabel?: string;\n // role。メニューを載せるときは 'menu'(既定)、それ以外の内容は 'dialog' 等に。\n role?: string;\n // パネル(浮く面)に足す追加クラス(幅・最大高さ等の文脈調整用)。\n panelClassName?: string;\n // パネルの影ユーティリティ。既定は DS の popover 影(UserMenu/🧩 スイッチャーと同じ。#867)。\n panelShadow?: string;\n // 既定の内側 padding(p-3) を出すか。ヘッダー/リストが独自 padding を持つ通知センターのような\n // パネルは false にして呼び出し側で表現する(既定 true = 従来挙動)。\n panelPadding?: boolean;\n // 既定の最大高さ(max-h-80) + 内部スクロールを出すか。呼び出し側で独自の高さ/内部スクロール\n // (例: ヘッダー固定+リストだけスクロール)を組みたい場合は false にする(既定 true = 従来挙動)。\n panelScroll?: boolean;\n // max-sm でトリガー追従(placement アンカー)をやめ、position:fixed + 左右対称ガター(12px)で\n // ビューポートに固定するモバイルシート表示にする。上端はトリガー直下に合わせる。sm 以上は\n // 従来どおり placement 通りのトリガー追従。既定 false(他 consumer の従来挙動は不変)。\n mobileSheet?: boolean;\n // true でパネルを createPortal で document.body 直下へ出し、position:fixed +\n // トリガーの getBoundingClientRect() 実測で配置する。overflow:hidden/auto な親(例:\n // スクロールする一覧パネル)にクリップされたくない場合に使う(#885)。既定 false = 従来の\n // absolute(トリガー追従・親に内包される)挙動を完全維持。mobileSheet と同時指定時は\n // mobileSheet を優先する(モバイルの固定シート表示はそのまま。破壊しない)。\n portal?: boolean;\n closeOnEsc?: boolean;\n closeOnOutside?: boolean;\n};\n\n// 8px オフセットは下の PORTAL_OFFSET_PX と値を揃えてある(非 portal 版と portal 版で見た目の\n// 間隔を一致させるため)。どちらか一方を変えたら必ずもう一方も変えること。\nconst PLACEMENT: Record<PopoverPlacement, string> = {\n 'bottom-start': 'top-[calc(100%+8px)] left-0',\n 'bottom-end': 'top-[calc(100%+8px)] right-0',\n 'top-start': 'bottom-[calc(100%+8px)] left-0',\n 'top-end': 'bottom-[calc(100%+8px)] right-0',\n};\n\n// パネル本体の見た目(面・境界・角丸・入場アニメ)。位置と影は呼び出し側の設定で足す。z-index は\n// portal 有無で変わる(下記 zIndexClass)ためここには含めない。\n// max-w は mobileSheet の左右ガター(12px×2=24px)と揃え、mobileSheet を使わない呼び出し側でも\n// 極小幅のビューポートで横にはみ出さないようにする(#867)。\nconst PANEL_BASE =\n 'min-w-[220px] max-w-[calc(100vw-24px)] bg-surface border border-solid border-border-strong rounded-card animate-[card-in_var(--dur-base)_var(--ease-spring)_both]';\n\n// portal 時の位置計算に使う定数(px)。トリガーとの間隔・ビューポート端からの最低ガター。\n// PORTAL_OFFSET_PX は上の PLACEMENT の calc(100%+8px) と値を揃えてある。片方を変えたら\n// もう片方も変えること。\nconst PORTAL_OFFSET_PX = 8;\nconst PORTAL_GUTTER_PX = 12;\n\n// portal 時のフォーカス移動(open時の最初のfocusable探索・下記フォーカストラップ)で共通して使う\n// focusable 要素セレクタ。1箇所にまとめて open/Tab トラップの判定基準がズレないようにする。\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])';\n\n// 指摘5(#885 レビュー3周目): トリガーを直接内包する、overflow がクリップを起こしうる祖先\n// (overflowX/overflowY が visible 以外)を探す。見つからなければビューポート自体を\n// クリップ境界とみなす(null)。document.body/html はクリップ元として扱わない(ページ全体の\n// スクロールはこれまで通りビューポート基準)。open のたびに一度だけ呼べば足りる\n// (トリガーとその祖先の DOM 構造は開いている間変わらない前提)。\n//\n// 指摘5(#885 レビュー4周目): このループは overflow だけを見ており、`position: fixed`(や、\n// containing block にならない `absolute` )の祖先を無視している。position:fixed な要素は\n// ビューポートを基準に配置され、祖先の overflow:hidden にクリップされない仕様のため、\n// そのような祖先を「クリップ境界」と誤認すると、無関係な祖先の矩形とトリガーが交差しなく\n// なるたびに理由なくパネルが消えてしまう。position:fixed に到達したらそこで探索を打ち切り\n// 「クリップ元なし(ビューポート基準)」として扱う。\n// なお、このループは「最も近いクリッパー1つ」しか見ないため、入れ子になった複数の overflow\n// クリッパー(祖先A の中に祖先B があり、どちらも独立してクリップしうるケース)は検出できない\n// (現状の唯一の portal consumer は `.cp-popover` 自身が最初に見つかるクリッパーで探索が\n// そこで止まるため未到達。将来 portal consumer が増えたら要検討)。\nfunction getScrollClipAncestor(el: Element | null): HTMLElement | null {\n let node = el?.parentElement ?? null;\n while (node && node !== document.body && node !== document.documentElement) {\n const style = getComputedStyle(node);\n if (style.position === 'fixed') return null;\n if (style.overflowY !== 'visible' || style.overflowX !== 'visible') return node;\n node = node.parentElement;\n }\n return null;\n}\n\nexport default function Popover({\n open,\n onClose,\n trigger,\n children,\n placement = 'bottom-start',\n ariaLabel,\n role = 'menu',\n panelClassName = '',\n panelShadow = 'shadow-popover',\n panelPadding = true,\n panelScroll = true,\n mobileSheet = false,\n portal = false,\n closeOnEsc = true,\n closeOnOutside = true,\n}: PopoverProps) {\n const ref = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n // 指摘6(#885 レビュー3周目): portal でパネルが document.body 直下へ移り、トリガーの直後の\n // 兄弟でなくなる(DOM 隣接性が失われる)ため、支援技術へ関連を明示するための安定 id。\n // useId() はコンポーネントインスタンスごとに一意なので複数の Popover が同時に開いても衝突しない。\n const panelId = useId();\n // mobileSheet はトリガー追従をやめる既存挙動なので、同時指定時は mobileSheet を優先する\n // (#885。portal はトリガー追従の実測配置なので mobileSheet の固定シート表示とは両立しない)。\n const effectivePortal = portal && !mobileSheet;\n\n // 外側クリック判定: 通常はラッパー(トリガー+パネル)の ref 1つで足りるが、portal 時はパネルが\n // document.body 直下に出て DOM 上ラッパーの子でなくなるため、パネル自身の ref も渡して\n // 「どちらにも含まれないクリック」だけを外側と判定する(use-dismiss.ts の二重 ref containment)。\n const dismissRefs = useMemo(() => (effectivePortal ? [ref, panelRef] : ref), [effectivePortal]);\n useDismiss(open, dismissRefs, onClose, { closeOnEsc, closeOnOutside });\n\n // モバイルシートは position:fixed なので上端をトリガー直下に固定するため実測する\n // (トップバー高さがページで異なり静的値を置けない)。max-sm 以外・非表示時は使わない。\n const [sheetTop, setSheetTop] = useState(0);\n useLayoutEffect(() => {\n if (!open || !mobileSheet) return undefined;\n const measure = () => {\n const el = ref.current;\n if (el) setSheetTop(el.getBoundingClientRect().bottom + 8);\n };\n measure();\n window.addEventListener('resize', measure);\n return () => window.removeEventListener('resize', measure);\n }, [open, mobileSheet]);\n\n // portal 時の位置(fixed の top/left)。トリガーの実測 rect + パネル自身の実測サイズから\n // placement の意味(absolute 版と同じ: bottom/top はトリガーとの上下関係、start/end は\n // 左右どちらの端を揃えるか)を再現し、ビューポート外にはみ出す場合はガター分クランプする。\n // null の間はまだ未測定 = 画面外(見えない位置)に置いて初期フレームのちらつきを防ぐ。\n const [portalPos, setPortalPos] = useState<{ top: number; left: number } | null>(null);\n // 指摘5(#885 レビュー3周目): トリガーが自身を内包するスクロールコンテナ(例: 参加者一覧の\n // .cp-popover。max-height+overflow-y:auto)の外へスクロールで隠れたかどうか。portal 化で\n // 親の overflow によるクリップから popover 自体は解放された結果、トリガーだけがクリップされて\n // 見えなくなっても popover は最後に計算した位置に浮いたまま追従し続けてしまう(修正前の\n // portal化が新たに持ち込んだ退行。トリガーごと隠れていた従来の absolute 版には存在しない)。\n const [triggerClipped, setTriggerClipped] = useState(false);\n useLayoutEffect(() => {\n if (!open || !effectivePortal) {\n setPortalPos(null);\n setTriggerClipped(false);\n return undefined;\n }\n // クリップ境界は開いている間の DOM 構造では変わらない前提なので、スクロールのたびではなく\n // 開いたときに一度だけ特定する(getComputedStyle は高コストなので rAF ループ内で毎回呼びたくない)。\n const clipAncestor = getScrollClipAncestor(ref.current);\n const compute = () => {\n const triggerEl = ref.current;\n const panelEl = panelRef.current;\n if (!triggerEl || !panelEl) return;\n const triggerRect = triggerEl.getBoundingClientRect();\n // offsetWidth/offsetHeight は border-box のレイアウト値で CSS transform を含まない。\n // getBoundingClientRect() だと PANEL_BASE の入場アニメ(card-in: scale(0.97)から開始)の\n // 影響でマウント直後の実寸より小さい値を掴んでしまい、位置がズレたまま固定される(#885)。\n const panelWidth = panelEl.offsetWidth;\n const panelHeight = panelEl.offsetHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n // 指摘5: トリガーがクリップ境界(スクロールコンテナ、無ければビューポート)と全く重ならなく\n // なったら「見えなくなった」とみなす。部分的にでも重なっていれば従来通り可視として扱う\n // (グリッド境界ぎりぎりで揺れるだけの一瞬をチラつかせないため)。\n const clipRect = clipAncestor\n ? clipAncestor.getBoundingClientRect()\n : { top: 0, left: 0, right: vw, bottom: vh };\n const clipped =\n triggerRect.bottom <= clipRect.top ||\n triggerRect.top >= clipRect.bottom ||\n triggerRect.right <= clipRect.left ||\n triggerRect.left >= clipRect.right;\n setTriggerClipped((prev) => (prev === clipped ? prev : clipped));\n\n let top = placement.startsWith('bottom')\n ? triggerRect.bottom + PORTAL_OFFSET_PX\n : triggerRect.top - PORTAL_OFFSET_PX - panelHeight;\n let left = placement.endsWith('end') ? triggerRect.right - panelWidth : triggerRect.left;\n\n const maxLeft = Math.max(PORTAL_GUTTER_PX, vw - panelWidth - PORTAL_GUTTER_PX);\n const maxTop = Math.max(PORTAL_GUTTER_PX, vh - panelHeight - PORTAL_GUTTER_PX);\n left = Math.min(Math.max(left, PORTAL_GUTTER_PX), maxLeft);\n top = Math.min(Math.max(top, PORTAL_GUTTER_PX), maxTop);\n\n // 値が変わらないなら前の参照を返し、無変化の再レンダリングを避ける(#885)。capture:true の\n // window scroll は文書内のあらゆるスクロールを拾うため、これが無いと無関係なスクロールの\n // たびに毎回新しいオブジェクトで再レンダリングが走ってしまう。\n setPortalPos((p) => (p && p.top === top && p.left === left ? p : { top, left }));\n };\n compute();\n // resize/scroll は rAF で間引く(#885)。scroll は capture:true のため文書内のあらゆる\n // スクローラ(チャットログ・キュー一覧・自パネルの overflow-y:auto 等)の全スクロールを拾い、\n // 素通しだと compute() のレイアウト計測(getBoundingClientRect 等)がイベントの数だけ走って\n // しまう。同一フレーム内の複数発火を1回のcompute()にまとめる。\n let raf = 0;\n const schedule = () => {\n if (raf) return;\n raf = requestAnimationFrame(() => {\n raf = 0;\n compute();\n });\n };\n window.addEventListener('resize', schedule);\n window.addEventListener('scroll', schedule, true);\n // パネル自身のサイズ変化(#885)。fetch解決前後でパネルの内容が差し替わり高さが変わる\n // consumer(MemberProfileCard: ローディング表示→取得後のbio/バッジ入りカード)があり、\n // それは resize/scroll のどちらのイベントも発生させない。ResizeObserver でパネル本体の\n // border-box 変化を直接観測し、変化のたびに実測し直して top/left を追従させる。これが無いと\n // 計測時の小さい高さでクランプ判定が確定してしまい、後から伸びた分だけビューポート外へ\n // はみ出す(bottom-*)/トリガーを覆う(top-*)まま固定されてしまう。初回位置を1フレーム遅らせ\n // ないよう、ResizeObserver のコールバックは schedule ではなく compute を直接呼ぶ。\n const panelEl = panelRef.current;\n let ro: ResizeObserver | undefined;\n if (panelEl) {\n ro = new ResizeObserver(compute);\n ro.observe(panelEl);\n }\n return () => {\n window.removeEventListener('resize', schedule);\n window.removeEventListener('scroll', schedule, true);\n ro?.disconnect();\n if (raf) cancelAnimationFrame(raf);\n };\n }, [open, effectivePortal, placement]);\n\n // 指摘6(#885 レビュー3周目): portal 時は open のたびにパネル内へ focus を移し、閉じたら\n // トリガーへ戻す。旧実装(非 portal)はパネルがトリガー直後の兄弟だったため、アバターボタンから\n // Tab するだけで自然にカード内(フォローボタン等)へ入れたが、portal 化で document.body 末尾に\n // 移った結果 Tab がページ末尾まで飛ぶようになった(#885 で新たに生じた退行)。role=\"menu\"(既定)\n // の非 portal consumer 5箇所(forum-switcher / app-shell / notification-bell /\n // Popover.stories / admin icon-rail)はいずれも portal を指定していないため、この effect は\n // effectivePortal でガードして portal consumer(現状 MemberProfileCard の role=\"dialog\" のみ)\n // に限定し、既存挙動を一切変えない。\n //\n // open/close と「実際に focus を移す」を2つの effect に分けている理由: 開いた直後の1フレーム目は\n // portalPos がまだ null で panelStyle が visibility:hidden(#885 の未測定時フォールバック)を\n // 返す。visibility:hidden の要素は仕様上フォーカス対象にならず focus() が黙って失敗するため、\n // portalPos が確定してから(=可視になってから)focus を移す必要がある。ただし portalPos は\n // リサイズ/スクロールのたびに再計算され続けるので、そのたびに focus し直すとカーソルが\n // カクカク奪われる。そこで「開いていた間に一度だけ動かす」を focusMovedRef で保証する。\n const previousFocusRef = useRef<HTMLElement | null>(null);\n const focusMovedRef = useRef(false);\n useLayoutEffect(() => {\n if (!open || !effectivePortal) return undefined;\n previousFocusRef.current = document.activeElement as HTMLElement | null;\n focusMovedRef.current = false;\n return () => {\n // 閉じたときトリガー(またはトリガー内の元々フォーカスされていた要素)へ戻す。フォーカスが\n // body へ落ちると Tab 順が失われるため。ただし「フォーカスがパネル内にあった場合だけ」に\n // 限定する必要がある(指摘2 #885 レビュー4周目)。cleanup 実行時点でパネルは既に DOM から\n // 削除済みのため、パネル内にフォーカスがあったなら document.activeElement は body に\n // 落ちている。この判定を欠くと、ユーザーが MiniProfile を開いたまま Tab/クリックで\n // 無関係な要素(例: チャット入力欄)へ移った後、consumer 側の都合で popover が閉じた\n // (例: 対象メンバーの退室で expandedId がクリアされる)ときに、入力中のフォーカスを\n // 奪ってトリガーへ引き戻してしまう。Radix / react-aria と同じ判定。\n const prev = previousFocusRef.current;\n if (focusMovedRef.current && document.activeElement === document.body && prev?.isConnected) {\n prev.focus({ preventScroll: true });\n }\n previousFocusRef.current = null;\n };\n }, [open, effectivePortal]);\n useLayoutEffect(() => {\n if (!open || !effectivePortal || !portalPos || triggerClipped || focusMovedRef.current)\n return undefined;\n const panelEl = panelRef.current;\n if (!panelEl) return undefined;\n // フォーカス可能な最初の子要素(フォローボタン等)へ入れる。無ければパネル自身(tabIndex=-1\n // を付けてある)へ focus し、少なくとも Escape でパネルを閉じられる状態にする。\n const focusable = panelEl.querySelector<HTMLElement>(FOCUSABLE_SELECTOR);\n (focusable ?? panelEl).focus({ preventScroll: true });\n // 指摘4(#885 レビュー4周目): focus() の成否を実際に確認してからラッチする。triggerClipped\n // (visibility:hidden で focus 不可)のガードを上に足したので現行 UI では通らないが、将来\n // programmatic open 等で portalPos 確定時点でも focus に失敗しうるケースに備え、\n // 「本当にパネル内へ移せた場合だけ」フラグを立てる(失敗時にラッチされたままだと、後から\n // 可視になっても二度と focus が入らなくなる)。\n focusMovedRef.current = panelEl.contains(document.activeElement);\n return undefined;\n }, [open, effectivePortal, portalPos, triggerClipped]);\n\n // 「出口」のフォーカス退行(#885)への対処: portal 化でパネルが document.body 末尾に移った\n // ため、パネル内最後の要素から Tab すると(パネルの次にDOM上何もない=)ブラウザUIへ抜け、\n // 逆にパネル先頭から Shift+Tab してもトリガーへ戻らない(非 portal 時代はパネルがトリガー\n // 直後の兄弟だったため自然につながっていた)。\n //\n // 案A(パネル内フォーカストラップ)を採用し、案B(Tabで抜けたらトリガーへ戻す)は採らなかった。\n // 理由: 現状の唯一の portal consumer(MemberProfileCard)は role=\"dialog\" で、かつ「参加者一覧\n // ポップオーバー(非 portal)がまだ開いている入れ子」の中に浮く。案Bだとパネル最後から Tab で\n // 参加者一覧ポップオーバーのトリガー(アバターボタン)へ戻ってしまい、続けて Tab すると参加者\n // 一覧の次の項目 → …と、開いている dialog の外の要素へフォーカスが漏れてしまう(WAI-ARIA の\n // dialog パターンとして期待される「閉じるまで dialog 内に留まる」に反する)。案Aならその漏れが\n // 起きず、Esc/外側クリックで MiniProfile だけ閉じる二段階 dismiss(既存)とも自然に噛み合う。\n // role=\"menu\"(既定)の非 portal consumer 5箇所は portal を指定しないため effectivePortal が\n // false のまま=この effect も handleTabTrap も一切関与しない(挙動不変)。\n //\n // aria-modal=\"true\" はあえて付けない: 本当に背景(参加者一覧)を inert にしているわけではなく\n // (裏の一覧は依然スクロール・フォーカス可能な要素を持つ)、trap しているのは Tab キー操作の\n // 範囲だけなので、aria-modal を付けると支援技術に「背景は完全に無効化されている」という\n // 不正確な情報を伝えてしまう。\n const handlePanelKeyDown = (e: ReactKeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'Tab') return;\n const panelEl = panelRef.current;\n if (!panelEl) return;\n const focusables = panelEl.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);\n if (focusables.length === 0) {\n // focusable な子が無い(パネル自身に tabIndex=-1 で focus している)場合は Tab 自体を\n // 無効化し、パネル自身に留める。\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey) {\n // 先頭要素、または(何らかの理由で)パネル外へフォーカスが逃げていた場合は末尾へ回す。\n if (active === first || !panelEl.contains(active)) {\n e.preventDefault();\n last.focus({ preventScroll: true });\n }\n } else if (active === last || !panelEl.contains(active)) {\n e.preventDefault();\n first.focus({ preventScroll: true });\n }\n };\n\n // 位置決め。通常は absolute でトリガー追従。mobileSheet は max-sm で fixed + 左右ガター、\n // sm 以上で placement 通りの absolute に戻す(sm: プレフィックスで上書き)。portal は\n // fixed + 上記 portalPos の実測値を inline style で当てる(クラスでは表現しない)。\n const smAnchor = PLACEMENT[placement]\n .split(' ')\n .map((c) => `sm:${c}`)\n .join(' ');\n const positioning = mobileSheet\n ? `fixed top-(--popover-sheet-top) left-3 right-3 w-auto sm:absolute sm:left-auto ${smAnchor}`\n : effectivePortal\n ? 'fixed'\n : `absolute ${PLACEMENT[placement]}`;\n\n // z-index: portal は body 直下に出るため、クリップ元の親パネル自身(参加者パネル等。\n // --z-dropdown を使用)より確実に手前へ出す専用トークンを使う。既存の z-(--z-dropdown) と\n // 同じ CSS変数参照記法ではなく `z-[var(--z-popover-portal,35)]` という\n // 任意値記法にしてあるのは、このパッケージの theme.css を import しない consumer(例:\n // products/insession/apps/help は自前で z スケールを定義し theme.css を読み込まない)で\n // --z-popover-portal が未定義になり、無指定の var() が invalid → z-index:auto に静かに\n // 落ちて背面に沈む事故を防ぐため(#885)。フォールバック値 35 は theme.css の\n // --z-popover-portal の定義値と揃えてある。\n const zIndexClass = effectivePortal ? 'z-[var(--z-popover-portal,35)]' : 'z-(--z-dropdown)';\n\n // 指摘5(#885): クリップされた間は「隠す」(visibility:hidden + pointer-events:none)を選び、\n // onClose() は呼ばない。理由: パネル内スクロールでトリガーが一瞬クリップ境界をまたぐたびに\n // onClose() すると、スクロールを少し戻しただけでは再表示されず(呼び出し側の state は既に\n // closed)ユーザーがもう一度アバターをクリックし直す必要が生じて体感が悪い。隠すだけにすれば\n // スクロールで戻ったときに compute() が自動で visibility を復帰させ、シームレスに再表示できる。\n // visibility:hidden の要素は仕様上ヒットテスト対象外(クリックは背後の要素へ通る)だが、念のため\n // pointer-events:none も明示して「隠れている間クリックを吸わない」ことを保証する。\n const panelStyle: CSSProperties | undefined = mobileSheet\n ? ({ '--popover-sheet-top': `${sheetTop}px` } as CSSProperties)\n : effectivePortal\n ? portalPos\n ? triggerClipped\n ? {\n top: portalPos.top,\n left: portalPos.left,\n visibility: 'hidden',\n pointerEvents: 'none',\n }\n : { top: portalPos.top, left: portalPos.left }\n : { top: -9999, left: -9999, visibility: 'hidden', pointerEvents: 'none' }\n : undefined;\n\n const panel = open && (\n <div\n ref={panelRef}\n // 指摘6: portal 時だけ安定 id を振り、下のトリガー側ラッパーの aria-owns から参照させる。\n // 非 portal 時は DOM 隣接性がそのまま関連を表すので id は付けない(従来どおり)。\n id={effectivePortal ? panelId : undefined}\n // 指摘6: portal 時はフォーカス可能な子が無いケースでもパネル自身へ focus できるように\n // tabIndex=-1 を付ける(プログラム的 focus のみ許可。Tab キーでは踏まない)。\n tabIndex={effectivePortal ? -1 : undefined}\n role={role}\n aria-label={ariaLabel}\n // 「出口」フォーカストラップ(上記コメント参照)。portal 時だけ Tab/Shift+Tab をパネル内で\n // ループさせる。非 portal consumer は effectivePortal===false のため onKeyDown 自体が\n // undefined になり一切影響しない。\n onKeyDown={effectivePortal ? handlePanelKeyDown : undefined}\n className={`${PANEL_BASE} ${zIndexClass} ${panelScroll ? 'max-h-80 overflow-y-auto' : ''} ${panelPadding ? 'p-3' : ''} ${positioning} ${panelShadow} ${panelClassName}`.trim()}\n style={panelStyle}\n >\n {children}\n </div>\n );\n\n return (\n <div\n className=\"relative inline-flex\"\n ref={ref}\n // 指摘6: portal でパネルが document.body 直下へ出て DOM 上トリガーの兄弟でなくなるため、\n // aria-owns でトリガー(を含むこのラッパー)とパネルの関連を支援技術へ明示する。\n aria-owns={effectivePortal && open ? panelId : undefined}\n >\n {trigger}\n {effectivePortal ? (panel ? createPortal(panel, document.body) : null) : panel}\n </div>\n );\n}\n","import { type RefObject, useEffect } from 'react';\n\ntype Ref = RefObject<HTMLElement | null>;\n\n// 「外側クリック / Escape で閉じる」を一箇所にまとめた共通フック(純粋 leaf)。\n// Popover / Menu / Dropdown 系の個別実装(space-topbar / notification-bell /\n// message-action-bar 等)で毎回書かれていた mousedown + keydown の登録・解除を集約する。\n// open が false の間はリスナーを張らない(無駄な購読を避ける)。\n//\n// ref は単一 or 配列を受け付ける。**createPortal で本体を document.body へ出す**ケース\n// (message-action-bar / sticker-picker / chat-participants-bar)では、トリガーと\n// ポップオーバー本体が DOM 上で親子でなくなるため、両方の ref を渡して「どちらにも\n// 含まれないクリック」だけを外側と判定する(二重 ref containment)。ignore は\n// 「この target のときは閉じない」を追加指定するための述語(例: 上に別モーダルが開いている間、\n// .modal-backdrop クリックを無視する)。\n//\n// リスナーの張り先は「渡された ref の要素が属する document の window」から解決する\n// (既定は各要素の ownerDocument.defaultView、要素が無ければグローバル window)。\n// これにより、Document Picture-in-Picture のような別ドキュメントへ createPortal する\n// 消費側(例: PiP 内の StickerPicker)でも、そのウィンドウ自身の mousedown/keydown を\n// 正しく拾える(メインドキュメント側の消費側は ownerDocument が常に main document なので\n// 挙動は従来と完全に同一)。\nexport function useDismiss(\n open: boolean,\n ref: Ref | Ref[],\n onDismiss: () => void,\n options: {\n closeOnEsc?: boolean;\n closeOnOutside?: boolean;\n ignore?: (target: Node) => boolean;\n } = {},\n) {\n const { closeOnEsc = true, closeOnOutside = true, ignore } = options;\n useEffect(() => {\n if (!open) return undefined;\n const refs = Array.isArray(ref) ? ref : [ref];\n const win = refs.map((r) => r.current?.ownerDocument?.defaultView).find(Boolean) ?? window;\n const onDown = (e: MouseEvent) => {\n if (!closeOnOutside) return;\n const target = e.target as Node;\n if (ignore?.(target)) return;\n if (refs.some((r) => r.current?.contains(target))) return;\n onDismiss();\n };\n const onKey = (e: KeyboardEvent) => {\n if (closeOnEsc && e.key === 'Escape') onDismiss();\n };\n win.addEventListener('mousedown', onDown);\n win.addEventListener('keydown', onKey);\n return () => {\n win.removeEventListener('mousedown', onDown);\n win.removeEventListener('keydown', onKey);\n };\n }, [open, ref, onDismiss, closeOnEsc, closeOnOutside, ignore]);\n}\n","import { createContext, useContext } from 'react';\n\n// プロフィールモーダルをどこからでも開くための注入点(コールバックのみ。#637)。\n// UI leaf には「開く関数の型」だけを置き、実際に UserProfile を描画する Provider は\n// apps/web が供給する(UserProfile を持つ @in-session/account を import できるのは\n// apps/web 側のため。leaf(ui) は account を import しない=ui-is-leaf 制約を保つ)。\n// uid 未指定=自己プロフィール、uid 指定=他人の公開プロフィールを開く。\nexport type OpenProfile = (uid?: string) => void;\n\nconst noopOpenProfile: OpenProfile = () => {};\n\nexport const ProfileModalContext = createContext<OpenProfile>(noopOpenProfile);\n\n// 通知・フォロー一覧・参加者カード等の各導線から呼ぶ。Provider 未設定時は no-op。\nexport function useOpenProfile(): OpenProfile {\n return useContext(ProfileModalContext);\n}\n","import type { InputHTMLAttributes, ReactNode } from 'react';\nimport { useId } from 'react';\n\n// DS のラジオ(純粋 leaf UI)。claude design \"INSESSION Design System\" の Controls 仕様に準拠(#463)。\n// 22x22 の円 / 2px 枠。選択時は枠を text 色にし、中央に 10px の accent ドットを出す。\n// ネイティブ input を視覚的に隠し(a11y/フォーカス維持)、隣の span を状態で描画する。\nexport type RadioProps = {\n checked: boolean;\n label?: ReactNode;\n className?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'type'>;\n\nexport default function Radio({ checked, label, id, className = '', ...rest }: RadioProps) {\n const autoId = useId();\n const inputId = id ?? autoId;\n return (\n <label\n htmlFor={inputId}\n className={`inline-flex cursor-pointer select-none items-center gap-3 ${className}`.trim()}\n >\n <input id={inputId} type=\"radio\" checked={checked} className=\"peer sr-only\" {...rest} />\n <span\n className={`grid h-[22px] w-[22px] place-items-center rounded-pill border-2 border-solid transition-colors peer-focus-visible:shadow-focus ${\n checked ? 'border-text' : 'border-border-strong'\n }`}\n >\n <span\n className={`h-2.5 w-2.5 rounded-pill bg-accent transition-transform duration-(--dur-fast) ${\n checked ? 'scale-100' : 'scale-0'\n }`}\n />\n </span>\n {label != null && <span className=\"text-md text-text\">{label}</span>}\n </label>\n );\n}\n","import type { CSSProperties } from 'react';\n\n// 円形カウントダウンタイマー(純粋 leaf UI)。時間計算はしない — 呼び出し側が\n// secondsLeft/totalSeconds を毎フレーム渡すだけの純粋表示部品(リレーゲーム等の残り時間表示 #974)。\n// conic-gradient + mask でリングを描き(mask の #000 はアルファ用のクリップ指定でありトークン違反ではない)、\n// 中央に残り秒数 + caption(i18n は持たないため注入)を重ねる。urgent(secondsLeft <= urgentThreshold)\n// では accent 色へ切り替え、ゆっくり脈動させる。脈動の keyframes は insession-app の apps/web/src/style.css に定義\n// (このパッケージ自体は keyframes を持たない既存流儀。badge.tsx の pop-in / modal.tsx の card-in と同じ)。\n// prefers-reduced-motion は同ファイル末尾のグローバルルールで自動的に止まる(spinner.tsx と同じ扱い)。\nexport type RingTimerProps = {\n secondsLeft: number;\n totalSeconds: number;\n // 直径(px)。既定 118。\n size?: number;\n // secondsLeft がこれ以下で urgent 表示(accent 色 + 脈動)に切り替える。既定 10。\n urgentThreshold?: number;\n // 数字の下に出す小さい説明文言(i18n は持たないため注入。例「のこり秒」)。\n caption?: string;\n className?: string;\n};\n\nexport default function RingTimer({\n secondsLeft,\n totalSeconds,\n size = 118,\n urgentThreshold = 10,\n caption,\n className = '',\n}: RingTimerProps) {\n const urgent = secondsLeft <= urgentThreshold;\n const pct = totalSeconds > 0 ? Math.min(100, Math.max(0, (secondsLeft / totalSeconds) * 100)) : 0;\n const ringColor = urgent ? 'var(--color-accent)' : 'var(--color-mint)';\n const maskStyle: CSSProperties = {\n background: `conic-gradient(${ringColor} ${pct}%, var(--color-border) 0)`,\n WebkitMask: 'radial-gradient(closest-side, transparent 72%, #000 73%)',\n mask: 'radial-gradient(closest-side, transparent 72%, #000 73%)',\n };\n\n const wrapperClass = [\n 'relative inline-flex shrink-0 items-center justify-center rounded-pill',\n urgent ? 'animate-[ring-timer-urgent-pulse_1s_ease-in-out_infinite]' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={wrapperClass} style={{ width: size, height: size }}>\n <div className=\"absolute inset-0 rounded-pill\" style={maskStyle} aria-hidden=\"true\" />\n <div className=\"relative flex flex-col items-center justify-center\">\n <span\n className={`font-bold leading-none tabular-nums ${urgent ? 'text-accent' : 'text-text'}`}\n style={{ fontSize: Math.round(size * 0.28) }}\n >\n {Math.max(0, Math.round(secondsLeft))}\n </span>\n {caption && <span className=\"mt-1 text-2xs text-text-dim\">{caption}</span>}\n </div>\n </div>\n );\n}\n","import type { InputHTMLAttributes } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// 検索入力(純粋 leaf UI)。claude design \"INSESSION Design System\" 準拠(loophub #682)。\n// Input と同系の surface-2 面 + 1.5px border + radius-md + focus-within リング。左に search\n// アイコンを固定表示する(常時 search 固定なので Input の prefix とは別プリミティブにしてある)。\n// i18n は持たない(placeholder は呼び出し側が渡す)。\nexport type SearchFieldProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'className'> & {\n className?: string;\n};\n\nconst FIELD =\n 'flex items-center gap-2 bg-surface-2 border-[1.5px] border-solid border-border rounded-md px-3.5 py-2.5 transition-[border-color,box-shadow] duration-(--dur-fast) focus-within:border-info focus-within:shadow-focus';\nconst CONTROL =\n 'flex-1 min-w-0 border-none outline-none bg-transparent text-md text-text placeholder:text-text-faint';\n\nexport default function SearchField({ className = '', ...rest }: SearchFieldProps) {\n return (\n <div className={`${FIELD} ${className}`.trim()}>\n <Icon name=\"search\" size={16} className=\"shrink-0 text-text-faint\" />\n <input className={CONTROL} {...rest} />\n </div>\n );\n}\n","import { type ReactNode, useEffect, useState } from 'react';\nimport BottomSheet from './bottom-sheet.tsx';\nimport Icon, { type IconName } from './icons/icon.tsx';\nimport Modal from './modal.tsx';\n\n// 設定系モーダルの2ペイン外殻(純粋 leaf UI)。左にセクションナビ、右にそのセクションの中身。\n// スペース設定(space-core)とアカウント設定(account)が同じ nav 構造を各々でベタ書きしていたのを\n// ここに集約する(#842)。i18n はこのパッケージに持たないため、ラベルは全て props で注入する。\n//\n// 見た目は DS(INSESSION Design System)の components/panels/SplitModal に準拠する(#835)。\n// 左レールは DS の surface-2(repo では bg-elevated)の面 + 右境界線で、右ペイン(surface)とは\n// 面の段差で分かれる。アクティブ行は surface-3 + border + 本文色で、accent はアイコンにだけ乗せる\n// (行全体を accent で塗らない=「控えめ・洗練」の方針)。\n//\n// 広い画面: レール(既定214px) + コンテンツ の横並び。\n// 狭い画面: 横に並べると両方使えない幅になるため、レイアウトごと差し替えて\n// 「セクション一覧 → タップで詳細(戻る導線つき)」のドリルダウンにする。\n// ネイティブの設定アプリと同じ体験で、セクションが何個あっても破綻しない。\n\n// ドリルダウンに切り替えるビューポート幅の上限。タブレット〜狭いPCウィンドウでも\n// レール214px+本文の2カラムは窮屈なため 768px にしている(#861)。\nconst NARROW_MAX_WIDTH = 768;\n\nexport type SplitModalItem = {\n id: string;\n label: string;\n // 行頭に出すアイコン。DS ではレール・ドリルダウン一覧の両方で使う。\n icon?: IconName;\n};\n\nexport type SplitModalProps = {\n items: SplitModalItem[];\n // 選択中のセクション id。\n value: string;\n onSelect: (id: string) => void;\n // 右ペイン(選択中セクションの中身)。\n children: ReactNode;\n onClose: () => void;\n // nav の aria-label。\n navLabel: string;\n // レール上部の見出し(例「設定」)。省略すると見出し行を出さない。\n navTitle?: string;\n // レール下部に固定される補足文。\n navFooter?: ReactNode;\n // 右ペインの見出し。省略すると見出し行を出さない(children が自前で持つ場合)。\n title?: string;\n // 右ペイン見出しの下の説明文。\n description?: string;\n // 右ペイン下部のアクション行。省略時は行ごと出ない(設定は即時反映のため通常は省略する)。\n footer?: ReactNode;\n // ダイアログの aria-label。\n ariaLabel?: string;\n // × 閉じるボタンの aria ラベル。\n closeLabel?: string;\n // ドリルダウン詳細の「戻る」の aria ラベル。\n backLabel?: string;\n // 外殻を BottomSheet にする(モバイルのスペース固有機能。#581 6b)。既定は中央 Modal。\n asSheet?: boolean;\n // Modal 外殻の幅。\n width?: string;\n // 左レールの幅(border-box)。\n navWidth?: number;\n // 外殻に足す追加クラス。\n className?: string;\n // ドリルダウンに切り替える判定の上書き。省略時はビューポート幅で自動判定する。\n narrow?: boolean;\n};\n\n// ビューポートが狭いか。境界値は NARROW_MAX_WIDTH(呼び出し側で明示的に上書きしない限り)。\n//\n// matchMedia の change だけに頼らないのは、iframe を属性でリサイズすると matches は変わるのに\n// change イベントが発火しないため(プレビュー/埋め込み環境で切り替わらなくなる)。\n// resize と ResizeObserver を併せて張る。\nfunction useNarrowViewport(maxWidth: number) {\n const [narrow, setNarrow] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined') return undefined;\n const sync = () => setNarrow(window.innerWidth <= maxWidth);\n sync();\n const mq = window.matchMedia?.(`(max-width: ${maxWidth}px)`);\n mq?.addEventListener('change', sync);\n window.addEventListener('resize', sync);\n const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(sync) : null;\n ro?.observe(document.documentElement);\n return () => {\n mq?.removeEventListener('change', sync);\n window.removeEventListener('resize', sync);\n ro?.disconnect();\n };\n }, [maxWidth]);\n return narrow;\n}\n\nexport default function SplitModal({\n items,\n value,\n onSelect,\n children,\n onClose,\n navLabel,\n navTitle,\n navFooter,\n title,\n description,\n footer,\n ariaLabel,\n closeLabel,\n backLabel,\n asSheet = false,\n width = 'min(760px, 94vw)',\n navWidth = 214,\n className = '',\n narrow,\n}: SplitModalProps) {\n const autoNarrow = useNarrowViewport(NARROW_MAX_WIDTH);\n const isNarrow = narrow ?? autoNarrow;\n // ドリルダウンで詳細を開いているか。広い画面へ戻ったら一覧状態に畳んでおく\n // (次に狭くなったときに一覧から始まる)。\n const [drilled, setDrilled] = useState(false);\n useEffect(() => {\n if (!isNarrow) setDrilled(false);\n }, [isNarrow]);\n\n const current = items.find((it) => it.id === value);\n\n const closeButton = closeLabel ? (\n <button\n type=\"button\"\n aria-label={closeLabel}\n title={closeLabel}\n onClick={onClose}\n // legacy の button ベーススタイルが左右 padding を持つため p-0 で潰す。潰さないと\n // ボタンが横に広がったうえ、フレックス収縮でアイコンの svg が幅0になり見えなくなる。\n className=\"inline-flex h-[30px] w-[30px] shrink-0 items-center justify-center rounded-chip border-none bg-transparent p-0 text-text-dim cursor-pointer [&>svg]:shrink-0 enabled:hover:bg-surface-hover enabled:hover:text-text\"\n >\n <Icon name=\"close\" size={19} />\n </button>\n ) : null;\n\n // 右ペインの見出し行(DS の sm-head)。title を渡さない消費側でも × は要るので、\n // その場合は×だけの右寄せ行として描画する。\n const paneHead =\n title || closeButton ? (\n <div className=\"flex shrink-0 items-start justify-between gap-3\">\n {title ? (\n <div className=\"min-w-0\">\n <h4 className=\"m-0 text-lg font-extrabold text-text\">{title}</h4>\n {description && (\n // max-w-[52ch] は意図的な据え置き(#950)。可読な行長(1行あたり文字数)を確保する\n // ための「文字数」基準の制約で、px/rem のスケールトークンに載せる性質の値ではない\n // (52ch は一般的な可読上限の目安。テキストコンテンツ量に応じた相対値なので\n // トークン化しても再利用の意味が薄い)。\n <p className=\"mt-1.5 mb-0 max-w-[52ch] text-[13px] leading-relaxed text-text-dim\">\n {description}\n </p>\n )}\n </div>\n ) : (\n <span />\n )}\n {closeButton}\n </div>\n ) : null;\n\n // 狭い画面: セクション一覧(詳細は開いていない)\n const list = (\n <div className=\"flex flex-1 min-h-0 flex-col\">\n {(navTitle || closeButton) && (\n <div className=\"flex shrink-0 items-center gap-2.5 border-b border-solid border-border bg-bg-elevated px-3.5 py-3\">\n <span className=\"min-w-0 flex-1 text-sm font-extrabold text-text\">{navTitle}</span>\n {closeButton}\n </div>\n )}\n <nav className=\"flex flex-1 min-h-0 flex-col overflow-y-auto\" aria-label={navLabel}>\n {items.map((it) => (\n <button\n key={it.id}\n type=\"button\"\n className=\"flex w-full cursor-pointer items-center gap-3 border-none border-b border-solid border-border bg-transparent px-4 py-3.5 text-left text-base font-semibold text-text\"\n onClick={() => {\n onSelect(it.id);\n setDrilled(true);\n }}\n >\n {it.icon && (\n <span className=\"shrink-0 text-accent\" aria-hidden=\"true\">\n <Icon name={it.icon} size={20} />\n </span>\n )}\n <span className=\"min-w-0 flex-1\">{it.label}</span>\n <span className=\"shrink-0 text-lg text-text-faint\" aria-hidden=\"true\">\n ›\n </span>\n </button>\n ))}\n </nav>\n </div>\n );\n\n // 狭い画面: 選択したセクションの詳細(上部に戻る導線)\n const detail = (\n <div className=\"flex flex-1 min-h-0 flex-col\">\n <div className=\"flex shrink-0 items-center gap-2 border-b border-solid border-border bg-bg-elevated px-3.5 py-3\">\n <button\n type=\"button\"\n aria-label={backLabel}\n title={backLabel}\n onClick={() => setDrilled(false)}\n className=\"-ml-1.5 inline-flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-chip border-none bg-transparent p-0 text-text-dim [&>svg]:shrink-0 enabled:hover:bg-surface-hover enabled:hover:text-text\"\n >\n <Icon name=\"chevron_left\" size={20} />\n </button>\n <span className=\"min-w-0 flex-1 text-sm font-extrabold text-text\">{current?.label}</span>\n {closeButton}\n </div>\n <div className=\"flex flex-1 min-w-0 min-h-0 flex-col gap-[18px] overflow-y-auto px-4 pt-4 pb-1\">\n {description && (\n <p className=\"m-0 text-[13px] leading-relaxed text-text-dim\">{description}</p>\n )}\n {children}\n </div>\n {footer && (\n <div className=\"flex shrink-0 justify-end gap-2.5 border-t border-solid border-border bg-bg-elevated px-4 py-3\">\n {footer}\n </div>\n )}\n </div>\n );\n\n // 広い画面: レール + コンテンツの横並び(DS 準拠)\n const wide = (\n <>\n <aside\n className=\"flex shrink-0 flex-col gap-5 self-stretch border-r border-solid border-border bg-bg-elevated px-4 py-[22px]\"\n style={{ width: navWidth }}\n >\n {navTitle && <h3 className=\"m-0 px-1 text-[15px] font-extrabold text-text\">{navTitle}</h3>}\n <nav className=\"flex flex-col gap-1\" aria-label={navLabel}>\n {items.map((it) => {\n const active = it.id === value;\n return (\n <button\n key={it.id}\n type=\"button\"\n aria-selected={active}\n className={`flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-solid px-3 py-2.5 text-left text-[13.5px] transition-colors ${\n active\n ? 'border-border bg-surface-3 font-bold text-text'\n : 'border-transparent bg-transparent font-semibold text-text-dim hover:bg-surface-hover hover:text-text'\n }`}\n onClick={() => onSelect(it.id)}\n >\n {it.icon && (\n <span\n className={`shrink-0 ${active ? 'text-accent' : 'text-text-faint'}`}\n aria-hidden=\"true\"\n >\n <Icon name={it.icon} size={17} />\n </span>\n )}\n <span className=\"min-w-0 flex-1\">{it.label}</span>\n </button>\n );\n })}\n </nav>\n {navFooter && (\n <div className=\"mt-auto px-1 text-xs leading-relaxed text-text-faint\">{navFooter}</div>\n )}\n </aside>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <div className=\"flex flex-1 min-w-0 min-h-0 flex-col gap-[18px] overflow-y-auto px-[26px] py-6\">\n {paneHead}\n {children}\n </div>\n {footer && (\n <div className=\"flex shrink-0 justify-end gap-2.5 border-t border-solid border-border bg-bg-elevated px-[26px] py-3.5\">\n {footer}\n </div>\n )}\n </div>\n </>\n );\n\n // asSheet はシート側でスクロールさせるので固定高を持たせない。\n const innerClass = isNarrow\n ? 'flex flex-col flex-1 min-h-0'\n : asSheet\n ? 'flex flex-1 min-h-0'\n : 'flex flex-[1_1_auto] min-h-0 max-h-[min(520px,72dvh)] h-[min(520px,72dvh)]';\n\n const inner = <div className={innerClass}>{isNarrow ? (drilled ? detail : list) : wide}</div>;\n\n if (asSheet) {\n // シートは自前の×とスクロール領域を持つので、closeLabel はシート側へ渡す。\n return (\n <BottomSheet open onClose={onClose} ariaLabel={ariaLabel} closeLabel={closeLabel}>\n <div className=\"flex flex-1 min-h-0 flex-col\">{inner}</div>\n </BottomSheet>\n );\n }\n\n // レールの面を外殻の角丸まで届かせるため、legacy .modal の padding/gap を潰して\n // overflow-hidden を掛ける(utilities レイヤーは legacy より後なので上書きできる)。\n // × は Modal の絶対配置ではなく右ペイン内(DS の位置)に置くので closeLabel は渡さない。\n return (\n <Modal\n onClose={onClose}\n width={width}\n className={`gap-0 overflow-hidden p-0 text-left max-h-[calc(100dvh-40px)] ${className}`.trim()}\n ariaLabel={ariaLabel}\n >\n {inner}\n </Modal>\n );\n}\n","import type { ReactNode } from 'react';\n\n// ステータス表現(純粋 leaf UI)。オンライン/実行中/エラー等の状態を、セマンティックカラー\n// トークンに沿って表す。feature ごとに個別だった app-running-dot / 参加者オンライン点 /\n// pomodoro 実行中表示などを DS に集約する。\n// - StatusDot: 状態を点だけで示す最小表現(アバター隅・行頭など)。\n// - StatusBadge: 点 + ラベルのピル。Badge(new/live の一過性強調) とは用途が別で、こちらは\n// 「継続的な状態」を表す。\nexport type StatusTone = 'success' | 'warning' | 'danger' | 'info' | 'neutral';\n\nconst DOT_TONE: Record<StatusTone, string> = {\n success: 'bg-success',\n warning: 'bg-warning',\n danger: 'bg-danger',\n info: 'bg-info',\n neutral: 'bg-text-faint',\n};\n\nexport type StatusDotProps = {\n tone?: StatusTone;\n // 直径(px)。既定 8。\n size?: number;\n // 明滅(生存・実行中の含意)。\n pulse?: boolean;\n // スクリーンリーダー向けラベル(i18n は props 注入)。省略時は装飾扱い。\n label?: string;\n className?: string;\n};\n\nexport function StatusDot({\n tone = 'neutral',\n size = 8,\n pulse = false,\n label,\n className = '',\n}: StatusDotProps) {\n return (\n <span\n role={label ? 'status' : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n style={{ width: size, height: size }}\n className={`inline-block shrink-0 rounded-pill ${DOT_TONE[tone]}${pulse ? ' animate-pulse' : ''} ${className}`.trim()}\n />\n );\n}\n\nconst BADGE_TONE: Record<StatusTone, string> = {\n success: 'bg-success-surface text-success border-success-border',\n warning: 'bg-warning-surface text-warning border-warning-border',\n danger: 'bg-danger-surface text-danger border-danger-border',\n info: 'bg-info-surface text-info border-info-border',\n neutral: 'bg-tint-8 text-text-dim border-border',\n};\n\nexport type StatusBadgeProps = {\n tone?: StatusTone;\n children: ReactNode;\n // 先頭に状態点を出す。\n dot?: boolean;\n // dot を明滅させる。\n pulse?: boolean;\n className?: string;\n};\n\nexport function StatusBadge({\n tone = 'neutral',\n children,\n dot = false,\n pulse = false,\n className = '',\n}: StatusBadgeProps) {\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1.5 rounded-pill border border-solid px-2 py-0.5 text-2xs font-extrabold uppercase tracking-tag ${BADGE_TONE[tone]} ${className}`.trim()}\n >\n {dot && <StatusDot tone={tone} size={6} pulse={pulse} />}\n {children}\n </span>\n );\n}\n","// ステップ進行表示(純粋 leaf UI)。done / current / todo の3状態ピル列で「今どこにいるか」を示す\n// (リレーゲームのフェーズ表示等 #974)。文言は i18n を持たないため steps[].label で注入する。\nexport type StepFlowStep = {\n key: string;\n label: string;\n};\n\nexport type StepFlowProps = {\n steps: StepFlowStep[];\n currentIndex: number;\n direction?: 'row' | 'column';\n className?: string;\n};\n\ntype StepTone = 'done' | 'current' | 'todo';\n\nconst PILL_TONE: Record<StepTone, string> = {\n done: 'bg-success-surface text-success border-success-border',\n current: 'bg-accent text-on-accent border-transparent',\n todo: 'bg-surface text-text-dim border-transparent',\n};\n\nfunction stepTone(index: number, currentIndex: number): StepTone {\n if (index < currentIndex) return 'done';\n if (index === currentIndex) return 'current';\n return 'todo';\n}\n\nexport default function StepFlow({\n steps,\n currentIndex,\n direction = 'row',\n className = '',\n}: StepFlowProps) {\n const isRow = direction === 'row';\n return (\n <div\n className={`flex ${isRow ? 'flex-row flex-wrap items-center gap-1.5' : 'flex-col items-stretch gap-1.5'} ${className}`.trim()}\n >\n {steps.map((step, index) => {\n const tone = stepTone(index, currentIndex);\n const showSeparator = isRow && index < steps.length - 1;\n return (\n <div key={step.key} className={isRow ? 'inline-flex items-center gap-1.5' : 'contents'}>\n <span\n className={`inline-flex items-center justify-center border border-solid px-2.5 py-1 text-smd font-bold ${isRow ? 'rounded-pill' : 'rounded-md'} ${PILL_TONE[tone]}`}\n >\n {step.label}\n </span>\n {showSeparator && (\n <span className=\"text-xs text-text-dim\" aria-hidden=\"true\">\n ▸\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","// 数値増減ステッパー(純粋 leaf UI)。− / 値 / + の3要素。clamp は当部品に閉じる。\n// 旧 .stepper / .stepper-btn / .stepper-value を @theme トークン経由のユーティリティへ移行。\n// タッチ端末での当たり判定拡大(旧 pointer:coarse の 40px)は pointer-coarse: で表現する。\nexport type StepperProps = {\n value: number;\n min: number;\n max: number;\n step: number;\n onChange: (next: number) => void;\n // 全体を無効化する(例: 実行中は編集不可)。個別の端到達 disabled とは別。\n disabled?: boolean;\n // 各ボタンの aria-label(i18n を持たないため注入。例 '-1' / '+5')。\n decLabel?: string;\n incLabel?: string;\n};\n\nconst BTN =\n 'w-[30px] h-[30px] pointer-coarse:w-10 pointer-coarse:h-10 p-0 inline-flex items-center justify-center text-lg leading-none rounded-full bg-tint-7 border border-solid border-border text-text-dim transition-[background,box-shadow] enabled:hover:bg-tint-13 enabled:hover:shadow-glow disabled:opacity-(--disabled-opacity) disabled:cursor-not-allowed';\n\nexport default function Stepper({\n value,\n min,\n max,\n step,\n onChange,\n disabled = false,\n decLabel = '-',\n incLabel = '+',\n}: StepperProps) {\n return (\n <div className=\"inline-flex items-center gap-1.5\">\n <button\n type=\"button\"\n className={BTN}\n aria-label={decLabel}\n disabled={disabled || value <= min}\n onClick={() => onChange(Math.max(min, value - step))}\n >\n −\n </button>\n <span className=\"min-w-[34px] text-center text-lg font-bold tabular-nums text-text\">\n {value}\n </span>\n <button\n type=\"button\"\n className={BTN}\n aria-label={incLabel}\n disabled={disabled || value >= max}\n onClick={() => onChange(Math.min(max, value + step))}\n >\n +\n </button>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\n// タブ / セグメンテッドコントロール(純粋 leaf UI)。legacy の .side-tabs / .tab-btn(下線式タブ)を\n// トークン経由のユーティリティで再構成する。media-tabs・playlist サブタブ・sticker picker タブなどの\n// 別実装を将来この一本へ寄せる。見た目は DS(claude design \"INSESSION Design System\" #463)の\n// 下線タブに準拠: 透明地 + アクティブ下に accent(コーラル)の 2px 下線がスプリングで伸びる\n// (after:bg-accent)。非アクティブは text-faint→hover text-dim。件数は badge スロットへ\n// CountChip を渡す(DS の count バッジ相当)。i18n は持たない(label は t() 済みを渡す)。\nexport type TabItem = {\n key: string;\n label: ReactNode;\n // ラベル右の付随要素(件数 CountChip 等)。\n badge?: ReactNode;\n};\n\nexport type TabsProps = {\n tabs: TabItem[];\n value: string;\n onChange: (key: string) => void;\n ariaLabel?: string;\n // タブ行の末尾に置く付随要素(ミニアクション等)。タブとは別扱いで右端に並ぶ。\n trailing?: ReactNode;\n // タブリスト全体(role=tablist の div)に足す追加クラス。並び/余白の文脈調整用。\n className?: string;\n // 幅の振る舞い。'default'=内容幅で左詰め(media-tabs 等)。'fill'=各タブが均等に伸びて\n // 行幅いっぱいを占める(legacy 基底 .tab-btn の flex:1 相当。playlist サブタブ / sticker タブ)。\n variant?: 'default' | 'fill';\n};\n\n// hover:bg-transparent hover:shadow-none active:scale-100 active:bg-transparent は、プリフライト未使用で\n// タブが <button> 要素であるため露出する legacy グローバル button:hover(glow+teal 背景)/button:active(scale)\n// を打ち消し、旧 .tab-btn:hover/:active(transparent・shadow none・transform none)の挙動へ完全一致させる(#448)。\nconst TAB_BASE =\n \"relative inline-flex items-center justify-center gap-1.5 border-none bg-transparent py-3 font-display text-smd font-bold tracking-widest text-text-faint shadow-none transition-colors duration-(--dur-base) cursor-pointer hover:text-text-dim hover:bg-transparent hover:shadow-none active:scale-100 active:bg-transparent after:absolute after:inset-x-[12%] after:-bottom-px after:h-0.5 after:origin-center after:scale-x-0 after:rounded-xs after:bg-accent after:transition-transform after:duration-(--dur-base) after:ease-spring after:content-['']\";\nconst TAB_WIDTH: Record<'default' | 'fill', string> = {\n default: 'flex-none px-3.5',\n fill: 'flex-1 px-1.5',\n};\nconst TAB_ACTIVE = 'text-text after:scale-x-100';\n\nexport default function Tabs({\n tabs,\n value,\n onChange,\n ariaLabel,\n trailing,\n className = '',\n variant = 'default',\n}: TabsProps) {\n const tabClass = `${TAB_BASE} ${TAB_WIDTH[variant]}`;\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n // border-t-0 border-x-0 は必須: プリフライト未使用のため border-solid が全辺の border-style を\n // solid にし、border-b で未指定の上/左/右の border-width が既定 medium(3px) のまま枠として出る。\n // 明示的に 0 にして legacy .side-tabs(border-bottom のみ)へ一致させる(#448 リグレッション修正)。\n className={`flex border-t-0 border-x-0 border-b border-solid border-border ${className}`.trim()}\n >\n {tabs.map((tab) => {\n const active = tab.key === value;\n return (\n <button\n key={tab.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={`${tabClass}${active ? ` ${TAB_ACTIVE}` : ''}`}\n onClick={() => onChange(tab.key)}\n >\n {tab.label}\n {tab.badge}\n </button>\n );\n })}\n {trailing}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport Icon from './icons/icon.tsx';\n\n// トースト / スナックバー(純粋 leaf UI)。既定は画面下部中央に固定表示(fixed)。\n// DS(claude design \"INSESSION Design System\" #663)の Toast: surface + 1px border + 左3px の tone 色ボーダー +\n// radius-md + shadow-popover。title(13.5/700) / message(12.5/text-dim) / action(tone 色のテキストボタン) +\n// onAction / onClose(close アイコン)。tone は info / success(=live green) / warn / danger(error は danger の別名)。\n// アイコンは props 注入(このパッケージの Icon を呼び出し側が渡す)で、色は tone に追従する。i18n は持たない。\n//\n// variant='snackbar' は legacy feature 側 .snackbar の見た目を1pxも変えずに再現する専用パレット\n// (bg=snackbar-surface / padding 11px 20px / gap 9px / success=border-strong+mint / error=soft pink)。\nexport type ToastTone = 'success' | 'error' | 'info' | 'warn' | 'danger';\nexport type ToastVariant = 'default' | 'snackbar';\n\n// snackbar variant の tone→(border 色 / icon 色) マップ。\nconst SNACKBAR_TONE: Record<ToastTone, { border: string; icon: string }> = {\n success: { border: 'border-border-strong', icon: 'text-success' },\n error: { border: 'border-snackbar-danger-border', icon: 'text-snackbar-danger' },\n info: { border: 'border-border-strong', icon: 'text-success' },\n warn: { border: 'border-border-strong', icon: 'text-warning' },\n danger: { border: 'border-snackbar-danger-border', icon: 'text-snackbar-danger' },\n};\n\n// DS(default) variant の tone→(左ボーダー色 / 前景色)。error は danger の別名。\nconst DS_TONE: Record<ToastTone, { border: string; text: string }> = {\n info: { border: 'border-l-info', text: 'text-info' },\n success: { border: 'border-l-success', text: 'text-success' },\n warn: { border: 'border-l-warning', text: 'text-warning' },\n danger: { border: 'border-l-danger', text: 'text-danger' },\n error: { border: 'border-l-danger', text: 'text-danger' },\n};\n\n// 固定表示。中央寄せの transform は snackbar-in キーフレーム(translate(-50%,0) で終わる)に委ねる。\nconst FIXED =\n 'fixed bottom-[26px] left-1/2 z-(--z-snackbar) pointer-events-none animate-[snackbar-in_var(--dur-slow)_var(--ease-spring)_both]';\n\nexport type ToastProps = {\n children?: ReactNode;\n tone?: ToastTone;\n // 見た目のバリアント。既定 'default'(DS トースト)。'snackbar' は legacy .snackbar 互換パレット。\n variant?: ToastVariant;\n // 行頭アイコン(省略可)。色は tone に追従する。\n icon?: ReactNode;\n // DS トーストの見出し / 本文(default variant)。children を渡した場合はそれを本文として使う。\n title?: ReactNode;\n message?: ReactNode;\n // 末尾のテキストアクション(tone 色)とハンドラ。\n action?: ReactNode;\n onAction?: () => void;\n // 閉じるアフォーダンス(close アイコン)を出す。\n onClose?: () => void;\n // 画面下部中央に固定表示する(既定 true)。false で inline 配置(カタログ/埋め込み用)。\n fixed?: boolean;\n // スクリーンリーダーへの通知の緊急度。既定 'status'(polite)、エラー等は 'alert'。\n role?: 'status' | 'alert';\n className?: string;\n};\n\nexport default function Toast({\n children,\n tone = 'success',\n variant = 'default',\n icon,\n title,\n message,\n action,\n onAction,\n onClose,\n fixed = true,\n role = 'status',\n className = '',\n}: ToastProps) {\n // snackbar は legacy .snackbar を1pxも変えずに再現する(pill / children ベース)。\n if (variant === 'snackbar') {\n const t = SNACKBAR_TONE[tone];\n return (\n <div\n role={role}\n className={`inline-flex items-center gap-[9px] rounded-pill border border-solid bg-snackbar-surface px-5 py-[11px] text-[14px] text-text shadow-overlay ${t.border}${\n fixed ? ` ${FIXED}` : ''\n } ${className}`.trim()}\n >\n {icon && (\n <span className={`${t.icon} text-[13px] font-extrabold`} aria-hidden=\"true\">\n {icon}\n </span>\n )}\n {children}\n </div>\n );\n }\n\n // DS default: surface + 左3px tone ボーダー + radius-md + shadow-popover。\n const t = DS_TONE[tone];\n return (\n <div\n role={role}\n className={`inline-flex min-w-[280px] max-w-[420px] items-start gap-3 rounded-md border border-solid border-border border-l-[3px] bg-surface px-[15px] py-[13px] text-text shadow-popover ${t.border}${\n fixed ? ` ${FIXED}` : ''\n } ${className}`.trim()}\n >\n {icon && (\n <span className={`mt-px shrink-0 ${t.text}`} aria-hidden=\"true\">\n {icon}\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col gap-[3px]\">\n {title != null && <span className=\"text-[13.5px] font-bold text-text\">{title}</span>}\n {message != null && (\n <span className=\"text-[12.5px] leading-[1.5] text-text-dim\">{message}</span>\n )}\n {children}\n </div>\n {action != null && (\n <button\n type=\"button\"\n onClick={onAction}\n className={`shrink-0 whitespace-nowrap border-none bg-transparent text-[12.5px] font-bold ${t.text} cursor-pointer`}\n >\n {action}\n </button>\n )}\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"close\"\n className=\"shrink-0 inline-flex border-none bg-transparent p-0 text-text-dim cursor-pointer\"\n >\n <Icon name=\"close\" size={17} />\n </button>\n )}\n </div>\n );\n}\n","// DS の Switch(トグル。純粋 leaf UI)。claude design \"INSESSION Design System\" の Switch 仕様に準拠(#463 / #663)。\n// legacy の .toggle-switch / .toggle-knob 依存をやめ、トークンベースのユーティリティで実装する。\n// track 46x26 の pill、on=success(green) / off=border-strong、knob 20x20 の白丸 + 微ドロップシャドウ、\n// off=left3 / on=left23 を transition。disabled は opacity 0.5 + not-allowed。\n// signature は既存維持(checked / onChange / label / disabled)。onChange は「引数なしトグル」で、\n// onClick から onChange() を呼ぶ現行仕様を壊さない。prefers-reduced-motion は style.css 末尾の legacy 規則で尊重。\nexport type ToggleProps = {\n checked?: boolean;\n onChange?: () => void;\n label?: string;\n disabled?: boolean;\n};\n\nexport default function Toggle({\n checked = false,\n onChange,\n label,\n disabled = false,\n}: ToggleProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n disabled={disabled}\n onClick={onChange}\n className={`relative inline-flex h-[26px] w-[46px] shrink-0 items-center rounded-pill border border-solid border-transparent p-0 transition-colors duration-(--dur-fast) cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed focus-visible:shadow-focus focus-visible:outline-none ${\n checked ? 'bg-success' : 'bg-border-strong'\n }`}\n >\n <span\n aria-hidden=\"true\"\n className={`absolute top-[3px] h-5 w-5 rounded-pill bg-white shadow-[0_1px_2px_rgba(0,0,0,0.25)] transition-[left] duration-(--dur-fast) ${\n checked ? 'left-[23px]' : 'left-[3px]'\n }`}\n />\n </button>\n );\n}\n"],"mappings":"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","names":["dim","jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","BASE","useEffect","useRef","jsx","jsxs","useRef","useEffect","useEffect","useRef","jsx","jsxs","useRef","useEffect","jsx","jsxs","jsx","VARIANT","jsx","VARIANT","jsx","jsxs","jsx","jsxs","useId","useState","jsx","jsxs","jsx","VARIANT","jsx","jsxs","jsx","jsxs","TONE","DOT","jsx","jsxs","useId","useRef","useState","useEffect","jsx","jsxs","useRef","useId","useState","panelEl","useId","jsx","jsxs","jsx","jsxs","jsx","jsxs","FIELD","CONTROL","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsxs","jsx","jsxs","t","jsx"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@insession/design-system",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "InSession / loophub 共通のデザインシステム。純粋 leaf UI プリミティブ + デザイントークン(アプリ依存なし。i18n 等は props で注入する)",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/insession-space/design-system.git"
|
|
10
|
+
},
|
|
11
|
+
"//": "ビルド成果物(dist)を配布する。theme.css はパッケージ直下に置いたまま ./theme.css として公開する(tsup は CSS を処理しないため)。react はホストと同一インスタンスを使うため peerDependency。",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./theme.css": "./theme.css"
|
|
18
|
+
},
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"theme.css",
|
|
24
|
+
"CHANGELOG.md"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"*.css"
|
|
28
|
+
],
|
|
29
|
+
"//publishConfig": "registry を明示するのは必須。開発機の ~/.npmrc が社内プロキシ(npm.flatt.tech 等)を registry に設定している場合、これが無いと npm publish がプロキシ宛になり公開レジストリへ出ない。",
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"registry": "https://registry.npmjs.org"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": "^19.0.0",
|
|
36
|
+
"react-dom": "^19.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@biomejs/biome": "^2.3.0",
|
|
40
|
+
"@changesets/cli": "^2.31.0",
|
|
41
|
+
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
42
|
+
"@storybook/addon-docs": "^10.5.0",
|
|
43
|
+
"@storybook/react-vite": "^10.5.0",
|
|
44
|
+
"@tailwindcss/vite": "^4.3.2",
|
|
45
|
+
"@types/node": "^22.10.0",
|
|
46
|
+
"@types/react": "^19.2.0",
|
|
47
|
+
"@types/react-dom": "^19.2.0",
|
|
48
|
+
"react": "^19.2.7",
|
|
49
|
+
"react-dom": "^19.2.7",
|
|
50
|
+
"storybook": "^10.5.0",
|
|
51
|
+
"tailwindcss": "^4.3.2",
|
|
52
|
+
"tsup": "^8.3.5",
|
|
53
|
+
"typescript": "^5.7.0",
|
|
54
|
+
"vite": "^8.1.3"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=22.18"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsup",
|
|
61
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
62
|
+
"check": "biome check .",
|
|
63
|
+
"format": "biome format --write .",
|
|
64
|
+
"storybook": "storybook dev -p 6006",
|
|
65
|
+
"build-storybook": "storybook build -o storybook-static",
|
|
66
|
+
"changeset": "changeset",
|
|
67
|
+
"changeset:version": "changeset version"
|
|
68
|
+
}
|
|
69
|
+
}
|