shadcn_view_components 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +590 -0
  3. data/LICENSE +49 -0
  4. data/README.md +542 -0
  5. data/app/assets/javascripts/shadcn/aria_relationships.js +88 -0
  6. data/app/assets/javascripts/shadcn/controllers/accordion_controller.js +241 -0
  7. data/app/assets/javascripts/shadcn/controllers/calendar_controller.js +98 -0
  8. data/app/assets/javascripts/shadcn/controllers/carousel_controller.js +305 -0
  9. data/app/assets/javascripts/shadcn/controllers/checked_state_controller.js +121 -0
  10. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +613 -0
  11. data/app/assets/javascripts/shadcn/controllers/command_controller.js +87 -0
  12. data/app/assets/javascripts/shadcn/controllers/dialog_controller.js +208 -0
  13. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +145 -0
  14. data/app/assets/javascripts/shadcn/controllers/input_otp_controller.js +416 -0
  15. data/app/assets/javascripts/shadcn/controllers/menu_controller.js +286 -0
  16. data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +430 -0
  17. data/app/assets/javascripts/shadcn/controllers/message_scroller_controller.js +37 -0
  18. data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +254 -0
  19. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +117 -0
  20. data/app/assets/javascripts/shadcn/controllers/resizable_controller.js +256 -0
  21. data/app/assets/javascripts/shadcn/controllers/select_controller.js +491 -0
  22. data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +30 -0
  23. data/app/assets/javascripts/shadcn/controllers/slider_controller.js +74 -0
  24. data/app/assets/javascripts/shadcn/controllers/tabs_controller.js +146 -0
  25. data/app/assets/javascripts/shadcn/controllers/toast_controller.js +81 -0
  26. data/app/assets/javascripts/shadcn/controllers/toggle_controller.js +21 -0
  27. data/app/assets/javascripts/shadcn/controllers/toggle_group_controller.js +37 -0
  28. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +123 -0
  29. data/app/assets/javascripts/shadcn/floating_position.js +660 -0
  30. data/app/assets/javascripts/shadcn/hide_after_exit.js +53 -0
  31. data/app/assets/javascripts/shadcn/index.js +65 -0
  32. data/app/assets/javascripts/shadcn/menu_popover.js +352 -0
  33. data/app/assets/javascripts/shadcn/package.json +17 -0
  34. data/app/assets/javascripts/shadcn/state_attrs.js +13 -0
  35. data/app/assets/stylesheets/shadcn/shadcn.css +766 -0
  36. data/app/assets/tailwind/shadcn_view_components/engine.css +11 -0
  37. data/app/components/shadcn/accordion.rb +121 -0
  38. data/app/components/shadcn/alert.rb +31 -0
  39. data/app/components/shadcn/alert_dialog.rb +165 -0
  40. data/app/components/shadcn/aspect_ratio.rb +34 -0
  41. data/app/components/shadcn/attachment.rb +86 -0
  42. data/app/components/shadcn/avatar.rb +55 -0
  43. data/app/components/shadcn/badge.rb +32 -0
  44. data/app/components/shadcn/base_component.rb +239 -0
  45. data/app/components/shadcn/breadcrumb.rb +70 -0
  46. data/app/components/shadcn/bubble.rb +48 -0
  47. data/app/components/shadcn/button.html.erb +1 -0
  48. data/app/components/shadcn/button.rb +41 -0
  49. data/app/components/shadcn/button_group.rb +41 -0
  50. data/app/components/shadcn/button_styled.rb +51 -0
  51. data/app/components/shadcn/calendar.rb +276 -0
  52. data/app/components/shadcn/card.rb +18 -0
  53. data/app/components/shadcn/carousel.rb +236 -0
  54. data/app/components/shadcn/chart.rb +57 -0
  55. data/app/components/shadcn/checkbox.rb +64 -0
  56. data/app/components/shadcn/collapsible.rb +25 -0
  57. data/app/components/shadcn/combobox.rb +552 -0
  58. data/app/components/shadcn/command.rb +149 -0
  59. data/app/components/shadcn/context_menu.rb +79 -0
  60. data/app/components/shadcn/dialog.rb +180 -0
  61. data/app/components/shadcn/direction_provider.rb +18 -0
  62. data/app/components/shadcn/drawer.rb +150 -0
  63. data/app/components/shadcn/dropdown_menu.rb +242 -0
  64. data/app/components/shadcn/empty.rb +40 -0
  65. data/app/components/shadcn/field.rb +106 -0
  66. data/app/components/shadcn/floating_position_options.rb +132 -0
  67. data/app/components/shadcn/form.rb +105 -0
  68. data/app/components/shadcn/hover_card.rb +66 -0
  69. data/app/components/shadcn/input.rb +13 -0
  70. data/app/components/shadcn/input_group/button.rb +48 -0
  71. data/app/components/shadcn/input_group.rb +51 -0
  72. data/app/components/shadcn/input_otp.rb +265 -0
  73. data/app/components/shadcn/item.rb +108 -0
  74. data/app/components/shadcn/kbd.rb +9 -0
  75. data/app/components/shadcn/label.rb +12 -0
  76. data/app/components/shadcn/marker.rb +37 -0
  77. data/app/components/shadcn/menubar.rb +110 -0
  78. data/app/components/shadcn/message.rb +29 -0
  79. data/app/components/shadcn/message_scroller.rb +52 -0
  80. data/app/components/shadcn/native_checked_state.rb +74 -0
  81. data/app/components/shadcn/native_select.rb +78 -0
  82. data/app/components/shadcn/navigation_menu.rb +122 -0
  83. data/app/components/shadcn/pagination.rb +160 -0
  84. data/app/components/shadcn/popover.rb +68 -0
  85. data/app/components/shadcn/preview_base.rb +107 -0
  86. data/app/components/shadcn/progress.rb +49 -0
  87. data/app/components/shadcn/radio_group.rb +74 -0
  88. data/app/components/shadcn/resizable.rb +77 -0
  89. data/app/components/shadcn/scroll_area.rb +59 -0
  90. data/app/components/shadcn/select.rb +356 -0
  91. data/app/components/shadcn/separator.rb +42 -0
  92. data/app/components/shadcn/sheet.rb +157 -0
  93. data/app/components/shadcn/sidebar.rb +332 -0
  94. data/app/components/shadcn/skeleton.rb +13 -0
  95. data/app/components/shadcn/slider.rb +279 -0
  96. data/app/components/shadcn/sonner.rb +30 -0
  97. data/app/components/shadcn/spinner.rb +32 -0
  98. data/app/components/shadcn/switch.rb +79 -0
  99. data/app/components/shadcn/table.rb +46 -0
  100. data/app/components/shadcn/tabs.rb +119 -0
  101. data/app/components/shadcn/textarea.rb +7 -0
  102. data/app/components/shadcn/toggle.rb +66 -0
  103. data/app/components/shadcn/toggle_group.rb +127 -0
  104. data/app/components/shadcn/tooltip.rb +74 -0
  105. data/config/importmap.rb +5 -0
  106. data/lib/generators/shadcn_view_components/install_generator.rb +182 -0
  107. data/lib/shadcn_view_components/classes.rb +89 -0
  108. data/lib/shadcn_view_components/component_naming.rb +21 -0
  109. data/lib/shadcn_view_components/contracts/calendar.rb +95 -0
  110. data/lib/shadcn_view_components/engine.rb +56 -0
  111. data/lib/shadcn_view_components/generated/contracts/accordion.rb +112 -0
  112. data/lib/shadcn_view_components/generated/contracts/alert-dialog.rb +300 -0
  113. data/lib/shadcn_view_components/generated/contracts/alert.rb +104 -0
  114. data/lib/shadcn_view_components/generated/contracts/aspect-ratio.rb +34 -0
  115. data/lib/shadcn_view_components/generated/contracts/attachment.rb +224 -0
  116. data/lib/shadcn_view_components/generated/contracts/avatar.rb +149 -0
  117. data/lib/shadcn_view_components/generated/contracts/badge.rb +39 -0
  118. data/lib/shadcn_view_components/generated/contracts/breadcrumb.rb +172 -0
  119. data/lib/shadcn_view_components/generated/contracts/bubble.rb +112 -0
  120. data/lib/shadcn_view_components/generated/contracts/button-group.rb +81 -0
  121. data/lib/shadcn_view_components/generated/contracts/button.rb +81 -0
  122. data/lib/shadcn_view_components/generated/contracts/card.rb +172 -0
  123. data/lib/shadcn_view_components/generated/contracts/carousel.rb +133 -0
  124. data/lib/shadcn_view_components/generated/contracts/chart.rb +109 -0
  125. data/lib/shadcn_view_components/generated/contracts/checkbox.rb +35 -0
  126. data/lib/shadcn_view_components/generated/contracts/collapsible.rb +89 -0
  127. data/lib/shadcn_view_components/generated/contracts/combobox.rb +368 -0
  128. data/lib/shadcn_view_components/generated/contracts/command.rb +222 -0
  129. data/lib/shadcn_view_components/generated/contracts/context-menu.rb +378 -0
  130. data/lib/shadcn_view_components/generated/contracts/dialog.rb +258 -0
  131. data/lib/shadcn_view_components/generated/contracts/direction.rb +34 -0
  132. data/lib/shadcn_view_components/generated/contracts/drawer.rb +280 -0
  133. data/lib/shadcn_view_components/generated/contracts/dropdown-menu.rb +380 -0
  134. data/lib/shadcn_view_components/generated/contracts/empty.rb +150 -0
  135. data/lib/shadcn_view_components/generated/contracts/field.rb +244 -0
  136. data/lib/shadcn_view_components/generated/contracts/form.rb +62 -0
  137. data/lib/shadcn_view_components/generated/contracts/hover-card.rb +90 -0
  138. data/lib/shadcn_view_components/generated/contracts/input-group.rb +155 -0
  139. data/lib/shadcn_view_components/generated/contracts/input-otp.rb +106 -0
  140. data/lib/shadcn_view_components/generated/contracts/input.rb +34 -0
  141. data/lib/shadcn_view_components/generated/contracts/item.rb +251 -0
  142. data/lib/shadcn_view_components/generated/contracts/kbd.rb +57 -0
  143. data/lib/shadcn_view_components/generated/contracts/label.rb +34 -0
  144. data/lib/shadcn_view_components/generated/contracts/marker.rb +82 -0
  145. data/lib/shadcn_view_components/generated/contracts/menubar.rb +394 -0
  146. data/lib/shadcn_view_components/generated/contracts/message-scroller.rb +149 -0
  147. data/lib/shadcn_view_components/generated/contracts/message.rb +149 -0
  148. data/lib/shadcn_view_components/generated/contracts/native-select.rb +82 -0
  149. data/lib/shadcn_view_components/generated/contracts/navigation-menu.rb +195 -0
  150. data/lib/shadcn_view_components/generated/contracts/pagination.rb +176 -0
  151. data/lib/shadcn_view_components/generated/contracts/popover.rb +159 -0
  152. data/lib/shadcn_view_components/generated/contracts/progress.rb +126 -0
  153. data/lib/shadcn_view_components/generated/contracts/radio-group.rb +58 -0
  154. data/lib/shadcn_view_components/generated/contracts/resizable.rb +85 -0
  155. data/lib/shadcn_view_components/generated/contracts/scroll-area.rb +59 -0
  156. data/lib/shadcn_view_components/generated/contracts/select.rb +245 -0
  157. data/lib/shadcn_view_components/generated/contracts/separator.rb +34 -0
  158. data/lib/shadcn_view_components/generated/contracts/sheet.rb +209 -0
  159. data/lib/shadcn_view_components/generated/contracts/sidebar.rb +558 -0
  160. data/lib/shadcn_view_components/generated/contracts/skeleton.rb +34 -0
  161. data/lib/shadcn_view_components/generated/contracts/slider.rb +38 -0
  162. data/lib/shadcn_view_components/generated/contracts/sonner.rb +36 -0
  163. data/lib/shadcn_view_components/generated/contracts/spinner.rb +34 -0
  164. data/lib/shadcn_view_components/generated/contracts/switch.rb +35 -0
  165. data/lib/shadcn_view_components/generated/contracts/table.rb +199 -0
  166. data/lib/shadcn_view_components/generated/contracts/tabs.rb +104 -0
  167. data/lib/shadcn_view_components/generated/contracts/textarea.rb +34 -0
  168. data/lib/shadcn_view_components/generated/contracts/toggle-group.rb +62 -0
  169. data/lib/shadcn_view_components/generated/contracts/toggle.rb +39 -0
  170. data/lib/shadcn_view_components/generated/contracts/tooltip.rb +116 -0
  171. data/lib/shadcn_view_components/numeric_property_validation.rb +124 -0
  172. data/lib/shadcn_view_components/property_contract_definitions.rb +92 -0
  173. data/lib/shadcn_view_components/property_contracts.rb +42 -0
  174. data/lib/shadcn_view_components/property_validation.rb +55 -0
  175. data/lib/shadcn_view_components/version.rb +6 -0
  176. data/lib/shadcn_view_components.rb +21 -0
  177. metadata +446 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2101ff232a685f61321d32cf4c61610f5c3cf80f1524928a3993ec90415bb006
4
+ data.tar.gz: 96b26bbd4b16ba7bbcb813cf07463c988931daaa28eaa6310ebacc4676c9ac93
5
+ SHA512:
6
+ metadata.gz: 949f78dcbb1c70d337c939b2e2ec327f44d6c58f5b0fc1e7fdd958f6598a3166849fa65a1c15de82b7dcd975d2a99f02529b0141521120ad5639582750981353
7
+ data.tar.gz: e87d59f8726efb40fcea61bc4f9ef41870e40391ee34a4b69bdd1861e904ee4bcc64629e449000ee6feb3e65862b55016a920a5b1f51ddadf0e45957036e3d64
data/CHANGELOG.md ADDED
@@ -0,0 +1,590 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.1.0 (unreleased)
6
+
7
+ Phase 0(インフラ構築 + Buttonによるパイプライン実証)。
8
+
9
+ ### gem の配布内容と consumer 検証を整備
10
+
11
+ - README・CHANGELOG・LICENSE を gem に同梱し、本プロジェクトと shadcn/ui 由来の配布物の MIT ライセンス本文を収録する
12
+ - RubyGems の重複 homepage metadata を除き、文書・Issue へのリンクを追加する。詳細文書は GitHub で公開する
13
+ - build 済み gem を一時 consumer app に install し、文書・metadata・require・generator・asset 解決・代表描画・Tailwind ビルドを現在版と下限版の依存 gem で検証する
14
+
15
+ ### questionnaire / toast を理由付き非対応として確定
16
+
17
+ - `spec/conformance/registry.yml`の各エントリを`exports`(実装済み)か`unsupported`(理由付き非対応)の
18
+ 厳密に一方へ統一し、`pending`を廃止した。`unsupported`は`reason` / `alternatives` / `reviewed_sha256`
19
+ のみを持ち、代替は実装済みアイテムのみを参照できる
20
+ - `spec/contracts/registry_status_spec.rb`が状態・形式・代替・SHAを検証し、upstream同期で
21
+ `reviewed_sha256`が`vendor/shadcn/manifest.json`と乖離すると非対応判断の再評価が強制される
22
+ - `questionnaire`はField / Form等の代替とサーバー主導の複数ステップフロー(1 step = 1リクエスト、
23
+ 422で同一step再描画)を案内する。`toast`は移植せず、既存のSonner通知
24
+ (`Shadcn::Sonner::Toaster` + `shadcn:toast`)を唯一の通知APIとする(base-novaではToastが正規である点は
25
+ 意図的な差異として決定ログに記録)。操作を伴う通知・重要情報は`Shadcn::Alert`へ案内
26
+ - `docs/unsupported-components.md`を新設し、READMEの生成インベントリへ非対応の理由と代替を表示する。
27
+ 現行Sonnerの非対応機能(Action / Close / type / priority / pause / swipe / promise)と、
28
+ `toast_controller.js`の手書きクラスが既知の限界であることをdocsへ記録した
29
+
30
+ ### Tailwind統合をtailwindcss-railsのEngine機構へ統一
31
+
32
+ - Tailwind CSS v4と`tailwindcss-rails >= 4.3`を必須にし、gem同梱のEngine CSSから生成テーマ、
33
+ 生成契約、Calendar個別契約、ViewComponent、配布JavaScriptを相対パスで走査する
34
+ - ホストの`app/assets/tailwind/application.css`は`tw-animate-css`と自動生成Engine wrapperの
35
+ 固定importだけを保持し、gemの物理パス、`@source`、任意のstylesheet指定を廃止した
36
+ - ビルド済みgemを任意パスへinstallしたconsumerで`tailwindcss:engines`と`tailwindcss:build`を実行し、
37
+ 最低対応4.3系と現在版の双方で全ソース由来のクラスが最終CSSへ入ることをCIで検証する
38
+
39
+ ### 全コンポーネントのテスト範囲を一元管理
40
+
41
+ - 実装済み61 registry itemについて、全公開exportの最小描画、Lookbook preview、upstreamとの
42
+ light / dark見た目比較、実ブラウザ操作テストの対応を`spec/coverage/registry.yml`へ集約した
43
+ - coverage registryと実装registry、preview、Stimulus controller、visual parity scenario、system specの
44
+ 対応を双方向に検査し、今後itemを追加したのに検証範囲を指定しなかった場合はCIを失敗させる
45
+ - 全itemへLookbook previewを用意し、Attachment、Bubble、ButtonGroup、InputGroup、Message、
46
+ NativeSelect、Progressのupstream visual parityを追加した。技術的に同じ状態を比較できない項目には
47
+ その理由を台帳へ明記した
48
+ - 新しい見た目比較で判明したButtonGroupのSeparator合成、InputGroupの標準Input / Textarea合成と
49
+ `data-align`、ProgressのTrack / Indicator構造の欠落を、生成契約を参照する実装へ修正した
50
+ - system specごとにpointer、keyboard、state、form、reset、reconnect、no-JS、accessibility等の
51
+ 確認項目を宣言し、Collapsible、MessageScroller、NativeSelect、Sonnerの実ブラウザ検証を追加した
52
+
53
+ ### Checkbox・RadioGroup・Switchの状態同期
54
+
55
+ - ネイティブinputの`checked`を唯一の状態源とし、初期描画、利用者操作、フォームreset、Turbo再接続で
56
+ `data-checked` / `data-unchecked`を同期する共通controller契約を追加した
57
+ - 同名かつ同じフォームに属するRadioを一括同期し、利用者のStimulus controller / actionと内部処理を
58
+ 重複なく合成する。任意dataとARIAは保持し、状態dataはネイティブ値を常に優先する
59
+ - `:checked`と`peer-checked`による装飾を追加し、JavaScriptが無効でも選択色、indicator、Switch thumbを
60
+ ネイティブ操作へ追従させた。装飾要素はアクセシビリティツリーから除外した
61
+ - checked / uncheckedのLookbook previewとupstream visual parity、フォームAPIと初期状態のcomponent
62
+ spec、代表プレビューのアクセシビリティ検査を追加した
63
+
64
+ ### Carouselの縦方向・RTL・リサイズ時の状態を同期
65
+
66
+ - Rootの`orientation:`と`direction:`を公開プロパティ契約へ追加し、正規化した値を
67
+ `data-orientation`、`data-direction`、`dir`へ出してレイアウトとcontrollerの唯一の状態源にした
68
+ - named group variantでContent、Item、Previous / Nextへ向きを伝播し、upstreamのhorizontal classを
69
+ 保ったままvertical配置とhorizontal RTLのChevron反転を追加した
70
+ - viewportやItemの実寸法に基づく前後移動、RTLのスクロール座標正規化、scroll / ResizeObserverによる
71
+ ボタン状態の再計算、向きに応じた矢印キー操作を追加した
72
+ - Root / ItemのARIA構造と利用者指定のaccessible nameを保ち、複数Item表示で曖昧になる
73
+ `aria-current`は追加せず、フォーカス可能なRootの矢印キー操作と現在位置をネイティブPrevious /
74
+ Nextの`disabled`へ同期した
75
+
76
+ ### InputOTPの実入力とSlot表示を同期
77
+
78
+ - 実際の`input[type="text"]`を値と選択範囲の唯一の情報源にし、初期値、入力、削除、貼り付け、
79
+ IME、one-time-code自動入力、caretを各Slotへ同期する`shadcn--input-otp` controllerを追加した
80
+ - ブロック省略時に`length`個のSlotを1つのGroupへ描画する標準構成を追加し、明示構成では
81
+ `Slot(index:)`と`Separator`を使えるようにした。実inputと表示コンテナの属性・クラスも分離した
82
+ - `inputmode`はキーボードのヒントで文字制限ではないことを明記し、`pattern`不一致の入力・貼り付けは
83
+ 一部の文字を除去せず変更全体を拒否するupstream互換の規則へ統一した
84
+ - JavaScript無効時に実inputを通常の入力欄へ戻す`noscript`スタイルと、フォーム・ラベル・エラー、
85
+ caret・選択範囲、disabledを検証するsystem spec、Lookbook preview、light / dark visual parityを追加した
86
+
87
+ ### Sliderをネイティブrange inputへ接続
88
+
89
+ - `id`、`name`、`form`、`disabled`、`required`、ARIA、data、イベント属性を外側の装飾ではなく
90
+ 実際の`input[type="range"]`へ渡し、ラベル連携とフォーム送信を成立させた
91
+ - inputを値の唯一の情報源とする`shadcn--slider` controllerを追加し、初期値とネイティブの
92
+ input / changeイベントから水平・垂直のrangeとthumb位置を同期する
93
+ - `step`と`orientation`を公開プロパティ契約へ追加し、有限数、`max > min`、正のstep、値域、
94
+ stepとの一致を描画前に検証する。値未指定時はブラウザ標準と同じstep調整済み中間値を使う
95
+ - 抽出器がinline collection callback内の`slider-thumb`とdata-slot無しのControlを取りこぼす原因を修正し、
96
+ Track / Range / Thumb / Controlのclassをすべてupstream生成契約から取得するようにした
97
+ - 水平・垂直のLookbook preview、light / dark visual parity、ラベル・キーボード・フォーム送信の
98
+ 実ブラウザsystem specを追加した
99
+
100
+ ### 複合コンポーネントのARIA参照とキーボード操作を整備
101
+
102
+ - Dialog系、Tabs、Combobox、Select、Accordion、Resizable、Calendarについて、Trigger、
103
+ Content、Label、選択項目を一意なIDとARIA参照で結び、開閉・選択・現在値を同期した
104
+ - 利用者指定のIDとARIA属性を保持しつつ未指定値だけを補完し、fragment cacheで自動生成IDが
105
+ 重複した場合は同じルート内の自動生成参照だけを再採番する共通処理を追加した
106
+ - 同種コンポーネントの入れ子を親controllerの探索対象から除外し、TabsのHome / End、
107
+ Resizableの矢印・Home / End、Calendarの表示月内グリッド移動を追加した
108
+ - Tabsの向きはRootの`orientation:`を唯一の指定箇所とし、Listの`orientation:`は削除した。
109
+ Listの`aria-orientation`とキーボード操作はRootの値から補完する
110
+ - `axe-core`をCupriteへ直接読み込み、代表LookbookプレビューをWCAG 2.0〜2.2 A/AAの
111
+ 対象ルールで検査するsystem specをCIへ追加した
112
+
113
+ ### ComboboxとchipsをRailsフォームへ接続
114
+
115
+ - 検索文字列、候補のハイライト、確定した送信値を分離し、確定値だけをルート直下の
116
+ ネイティブ`select`で管理する専用`shadcn--combobox` controllerを追加した
117
+ - ルートに`name:`、`default_value:`、`multiple:`、`disabled:`、`required:`、`form:`を追加し、
118
+ 単一選択はラベルと値を分け、chipsは追加・削除・自由入力をRailsの配列パラメータへ反映する
119
+ - 空値と重複を除外し、動的chipもRubyと同じ完全なSSR templateから生成する。Turbo再接続では
120
+ 確定値から表示を復元し、初期化イベントや一時的な検索文字列を残さない
121
+ - 確定値が変わったときだけ、canonical selectからbubblingする`input`、`change`を順に発火する
122
+ - disabled / requiredのネイティブ動作と可視入力のARIAを同期し、実Rails controllerへの送信、
123
+ 422再描画、連続chip削除をcomponent / JavaScript / system specで検証した
124
+ - 空の単一値と全削除したchipsもフォーム上で明示し、chipsの空文字markerは受信側で空配列へ正規化する。
125
+ 候補はmanual popoverとしてroot外pointer・focus・Escapeで閉じ、検索inputの操作では開いた状態を保つ
126
+
127
+ ### Menubar・NavigationMenuの状態管理を分離
128
+
129
+ - 単一の`shadcn--menu`が先頭のpopoverだけを操作していた構造を廃止し、Menubarと
130
+ NavigationMenuへ各ARIAパターン専用のStimulus controllerを追加した
131
+ - Menubarの各Menu、NavigationMenuの各Item、サブメニューのTriggerとContentを
132
+ DOM上の親要素から一対一に対応付け、IDと`aria-controls`、ARIA menuの`aria-labelledby`を同期する
133
+ - ContextMenu以外は`popover=auto`のネイティブなlight dismissを維持し、開いているTriggerへの
134
+ pointer操作を記録して、ブラウザの自動解散後にclickで再び開く競合を解消した。非同期の`toggle`通知より
135
+ 利用者の開閉要求を優先し、開いている親popover内の子だけを残す共有調停で別rootも同時に開かないようにした
136
+ - Menubarの左右移動、NavigationMenuのネイティブリンク操作、段階的なEscape、外側クリック、
137
+ フォーカス復帰、ARIA menuitemのEnter / Space活性化を実装し、入れ子の別controllerを
138
+ 項目探索や閉じる対象から除外した
139
+ - ContextMenu Triggerをフォーカス可能な右クリック領域へ戻し、左クリックactionが残る継承不具合を解消した。
140
+ manualのContextMenuを開く際は既存のauto popoverを閉じ、ARIA menuはTab / Shift+Tabで全階層を閉じる。
141
+ NavigationMenuは`nav`と通常リンクの構造へ戻し、開いたContent内のTab巡回を維持したまま
142
+ Content外へのfocus移動で閉じる
143
+ - 複数Menu / Item、サブメニュー、入れ子の制御範囲をJavaScript単体テストと実ブラウザテストで検証した
144
+
145
+ ### 公開コンポーネントと名前空間の境界を明確化
146
+
147
+ - `Chart`、`Form`、`Resizable`、`Sonner`を描画クラスではなく名前空間として定義し、
148
+ 実際に描画できる配下クラスだけを公開コンポーネントとした
149
+ - upstreamの非JSX exportを誤ってクラス化していた`Chart::Tooltip`と`Chart::Legend`を削除し、
150
+ 基底クラスと内部ナビゲーション用クラスを非公開にした
151
+ - 公開コンポーネント一覧と適合試験レジストリの一致、ルートスロット契約、全クラスの
152
+ 最小構成での描画を一括検証し、公開したクラスだけが描画時に失敗する状態を検出可能にした
153
+
154
+ ### Selectをフォーム送信可能なlistboxとして完成
155
+
156
+ - primitive Rootの別名exportも抽出契約へ残し、Selectルートだけ契約面が欠けて描画時に例外となる
157
+ 原因を生成パイプラインから解消した
158
+ - `shadcn--menu`への誤った依存を廃止し、hidden inputを確定値の唯一の情報源とする専用
159
+ `shadcn--select` controllerでクリック、全キーボード操作、disabled option、再接続を扱う
160
+ - Trigger・listbox・optionをIDとARIAで関連付け、表示値・選択状態・フォーム値を同じ値から同期する
161
+ - Selectのcomponent / DOM / system / visual parity検証とLookbook previewを追加した
162
+ - JS不要・native validation向けの`NativeSelect`との責務を明記し、装飾用sizeがHTMLの行数属性へ
163
+ 誤って流れないよう`data-size`へ分離した
164
+
165
+ ### 公開プロパティの値域検証を統一
166
+
167
+ - CVAバリアントとは別に、Rails側でdata属性・ARIA・CSS値へ変換する列挙値と数値の
168
+ `PropertyContracts` を追加し、許容値・既定値・`nil`の可否を一箇所で宣言した
169
+ - Sheet side、orientation、Toggle / Toggle Group状態、direction、状態・サイズ系propを
170
+ String / Symbolから正規化し、未知値・`nil`・異種型を描画前の`ArgumentError`に統一した
171
+ - Progressは0〜100を検証し、不定状態の`nil`では`aria-valuenow`を省略する。Sliderは有限数、
172
+ `min < max`、valueの包含範囲を検証し、InputOTP length・AspectRatio ratio・Toggle Group spacingも
173
+ 各境界を初期化時に検証する
174
+ - contract由来variantも型外入力を`ArgumentError`に統一し、Buttonを合成するAPIでは描画時ではなく
175
+ 初期化時にvariant / sizeを検証する
176
+
177
+ ### 浮動要素の位置決めを共通化
178
+
179
+ - Popover、Tooltip、Hover Card、Dropdown / Context / Menubar / Navigation Menuと
180
+ Submenuの座標計算を一つの位置決めmoduleへ集約し、controllerは開閉・ARIA・anchor選択だけを担う
181
+ - `side`、`align`、`side_offset`、`align_offset`、`collision_padding`をContentの共通optionとして公開し、
182
+ upstream既定値をSSRの`data-position-*`へ出力する。実配置の`data-side` / `data-align`とは分離する
183
+ - 四辺のviewport衝突でside / alignを反転・調整し、RTLのstart/endとinline-start/inline-end、
184
+ `--anchor-*` / `--available-*` / `--transform-origin` CSS変数を共通処理する
185
+ - overflow ancestorのscroll、window / visual viewportのresize、anchor / contentのsize変更、
186
+ anchorのlayout移動を監視し、close・light dismiss・Stimulus切断時に全購読と予約済み更新を解除する
187
+
188
+ ### 配布Stimulus controllersの検証を必須化
189
+
190
+ - gemから配布するJavaScript全体をESLintとTypeScript `checkJs`の対象にし、構文だけでなく
191
+ DOM型、event型、未使用変数もrelease前に検出する
192
+ - 実Stimulusとjsdomを使い、全controllerの主要状態遷移、複数instance、再接続、
193
+ listener・timerの後始末を高速なDOM単体テストで保証する
194
+ - controller一覧とtest一覧の一致を検査し、新規controllerだけが未検証で追加されることを防ぐ
195
+ - 実配布packageへの相対linkをconsumer fixtureで使い、同期直後のsourceをlint・型検査・
196
+ DOM test・esbuild bundleのすべてで検証する
197
+
198
+ ### 非Importmap向けJavaScript entry pointを実行可能にする
199
+
200
+ - gem内の `app/assets/javascripts/shadcn` を固有名のlocal ESM packageとして定義し、内部importを
201
+ Node bundlerのpackage self-referenceで解決できるようにした
202
+ - importmapとbundlerのどちらも `@supermomonga/shadcn-view-components` を正式なentry pointとした
203
+ - importmap-railsの標準構成に従い、engineのmap定義とcache監視対象をinitializerで合成する
204
+ - bundler用packageはgeneratorがhost repository内の固定相対pathへ完全同期し、machine固有の
205
+ gem install pathをpackage.jsonやlockfileへ保存しない
206
+ - 実consumer fixtureをesbuildし、配布済みcontroller全件の登録とToggle操作をCIで検証する
207
+ - README、install generator、ESM source commentの非Importmap手順を同じlocal package方式へ統一した
208
+
209
+ ### OTP inflectionのhost applicationへの副作用を解消
210
+
211
+ - require時とengine initializerで重複登録していたグローバルな `OTP` acronymを削除した
212
+ - component定数名の規則をgem内部の一箇所へ集約し、契約解決もhostのinflectionから分離した
213
+ - Rails main loaderの既定inflectorをdelegateするpath限定wrapperをengine initializer一箇所で設定し、
214
+ gem内の `app/components/shadcn/input_otp.rb` だけを `InputOTP` へ写像する
215
+ - 別processの契約specで、require前後とRails boot後のhost inflectionが不変であること、hostの
216
+ 同名fileに写像が漏れないこと、InputOTPのeager load成功を保証した
217
+
218
+ ### install generatorのTailwind directiveを独立して保証
219
+
220
+ - host CSSの`tw-animate-css` importとEngine wrapper importを別々に検査し、
221
+ どちらか一方だけが既にある場合も不足したdirectiveを補う
222
+ - 二つのimportの有無による4状態が同じ最終条件に収束し、generatorを再実行しても
223
+ 行の重複やbyte差分を作らないことをgenerator specで保証し、このspecを
224
+ `verify:spec` の必須対象に加えた
225
+
226
+ ### 自動upstream同期PRに必須検証を固定
227
+
228
+ - 差分検出後、PR作成前に `bundle exec rake verify` の8検査を失敗伝播ありで実行し、
229
+ 失敗した同期内容を成功扱いでPRにしないようにした
230
+ - PR作成credentialを `github.token` に固定。作成後は同じhead branchへ通常CIを
231
+ `workflow_dispatch` し、`pull_request` eventの再帰防止や外部tokenの有無に関係なく
232
+ PRに8個のstatus checkを付ける。PRは必ずdraftで作成し、全checkの生成を実確認した
233
+ 後だけreview readyに変更する
234
+ - PR本文とActions summaryにupstreamの完全SHA、registry snapshot hash、取得日時、
235
+ 検証結果とrun URLを表示し、manifest fixtureを使ったworkflow契約specで保証した
236
+
237
+ ### upstream同期のtimestamp差分を抑止
238
+
239
+ - upstream の内容と revision が前回から変わらない場合、manifest の `fetched_at` と
240
+ `checked_at` を保持し、定期同期が時刻だけのcommit / Pull Requestを作らないようにした
241
+ - 同一responseの再同期ではvendorスナップショット全体がバイト単位で不変になり、内容または
242
+ revisionが変わった時だけ対応するmetadataが更新されることを固定時刻のテストで保証する
243
+
244
+ ### upstream同期を整合したsnapshot単位で確定
245
+
246
+ - release metadataとlive registry一式を同期の前後で二度取得し、index、全item、theme、
247
+ style bootstrapの集合hashとrelease tag / SHAが安定している場合だけ更新する
248
+ - manifestをversion 2へ更新し、正規化したindex / style bootstrap本体と個別SHA、registry一式の
249
+ content SHA、二重取得の整合条件を記録する。GitHub release SHAはregistry revisionとはみなさず、
250
+ exact versionのTailwind CSSを特定するための参考情報として分離した
251
+ - 全成果物とlocal overrideを同一filesystem上のstaging directoryへ作成・checksum検証してから
252
+ directory単位で置換する。overrideは保存byteそのものをhash化し、確定直前と現snapshotを
253
+ backupへ移した直後にも変更がないことを確認する。確定失敗や中断時は以前のdirectoryを復元する
254
+ - index掲載itemの404、通信、JSON、schema、metadata不一致を別の同期エラーとして中止し、
255
+ Tailwind CSSの旧版流用やstyle依存の空配列化を廃止。どの部分失敗でも既存snapshotを保つ
256
+
257
+ ### pnpm toolchainとdependency build policyの固定
258
+
259
+ - `mise.toml` と各 `package.json` で pnpm 10.22.0 を固定し、ローカルとCIが
260
+ 実行時期に左右されず同じpackage managerを使うようにした
261
+ - Extractorでは `@parcel/watcher` / `esbuild`、Visual Parityでは `esbuild` の
262
+ install scriptだけを明示的に許可し、未判断のdependency buildは
263
+ `strictDepBuilds` でinstall failureとして検出する
264
+ - 各toolは従来どおり独立したlockfileを維持し、workspace化による依存解決の変更を避けた
265
+
266
+ ### visual parityの検証出力とbaseline更新を分離
267
+
268
+ - 通常のvisual specは `tmp/visual-parity/run-<pid>/` へ成果物を出し、追跡中の
269
+ `spec/visual/baselines/` を書き換えない
270
+ - `rake parity:update` だけが追跡baselineを更新する。CI失敗時のours / upstream /
271
+ diff / reportはGitHub Actions artifactとして7日間保存する
272
+
273
+ ### ローカル検証とCIのentry pointを統一
274
+
275
+ - `bin/setup` でmise toolchain、Ruby gems、root / Extractor / Visual Parityの
276
+ JavaScript依存をまとめて導入し、通常CIの全jobとupstream同期も同じsetup経路を使う
277
+ - visual parityの静的icon shimを生成対象から分離し、clean checkoutでも参照アプリを
278
+ ビルドできるようにした
279
+ - dummy CSSの鮮度比較では、native変換がOSごとに等価な表現を選ぶTailwind preflightを
280
+ 除外し、リポジトリが所有するtheme・utilities・追加base層を比較する
281
+ - parity画像の寸法差を各画像の背景色で補完し、dark時だけ固定の白背景が差分になる
282
+ 偽陽性を解消した
283
+ - `rake verify` / `rake verify:full` がCI必須の8検査をすべて実行し、CIの各jobも
284
+ 対応する `verify:*` subtaskを呼ぶようにした
285
+ - 各CI jobが対応taskを`LOCAL_VERIFY_TASK`として宣言し、契約specが全jobと
286
+ `verify:full`の依存taskの完全一致を検査する。workflowの全stepも準備・検証・成果物保存に分類し、
287
+ 検査追加時の片側だけの更新やCIへの検査コマンド直書きをCIで検知する
288
+ - 通常RSpec jobから漏れていたrequest specと、従来のローカルverifyから漏れていた
289
+ TypeScript、Vitest、Tailwind、RBI freshnessを共通経路へ含めた
290
+
291
+ ### 残っていた parity 失敗 8件の解消(不具合修正)
292
+
293
+ 参照側CSSパイプラインの独立化の時点で残っていた8件の失敗(静的5件: command / calendar
294
+ default・plain / item、アニメーション3件: dropdown-menu / combobox / hover-card)を解消。
295
+ `bundle exec rake`(shadcn:check / sorbet / rubocop / 全spec + parity)が完全に緑になった。
296
+
297
+ - アニメーション検証の整数除算バグ(combobox / hover-card): JS由来の rect 値は JSON 数値
298
+ として整数になりうるため、`114 / 120` のような比率計算が Ruby の整数除算で 0 になり、
299
+ アニメーション形状の比較が必ず失敗しうた。比率計算を to_f に統一(spec 側のバグ修正)
300
+ - dropdown-menu: upstream の `DropdownMenuLabel` は `Menu.GroupLabel` への写像のため、
301
+ Group 外でメニューを開くと Base UI が文脈エラー(#31)を投げ React ツリー全体が
302
+ アンマウントされていた(静的比較は閉じた状態のため検知できていなかった)。
303
+ 公式ドキュメント構成に従いラベルを `DropdownMenuGroup` 内へ移動(プレビュー・
304
+ upstreamデモ両側)
305
+ - command: `Command::Input` が InputGroup 合成を持たず placeholder が消失していた
306
+ (upstream は `<InputGroup>` + `<InputGroupAddon>` 構成)。combobox と同じ合成パターン
307
+ で再実装し、placeholder を内側の input へ転記
308
+ - item: upstream useRender の state(`data-variant` / `data-size`)を出力していなかったため
309
+ ItemGroup の `has-data-[size=sm]:gap-2.5` が発火せず gap が不一致。また item-separator
310
+ が Separator 契約クラス(`shrink-0 bg-border data-horizontal:h-px`)を持たず高さ 0 だった
311
+ - calendar: セル寸法が upstream(--cell-size = 28px)より大きかった。month_grid の幅を
312
+ 7×cell に固定、DayButton 契約を `<Button variant="ghost" size="icon">` 合成に修正
313
+ (px-2.5 がセルの最小幅を超過させていた)、ナビをキャプション行上の絶対配置に変更
314
+ (タイトル表記も upstream に合わせ「2026年8月」)
315
+
316
+ ### パリティ検証の参照側を upstream 本来のCSSパイプラインへ(検証設計修正)
317
+
318
+ visual parity の upstream 参照側は、これまで gem の `shadcn.css` を読んでいた(トークンと
319
+ フォントを両側で同一にして決定論的に比較するため)。しかし**共有したものはテスト対象から
320
+ 外れる**ため、shadcn.css とその Tailwind コンパイル意味論に属する不具合 — 前項で修正した
321
+ カスタムバリアント欠落(tabs line の下線消失)もその型 — は両側で同じだけ壊れて差分が消え、
322
+ 検出できなかった。
323
+
324
+ - npm shadcn パッケージ同梱の `tailwind.css`(index.json の `@import "shadcn/tailwind.css"`
325
+ の実体)を `vendor/shadcn/style/tailwind.css` にスナップショットし、manifest の
326
+ `source.tailwind_css` がバージョン(`upstream_release.tag` に固定)と SHA256 を記録。
327
+ `rake shadcn:sync` がこのファイルも取得・更新する
328
+ - gem の `shadcn.css` は当該ファイルを verbatim 取り込みに変更。従来手追加していた
329
+ `data-horizontal` / `data-vertical` の2バリアント断片を廃止し、9種のカスタムバリアント・
330
+ accordion keyframes・`no-scrollbar`・`scroll-fade`・`shimmer` を upstream どおり提供する
331
+ - 参照側には upstream 実アプリの globals.css 相当のみを生成した
332
+ `tools/visual-parity/src/upstream_theme.css` を与え、gem 出力から独立させた
333
+ (`shadcn:generate` / `shadcn:check` の対象に追加)。全シナリオの描画は変化せず
334
+ (既存の移植に CSS パイプライン起因の漏れが無いことの確認)。「accordion の開閉
335
+ アニメーションが upstream と一致する」は keyframes 定義の供給により今回から緑化
336
+ - 新スペック `spec/conformance/custom_variant_spec.rb`: shadcn.css への verbatim取り込み
337
+ の存在と、契約が使う bare `data-*:` バリアントが「upstream 定義済み」か「Base UI の
338
+ bare 状態属性(presence で正しい)の許可リスト」に分類できることを機械的に検査
339
+
340
+ ### 方向カスタムバリアントの欠落修正と resizable 挙動の修正(不具合修正)
341
+
342
+ 契約が使う Tailwind の `data-horizontal:` / `data-vertical:` が、存在しない
343
+ `[data-horizontal]` 属性へのマッチにコンパイルされており、`data-orientation`
344
+ を出力するどのコンポーネントにも適用されていなかった。tabs では active
345
+ インジケータ(line バリアントの下線)の寸法・位置指定が死んでいて下線が描かれず、
346
+ root の `data-horizontal:flex-col` も効かないためリストとコンテンツが横並びに
347
+ なっていた。parity 検証は upstream 側も同じテーマCSS(shadcn.css)で描くため、
348
+ この欠落を検出できていなかった。
349
+
350
+ - extractor の CSS 生成に upstream npm shadcn/tailwind.css 由来の
351
+ `@custom-variant data-horizontal / data-vertical` を追加し、shadcn.css と
352
+ dummy の静的CSSを再生成。tabs ほか button-group / field / scroll-area /
353
+ separator / slider / toggle-group の方向系クラスが活性化する
354
+ - resizable コントローラの修正:
355
+ - ドラッグ軸の反転(セパレータの `aria-orientation="vertical"` を縦方向
356
+ ドラッグと解釈しており、横並びグループで上下移動が分割を変えていた)を正す
357
+ - 前後パネルの対を「ハンドルより手前のパネル数」から決める(子要素全体の
358
+ index だったため、3パネル以上で2個目以降のハンドルが無反応だった)
359
+ - ドラッグを開始時の比率 + 移動量の相対方式に変更(カーソルの絶対位置をそのまま
360
+ 比率にしていたため、掴んだ瞬間パネルがカーソル位置へ跳んでいた)
361
+ - 縦積みグループで上下キーでもリサイズできるようにし、flex-basis は %
362
+ 表記のときだけ信頼する
363
+ - `Resizable::PanelGroup` / `Resizable::Handle` に `orientation:` を追加し、
364
+ 垂直グループ(PanelGroupの`data-orientation="vertical"`でflex-col、Handleの
365
+ `aria-orientation="horizontal"`でrow-resize)を構成できるように
366
+ - Lookbook に `tabs/vertical` と `resizable/vertical` のシナリオを追加
367
+ (parity の upstream デモ・シナリオも登録)
368
+
369
+ ### combobox の選択確定・chips 操作の実装(不具合修正)
370
+
371
+ 選択肢のクリック・chips入力欄でのEnter確定が全く機能しない不具合を修正した。
372
+ 原因は選択確定の接線がJS/Ruby双方に存在しなかったことと、chipsプレビューが
373
+ コントローラ無しで描かれていたこと。
374
+
375
+ - `Combobox::Item` に `data-action="click->shadcn--command#select"` を追加し、
376
+ クリック(およびEnter時の合成クリック)で選択確定するように。単一選択では
377
+ チェックインジケータ(`data-indicator`)の移動・入力欄へのラベル反映・リストを
378
+ 閉じるまでを行う。キー操作は従来どおりキャプチャリスナーに一元化
379
+ (data-action 化による二重発火は起こさない)
380
+ - chipsモード: `Combobox::ChipsInput` をコントローラが発見できるようにし、Enter で
381
+ ハイライト項目(リスト無し時は入力テキスト)を新規chipとして確定。
382
+ `Combobox::Chip` の削除ボタンにも `removeChip` アクションを接線
383
+ (動的追加chipにも効く。新規chipは接続時に確保した既存chipの複製で、
384
+ クラスと削除ボタンを引き継ぐ。全chip削除後の追加でも契約どおりのマークアップになる)
385
+ - chipsプレビュー(`combobox/chips`)を `Shadcn::Combobox.new` でラップし
386
+ コントローラを接線
387
+ - 選択確定時に入力欄の `aria-expanded` を開閉に同期
388
+ - 適合試験: allowances の `ComboboxItem` に `data-action` を許可に追加
389
+
390
+ ### form の Field ベース再設計(破壊的変更)
391
+
392
+ base-nova には form アイテムが存在せず、公式 docs/forms ガイドは Field プリミティブ +
393
+ `data-invalid` / `aria-invalid` の手動ワイヤリングへ移行した(Issue #3)。旧new-york-v4
394
+ 定義の local-override 維持を撤退し、同ガイドに沿った独自契約として再設計した。
395
+
396
+ - 新API(2 exports):
397
+ - `Shadcn::Form::Item` — Field と同じ DOM 構造(`data-slot="field"`)を描く。
398
+ `invalid:` キーワードで `data-invalid="true|false"` を出力。`orientation:` も
399
+ Field と同様に受け付ける
400
+ - `Shadcn::Form::Error` — upstream `FieldError` セマンティクスの Rails 向け版。
401
+ `message:`(文字列)/`errors:`(文字列配列、重複除去)を受け、1件は平文・
402
+ 複数は ul リスト・無ければ非描画。`model.errors.full_messages_for(:attr)` を
403
+ そのまま渡せる
404
+ - 廃止: `Form::Label` / `Form::Control` / `Form::Description` / `Form::Message`。
405
+ ラベルと説明は `Shadcn::Field::Label` / `Shadcn::Field::Description` を直接使う
406
+ - 属性変更: ラベルの `data-error` → Field 構造の `data-invalid`(破壊的変更)。
407
+ `aria-invalid` / `aria-describedby` / `for`-`id` の紐付けは従来どおり呼び出し側責務
408
+ - 契約: `vendor/shadcn/overrides/items/form.json` を「旧スタイルの逐語コピー」から
409
+ 独自契約(オリジナルソース)へ書き換え。`registryDependencies` は `field` のみ
410
+ (react-hook-form / zod 等のnpm依存は解消)。FormField の孤児契約も消滅
411
+ - 関連更新: `Field::Error` も upstream 準拠で「本文無ければ非描画」に。
412
+ `Shadcn::Field` が upstream と同様に `data-orientation` を出力するように。
413
+ `Field::Label` は upstream と同じく `<Label>` の契約クラスを実行時合成する
414
+ (適合試験は allowances の `class_mode: contains` で緩和)。
415
+ field プレビュー(`field/default` / `field/horizontal`)と visual parity
416
+ シナリオを追加し、form の parity デモを react-hook-form 非依存に書き換え。
417
+ parity参照サーバのビルド入力が変わっても再ビルドされない
418
+ `parity_server.rb` の `stale?` 判定(比較演算の向き)を修正
419
+ - direction(Issue #3): base-nova は re-export のみで抽出可能な契約面が無いため
420
+ **現行維持**(手書き `DirectionProvider` + local-override)。決定は
421
+ docs.local/00-overview §5 決定ログに記録
422
+
423
+ ### スタイル移行: new-york-v4 → base-nova(破壊的変更)
424
+
425
+ 公式ドキュメントのデフォルトがbase系プリセットへ移行した(docsの`/docs/components/*`は
426
+ baseページへ307リダイレクト、CLI `init -d`は`--preset=base-nova`、`new-york-v4`はCLIの
427
+ `FALLBACK_STYLE`=レガシー配信)ことに追従し、vendoring対象スタイルを`base-nova`へ移行した。
428
+
429
+ - 契約: 全60コンポーネントのクラス文字列がbase-novaに更新(Badge destructive は
430
+ `bg-destructive/10 text-destructive` の淡い表現へ。公式docs表示と一致)
431
+ - 属性契約: `data-state=open/closed` → `data-open` / `data-closed`(Base UI規約)。
432
+ accordion / dialog / sheet / drawer / popover / hover_card / tabs / toggle 系の
433
+ コントローラ・コンポーネントを更新
434
+ - 廃止対応: base-novaに存在しない `Popover::Anchor` / `Select` ルート契約 /
435
+ `NavigationMenu::Viewport` を非対応化(または削除)。`form` / `direction` は
436
+ upstreamから提供が無い(または re-export のみ)ため
437
+ `vendor/shadcn/overrides/items/`(origin: local-override)として現行維持
438
+ - 抽出器: Base UI `useRender` パターンをJSX形状へ機械変換する対応を追加
439
+ (`parse/userender.ts`)。`IconPlaceholder` / キャメルケースprops(DOM属性でない)の除去
440
+ - 新規未対応: `questionnaire` / `toast`(個別評価)
441
+ - 検証: 適合試験・コントラクト整合は全件更新。visual parity のbaselineは
442
+ base-nova描画で再生成
443
+
444
+ ### upstream出所
445
+
446
+ - 出所: `vendor/shadcn/manifest.json` を参照(tag / resolved_sha / fetched_at)
447
+ - 初期スナップショット: shadcn@4.19.0(2026-08-27取得、registry:ui 61アイテム + neutralテーマ)
448
+ - 注: upstreamインデックスに列挙されているが404となるアイテム(questionnaire, toast)は
449
+ 「upstream側の不整合」として警告付きスキップ
450
+
451
+ ### レビュー対応(実装後)
452
+
453
+ 3エージェントによるコードレビュー(Ruby実装・抽出器・テスト/JS)の指摘を
454
+ 8コミットで修正。主要なもの:
455
+
456
+ - 抽出器: cn() 引数順序の保全(tailwind-merge の後勝ちを upstream と同一に)、
457
+ enum ガード(side === "right" && ...)の露出prop化、boolean 既定値による
458
+ 偽陽性クラスの除去、依存アイテムの sha256 検証、defaults 優先順位の統一、
459
+ ソート比較器のコードユニット順統一、check のオプション拒否など
460
+ - コンポーネント: void要素ヘルパ(void_tag)統一、利用者 data/aria/style の
461
+ マージ規約適用漏れ一括解消、NativeSelect のフォーム属性送達、
462
+ Pagination::Link の Boolean 受け、Combobox インジケータの hidden 化など
463
+ - JS/スペック: キー操作二重発火の解消、calendar スペックの時限爆弾解消、
464
+ 非同期イベント後の再試行付き検証への統一、showAt クランプ修正、
465
+ disconnect のリスナー除去漏れ解消
466
+ - 重複削減: メニュートリオ(dropdown/context/menubar)を継承で 476→217行に畳み込み
467
+
468
+ ### 追加(Phase 4 最終 — calendar の個別評価)
469
+
470
+ - Calendar(+DayButton): react-day-picker に依存しない月テーブル(年月キャプション・
471
+ 曜行・日付ボタン・前後月への GET リンク)。完全JSレス(Graceful)
472
+ - 契約は lib/shadcn_view_components/contracts/calendar.rb に個別契約として
473
+ 手動で保守(クラス値は tools/extractor と同一の cva + tailwind-merge で事前解決。
474
+ 生成物とは異なり rake shadcn:generate の対象外)
475
+ - 整合スペック: registry と targets.json + 個別契約の三方比較に拡張
476
+ - これにより vendor 61アイテムすべてが実装(適合試験対象)
477
+
478
+ ### 追加(Phase 4 wave2/3 — 重量級)
479
+
480
+ - sidebar(23エクスポート): Provider の data-state による開閉、Trigger/Rail、
481
+ メニュー階層(Menu/Sub)、Skeleton合成。Turboキャッシュ復帰相当の
482
+ 再接続冪等性システムスペック付き(05 §6.2)
483
+ - attachment(9)/bubble(4)/message(6)/message-scroller(6):
484
+ チャット・添付の静的構造。message-scroller は追従と「一番下へ」ボタン付き
485
+ - chart(4): recharts に依存しない容器・凡例・ツールチップ構造
486
+ (描画はホストが選ぶ — 個別評価)
487
+ - sonner(Toaster): shadcn:toast CustomEvent で通知を追加するStimulus実装
488
+ - calendar は react-day-picker の実行時クラス合成のため静的抽出対象外とし、
489
+ 個別評価として pending で明示(10-roadmap Phase 4)
490
+
491
+ ### 追加(Phase 4 wave1 — 残存フォーム部品・コンテナ)
492
+
493
+ - 9アイテム / 47エクスポート: Progress, Slider, NativeSelect(+OptGroup/Option),
494
+ InputOTP(+Group/Slot/Separator), Select(+Trigger/Value/Content/Group/Item/Label/
495
+ Separator/ScrollUp/ScrollDownButton), Field(+Content/Description/Error/Group/
496
+ Label/Legend/Separator/Set/Title), InputGroup(+Addon/Button/Input/Textarea/Text),
497
+ ButtonGroup(+Separator/Text), DirectionProvider
498
+ - ネイティブ最優先の継続: slider は input[type=range]、native-select は素の
499
+ select/optgroup/option、select は Popover API listbox、input-otp は
500
+ autocomplete=one-time-code の素のinput
501
+ - 抽出器: cva のバリアント値・compound における文字列配列の連結対応(field)
502
+ - InputOTP の autoload mappingはengine内の対象fileだけに限定し、hostの命名規則に影響させない
503
+ - 残る未実装は重量級8アイテム(sidebar/calendar/chart/sonner/attachment/bubble/
504
+ message/message-scroller)— registry.yml の pending で負債を可視化
505
+
506
+ ### 追加(Phase 3 — オーバーレイ・メニュー系)
507
+
508
+ - 14アイテム / 100以上のエクスポート:
509
+ Dialog, AlertDialog, Sheet, Drawer, Popover, HoverCard, Tooltip,
510
+ DropdownMenu, ContextMenu, Menubar, NavigationMenu, Command, Combobox, Resizable
511
+ - ネイティブ最優先の本番(05 §3 / 10-roadmap Phase 3):
512
+ - dialog系は `<dialog>` + showModal(フォーカストラップ・背景inert・EscClose・
513
+ フォーカス復帰はAlertDialogを含めてネイティブ提供)
514
+ - popover/tooltip/menu は Popover API(light dismiss)。context-menu は
515
+ 右クリック位置に popover=manual で開く(イベント列の競合回避)
516
+ - resizable はドラッグ + 矢印キーによるパネル配分
517
+ - command/combobox は SSR済みリストのフィルタ(value+本文照合、
518
+ 矢印/Home/End/Enter、空グループ畳み込み、empty表示)
519
+ - Stimulusコントローラ: dialog / popover / hover-card / tooltip / menu /
520
+ resizable / command(計8個、register()で一括登録)
521
+ - 抽出器の拡張: 引数なしcva呼び出し、`side === "right" && "クラス"` 形式の
522
+ 条件付き静的クラス解決、兄弟エクスポートのルート継承条件の厳密化、
523
+ asChild のDOM属性除外、JSXを返さないエクスポート除外、名前無しラッパーの
524
+ スロット記録
525
+ - 適合試験: 合成コンポーネント向け slots_mode: superset、
526
+ 静的クラスのみの契約向けフォールバック検証
527
+ - turbo:submit-end 標準フック(dialog内フォーム送信で閉じる)
528
+ - システムスペック: 開閉/Esc/inert(Tabトラップ)/フォーカス復帰/
529
+ light dismiss/hover intent/矢印キー/右クリック/ドラッグ・ナッジ/フィルタ
530
+
531
+ ### 追加(Phase 2 wave2 — tabs/carousel/pagination/form)
532
+
533
+ - 4アイテム / 22エクスポート: Tabs(+List/Trigger/Content), Carousel(+Content/Item/Previous/Next),
534
+ Pagination(+Content/Item/Link/Previous/Next/Ellipsis), Form(+Item/Label/Control/Description/Message)
535
+ - 抽出器の拡張(条件付きバリアントの契約化):
536
+ - `cva({ variant: isActive ? "outline" : "ghost", size })` のような呼び出し側制約を
537
+ 条件識別子の真偽2値 × passthrough全値域の組合せとして列挙(snake_case で契約側prop化)
538
+ - `orientation === "horizontal" ? A : B` の静的クラス分岐をファイルスコープの
539
+ パラメータ既定値で解決(carousel)
540
+ - 子コンポーネント経由でルートを描くエクスポート(PaginationPrevious/Next)は
541
+ 同一アイテム内の兄弟エクスポートのルートスロットを継承
542
+ - コンポーネント参照タグへの variant/size 属性はDOM属性ではないため契約から除外
543
+ - JSXを返さないエクスポート(useFormField等)を契約対象から除外
544
+ - Tabs: ARIA tabsパターン + roving tabindex(矢印キー移動・aria-selected・パネル hidden 切替)
545
+ - Carousel: embla を使わない生スクロールでの再実装(ナビの有効化状態管理)
546
+ - Form: Rails流の再解釈(aria-invalid/data-error 連携、Messageは本文が無ければ描かない)
547
+ - Phase 2 のDoD: form_with統合スペック(送出・バリデーションエラー表示)、
548
+ キーボード操作スペック、JS無効時フォールバック分類の契約コメント化
549
+ - Lookbookプレビュー4種追加(計30種)
550
+
551
+ ### 追加(Phase 2 wave1 — フォーム部品・軽インタラクティブ)
552
+
553
+ - 8アイテム / 17エクスポート: Accordion(+Item/Trigger/Content), Checkbox, Collapsible(+Trigger/Content),
554
+ RadioGroup(+Item), ScrollArea(+Scrollbar), Switch, Toggle, ToggleGroup(+Item)
555
+ - ネイティブ最優先設計(05 §3): checkbox/switch/radio は素のinput、accordion/collapsible は
556
+ `<details>`/`<summary>` でJS無し開閉(summaryはdetailsの直接子である必要がある)、
557
+ toggle/toggle-group は button + data-state + Stimulusコントローラ
558
+ - Stimulusコントローラ(toggle / toggle-group)と `ShadcnViewComponents.register(application)`
559
+ 登録ヘルパ、importmap環境でも解決できるベア指定子import
560
+ - 抽出器の拡張: registryDependencies 経由のcva定義解決(toggle-group → toggleVariants)、
561
+ 静的クラスのみのサブ要素cn(switch thumb)の static_attributes マージ
562
+ - システムスペック(層3): data-state/aria-pressed遷移、単一排他、ネイティブdetails開閉
563
+ - Lookbookプレビュー8種追加(計26種)
564
+
565
+ ### 追加(Phase 1 — 表示のみコンポーネント)
566
+
567
+ - 17アイテム / 60エクスポート: Badge, Alert, Card(+Header/Title/Description/Action/Content/Footer),
568
+ Avatar(+Image/Fallback/Badge/Group/Group::Count), Separator, Skeleton, Table(+7部位),
569
+ Label, Kbd(+Group), Spinner, Empty(+5部位), AspectRatio, Item(+9部位), Marker(+2部位),
570
+ Input, Textarea, Breadcrumb(+6部位)
571
+ - 抽出器の拡張: cva defaultVariants 未指定時のパラメータ既定値、data-slot を持たない
572
+ ルート(spinner等)、cn を経ない静的className(table-container等)、classes_slot
573
+ (契約クラスがルート以外の要素に属する構造の検証対象特定)
574
+ - 複合エクスポート対応の適合試験(registry.yml の exports リスト)と
575
+ class_mode: contains の allowances(upstream が実行時に別アイテムのクラスを合成する構造)
576
+ - Lookbookプレビュー18種、コンポーネントスペック、targets/registry/generated 三方整合スペック
577
+
578
+ ### 追加(Phase 0)
579
+
580
+ - 生成パイプライン: `rake shadcn:sync` / `extract` / `generate` / `update` / `check`
581
+ (tools/extractor: Node + TypeScript + Babel AST + cva/tailwind-merge事前解決)
582
+ - `Shadcn::Button`(全バリアント×サイズ組み合わせの適合試験つき)
583
+ - `ShadcnViewComponents::Classes` ランタイムクラス解決ヘルパ
584
+ - エンジン(Sprockets/Propshaft用アセットパス + importmap-rails自動pin)
585
+ - インストーラ `bin/rails g shadcn_view_components:install`(冪等)
586
+ - テーマCSS生成(oklch変数 / `@theme inline` / `.dark`)
587
+ - Sorbet `typed: strict` 全面 + tapioca RBI コミット
588
+ - CI(ci.yml: lint / sorbet / rspec / system / determinism / tailwind-build)
589
+ - 週次ドリフト検知 + 自動PR(upstream-drift.yml)
590
+ - Lookbookプレビュー(spec/dummy)とCupriteシステムスペック