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
@@ -0,0 +1,378 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # !! AUTO-GENERATED by tools/extractor — DO NOT EDIT !!
5
+ # Source: shadcn/ui base-nova "context-menu" (item sha256: d712a605f27a1134c8a76d712fc20b64a019291bfa36de6659f3433147688ec5)
6
+ # Regenerate with: rake shadcn:generate
7
+
8
+ module ShadcnViewComponents
9
+ module Contracts
10
+ module ContextMenu
11
+ ROOT_SLOT = T.let("context-menu", String)
12
+
13
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
14
+ CLASSES_SLOT = T.let("", String)
15
+
16
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
17
+
18
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
19
+
20
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
21
+ COMBINATIONS = T.let({
22
+ {} => ""
23
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
24
+
25
+ SLOTS = T.let([
26
+ { name: "context-menu", tag: "ContextMenuPrimitive.Root", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
27
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
28
+
29
+ extend T::Sig
30
+
31
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
32
+ module_function def combination(options)
33
+ COMBINATIONS.fetch(options)
34
+ end
35
+ module CheckboxItem
36
+ ROOT_SLOT = T.let("context-menu-checkbox-item", String)
37
+
38
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
39
+
40
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
41
+
42
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
43
+ COMBINATIONS = T.let({
44
+ {} => "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
45
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
46
+
47
+ SLOTS = T.let([
48
+ { name: "context-menu-checkbox-item", tag: "ContextMenuPrimitive.CheckboxItem", static_attributes: {}.freeze, dynamic_attributes: ["checked", "data-inset"].freeze }.freeze
49
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
50
+
51
+ extend T::Sig
52
+
53
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
54
+ module_function def combination(options)
55
+ COMBINATIONS.fetch(options)
56
+ end
57
+ end
58
+ module Content
59
+ ROOT_SLOT = T.let("", String)
60
+
61
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
62
+ CLASSES_SLOT = T.let("context-menu-content", String)
63
+
64
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
65
+
66
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
67
+
68
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
69
+ COMBINATIONS = T.let({
70
+ {} => "cn-menu-target cn-menu-translucent z-50 max-h-(--available-height) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95"
71
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
72
+
73
+ SLOTS = T.let([
74
+ { name: "", tag: "ContextMenuPrimitive.Portal", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze,
75
+ { name: "context-menu-content", tag: "ContextMenuPrimitive.Popup", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
76
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
77
+
78
+ extend T::Sig
79
+
80
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
81
+ module_function def combination(options)
82
+ COMBINATIONS.fetch(options)
83
+ end
84
+ end
85
+ module Group
86
+ ROOT_SLOT = T.let("context-menu-group", String)
87
+
88
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
89
+ CLASSES_SLOT = T.let("", String)
90
+
91
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
92
+
93
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
94
+
95
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
96
+ COMBINATIONS = T.let({
97
+ {} => ""
98
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
99
+
100
+ SLOTS = T.let([
101
+ { name: "context-menu-group", tag: "ContextMenuPrimitive.Group", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
102
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
103
+
104
+ extend T::Sig
105
+
106
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
107
+ module_function def combination(options)
108
+ COMBINATIONS.fetch(options)
109
+ end
110
+ end
111
+ module Item
112
+ ROOT_SLOT = T.let("context-menu-item", String)
113
+
114
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
115
+
116
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
117
+
118
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
119
+ COMBINATIONS = T.let({
120
+ {} => "group/context-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:*:[svg]:text-accent-foreground data-[variant=destructive]:*:[svg]:text-destructive"
121
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
122
+
123
+ SLOTS = T.let([
124
+ { name: "context-menu-item", tag: "ContextMenuPrimitive.Item", static_attributes: {}.freeze, dynamic_attributes: ["data-inset", "data-variant"].freeze }.freeze
125
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
126
+
127
+ extend T::Sig
128
+
129
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
130
+ module_function def combination(options)
131
+ COMBINATIONS.fetch(options)
132
+ end
133
+ end
134
+ module Label
135
+ ROOT_SLOT = T.let("context-menu-label", String)
136
+
137
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
138
+
139
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
140
+
141
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
142
+ COMBINATIONS = T.let({
143
+ {} => "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7"
144
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
145
+
146
+ SLOTS = T.let([
147
+ { name: "context-menu-label", tag: "ContextMenuPrimitive.GroupLabel", static_attributes: {}.freeze, dynamic_attributes: ["data-inset"].freeze }.freeze
148
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
149
+
150
+ extend T::Sig
151
+
152
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
153
+ module_function def combination(options)
154
+ COMBINATIONS.fetch(options)
155
+ end
156
+ end
157
+ module Portal
158
+ ROOT_SLOT = T.let("context-menu-portal", String)
159
+
160
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
161
+ CLASSES_SLOT = T.let("", String)
162
+
163
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
164
+
165
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
166
+
167
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
168
+ COMBINATIONS = T.let({
169
+ {} => ""
170
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
171
+
172
+ SLOTS = T.let([
173
+ { name: "context-menu-portal", tag: "ContextMenuPrimitive.Portal", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
174
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
175
+
176
+ extend T::Sig
177
+
178
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
179
+ module_function def combination(options)
180
+ COMBINATIONS.fetch(options)
181
+ end
182
+ end
183
+ module RadioGroup
184
+ ROOT_SLOT = T.let("context-menu-radio-group", String)
185
+
186
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
187
+ CLASSES_SLOT = T.let("", String)
188
+
189
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
190
+
191
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
192
+
193
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
194
+ COMBINATIONS = T.let({
195
+ {} => ""
196
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
197
+
198
+ SLOTS = T.let([
199
+ { name: "context-menu-radio-group", tag: "ContextMenuPrimitive.RadioGroup", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
200
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
201
+
202
+ extend T::Sig
203
+
204
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
205
+ module_function def combination(options)
206
+ COMBINATIONS.fetch(options)
207
+ end
208
+ end
209
+ module RadioItem
210
+ ROOT_SLOT = T.let("context-menu-radio-item", String)
211
+
212
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
213
+
214
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
215
+
216
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
217
+ COMBINATIONS = T.let({
218
+ {} => "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
219
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
220
+
221
+ SLOTS = T.let([
222
+ { name: "context-menu-radio-item", tag: "ContextMenuPrimitive.RadioItem", static_attributes: {}.freeze, dynamic_attributes: ["data-inset"].freeze }.freeze
223
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
224
+
225
+ extend T::Sig
226
+
227
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
228
+ module_function def combination(options)
229
+ COMBINATIONS.fetch(options)
230
+ end
231
+ end
232
+ module Separator
233
+ ROOT_SLOT = T.let("context-menu-separator", String)
234
+
235
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
236
+
237
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
238
+
239
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
240
+ COMBINATIONS = T.let({
241
+ {} => "-mx-1 my-1 h-px bg-border"
242
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
243
+
244
+ SLOTS = T.let([
245
+ { name: "context-menu-separator", tag: "ContextMenuPrimitive.Separator", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
246
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
247
+
248
+ extend T::Sig
249
+
250
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
251
+ module_function def combination(options)
252
+ COMBINATIONS.fetch(options)
253
+ end
254
+ end
255
+ module Shortcut
256
+ ROOT_SLOT = T.let("context-menu-shortcut", String)
257
+
258
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
259
+
260
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
261
+
262
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
263
+ COMBINATIONS = T.let({
264
+ {} => "ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground"
265
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
266
+
267
+ SLOTS = T.let([
268
+ { name: "context-menu-shortcut", tag: "span", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
269
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
270
+
271
+ extend T::Sig
272
+
273
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
274
+ module_function def combination(options)
275
+ COMBINATIONS.fetch(options)
276
+ end
277
+ end
278
+ module Sub
279
+ ROOT_SLOT = T.let("context-menu-sub", String)
280
+
281
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
282
+ CLASSES_SLOT = T.let("", String)
283
+
284
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
285
+
286
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
287
+
288
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
289
+ COMBINATIONS = T.let({
290
+ {} => ""
291
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
292
+
293
+ SLOTS = T.let([
294
+ { name: "context-menu-sub", tag: "ContextMenuPrimitive.SubmenuRoot", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
295
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
296
+
297
+ extend T::Sig
298
+
299
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
300
+ module_function def combination(options)
301
+ COMBINATIONS.fetch(options)
302
+ end
303
+ end
304
+ module SubContent
305
+ ROOT_SLOT = T.let("context-menu-sub-content", String)
306
+
307
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
308
+ CLASSES_SLOT = T.let("", String)
309
+
310
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
311
+
312
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
313
+
314
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
315
+ COMBINATIONS = T.let({
316
+ {} => ""
317
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
318
+
319
+ SLOTS = T.let([
320
+ { name: "context-menu-sub-content", tag: "ContextMenuContent", static_attributes: { class: "cn-menu-target cn-menu-translucent shadow-lg", side: "right" }.freeze, dynamic_attributes: [].freeze }.freeze
321
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
322
+
323
+ extend T::Sig
324
+
325
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
326
+ module_function def combination(options)
327
+ COMBINATIONS.fetch(options)
328
+ end
329
+ end
330
+ module SubTrigger
331
+ ROOT_SLOT = T.let("context-menu-sub-trigger", String)
332
+
333
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
334
+
335
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
336
+
337
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
338
+ COMBINATIONS = T.let({
339
+ {} => "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
340
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
341
+
342
+ SLOTS = T.let([
343
+ { name: "context-menu-sub-trigger", tag: "ContextMenuPrimitive.SubmenuTrigger", static_attributes: {}.freeze, dynamic_attributes: ["data-inset"].freeze }.freeze
344
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
345
+
346
+ extend T::Sig
347
+
348
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
349
+ module_function def combination(options)
350
+ COMBINATIONS.fetch(options)
351
+ end
352
+ end
353
+ module Trigger
354
+ ROOT_SLOT = T.let("context-menu-trigger", String)
355
+
356
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
357
+
358
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
359
+
360
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
361
+ COMBINATIONS = T.let({
362
+ {} => "select-none"
363
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
364
+
365
+ SLOTS = T.let([
366
+ { name: "context-menu-trigger", tag: "ContextMenuPrimitive.Trigger", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
367
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
368
+
369
+ extend T::Sig
370
+
371
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
372
+ module_function def combination(options)
373
+ COMBINATIONS.fetch(options)
374
+ end
375
+ end
376
+ end
377
+ end
378
+ end
@@ -0,0 +1,258 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # !! AUTO-GENERATED by tools/extractor — DO NOT EDIT !!
5
+ # Source: shadcn/ui base-nova "dialog" (item sha256: 72258057e1629a7872447f599b39ccfc7f91cc0dd6cba434671e2f16525bbd9a)
6
+ # Regenerate with: rake shadcn:generate
7
+
8
+ module ShadcnViewComponents
9
+ module Contracts
10
+ module Dialog
11
+ ROOT_SLOT = T.let("dialog", String)
12
+
13
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
14
+ CLASSES_SLOT = T.let("", String)
15
+
16
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
17
+
18
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
19
+
20
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
21
+ COMBINATIONS = T.let({
22
+ {} => ""
23
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
24
+
25
+ SLOTS = T.let([
26
+ { name: "dialog", tag: "DialogPrimitive.Root", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
27
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
28
+
29
+ extend T::Sig
30
+
31
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
32
+ module_function def combination(options)
33
+ COMBINATIONS.fetch(options)
34
+ end
35
+ module Close
36
+ ROOT_SLOT = T.let("dialog-close", String)
37
+
38
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
39
+ CLASSES_SLOT = T.let("", String)
40
+
41
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
42
+
43
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
44
+
45
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
46
+ COMBINATIONS = T.let({
47
+ {} => ""
48
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
49
+
50
+ SLOTS = T.let([
51
+ { name: "dialog-close", tag: "DialogPrimitive.Close", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
52
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
53
+
54
+ extend T::Sig
55
+
56
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
57
+ module_function def combination(options)
58
+ COMBINATIONS.fetch(options)
59
+ end
60
+ end
61
+ module Content
62
+ ROOT_SLOT = T.let("", String)
63
+
64
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
65
+ CLASSES_SLOT = T.let("dialog-content", String)
66
+
67
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
68
+
69
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
70
+
71
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
72
+ COMBINATIONS = T.let({
73
+ {} => "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95"
74
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
75
+
76
+ SLOTS = T.let([
77
+ { name: "", tag: "DialogPortal", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze,
78
+ { name: "dialog-content", tag: "DialogPrimitive.Popup", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze,
79
+ { name: "dialog-close", tag: "DialogPrimitive.Close", static_attributes: {}.freeze, dynamic_attributes: ["render"].freeze }.freeze
80
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
81
+
82
+ extend T::Sig
83
+
84
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
85
+ module_function def combination(options)
86
+ COMBINATIONS.fetch(options)
87
+ end
88
+ end
89
+ module Description
90
+ ROOT_SLOT = T.let("dialog-description", String)
91
+
92
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
93
+
94
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
95
+
96
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
97
+ COMBINATIONS = T.let({
98
+ {} => "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground"
99
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
100
+
101
+ SLOTS = T.let([
102
+ { name: "dialog-description", tag: "DialogPrimitive.Description", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
103
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
104
+
105
+ extend T::Sig
106
+
107
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
108
+ module_function def combination(options)
109
+ COMBINATIONS.fetch(options)
110
+ end
111
+ end
112
+ module Footer
113
+ ROOT_SLOT = T.let("dialog-footer", String)
114
+
115
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
116
+
117
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
118
+
119
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
120
+ COMBINATIONS = T.let({
121
+ {} => "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end"
122
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
123
+
124
+ SLOTS = T.let([
125
+ { name: "dialog-footer", tag: "div", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
126
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
127
+
128
+ extend T::Sig
129
+
130
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
131
+ module_function def combination(options)
132
+ COMBINATIONS.fetch(options)
133
+ end
134
+ end
135
+ module Header
136
+ ROOT_SLOT = T.let("dialog-header", String)
137
+
138
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
139
+
140
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
141
+
142
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
143
+ COMBINATIONS = T.let({
144
+ {} => "flex flex-col gap-2"
145
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
146
+
147
+ SLOTS = T.let([
148
+ { name: "dialog-header", tag: "div", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
149
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
150
+
151
+ extend T::Sig
152
+
153
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
154
+ module_function def combination(options)
155
+ COMBINATIONS.fetch(options)
156
+ end
157
+ end
158
+ module Overlay
159
+ ROOT_SLOT = T.let("dialog-overlay", String)
160
+
161
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
162
+
163
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
164
+
165
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
166
+ COMBINATIONS = T.let({
167
+ {} => "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0"
168
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
169
+
170
+ SLOTS = T.let([
171
+ { name: "dialog-overlay", tag: "DialogPrimitive.Backdrop", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
172
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
173
+
174
+ extend T::Sig
175
+
176
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
177
+ module_function def combination(options)
178
+ COMBINATIONS.fetch(options)
179
+ end
180
+ end
181
+ module Portal
182
+ ROOT_SLOT = T.let("dialog-portal", String)
183
+
184
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
185
+ CLASSES_SLOT = T.let("", String)
186
+
187
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
188
+
189
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
190
+
191
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
192
+ COMBINATIONS = T.let({
193
+ {} => ""
194
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
195
+
196
+ SLOTS = T.let([
197
+ { name: "dialog-portal", tag: "DialogPrimitive.Portal", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
198
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
199
+
200
+ extend T::Sig
201
+
202
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
203
+ module_function def combination(options)
204
+ COMBINATIONS.fetch(options)
205
+ end
206
+ end
207
+ module Title
208
+ ROOT_SLOT = T.let("dialog-title", String)
209
+
210
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
211
+
212
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
213
+
214
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
215
+ COMBINATIONS = T.let({
216
+ {} => "cn-font-heading text-base leading-none font-medium"
217
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
218
+
219
+ SLOTS = T.let([
220
+ { name: "dialog-title", tag: "DialogPrimitive.Title", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
221
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
222
+
223
+ extend T::Sig
224
+
225
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
226
+ module_function def combination(options)
227
+ COMBINATIONS.fetch(options)
228
+ end
229
+ end
230
+ module Trigger
231
+ ROOT_SLOT = T.let("dialog-trigger", String)
232
+
233
+ # 契約クラスが属する要素の data-slot(ルートがラッパー構造の場合)
234
+ CLASSES_SLOT = T.let("", String)
235
+
236
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
237
+
238
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
239
+
240
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
241
+ COMBINATIONS = T.let({
242
+ {} => ""
243
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
244
+
245
+ SLOTS = T.let([
246
+ { name: "dialog-trigger", tag: "DialogPrimitive.Trigger", static_attributes: {}.freeze, dynamic_attributes: [].freeze }.freeze
247
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
248
+
249
+ extend T::Sig
250
+
251
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
252
+ module_function def combination(options)
253
+ COMBINATIONS.fetch(options)
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,34 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # !! AUTO-GENERATED by tools/extractor — DO NOT EDIT !!
5
+ # Source: shadcn/ui base-nova "direction" (item sha256: 1d840f47e820da56f2879b948533a3d2e3f9eb99b03f653487b9b877c4f88b1b)
6
+ # Regenerate with: rake shadcn:generate
7
+
8
+ module ShadcnViewComponents
9
+ module Contracts
10
+ module DirectionProvider
11
+ ROOT_SLOT = T.let("", String)
12
+
13
+ DEFAULTS = T.let({}.freeze, T::Hash[Symbol, Symbol])
14
+
15
+ VARIANTS = T.let({}.freeze, T::Hash[Symbol, T::Array[Symbol]])
16
+
17
+ # キーはソート済みpropペア。値は事前解決済みの最終クラス文字列
18
+ COMBINATIONS = T.let({
19
+ {} => ""
20
+ }.freeze, T::Hash[T::Hash[Symbol, Symbol], String])
21
+
22
+ SLOTS = T.let([
23
+ { name: "", tag: "Direction.DirectionProvider", static_attributes: {}.freeze, dynamic_attributes: ["dir"].freeze }.freeze
24
+ ].freeze, T::Array[T::Hash[Symbol, T.untyped]])
25
+
26
+ extend T::Sig
27
+
28
+ sig { params(options: T::Hash[Symbol, Symbol]).returns(String) }
29
+ module_function def combination(options)
30
+ COMBINATIONS.fetch(options)
31
+ end
32
+ end
33
+ end
34
+ end