shadcn-rails 0.1.0 → 0.2.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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -2
  3. data/README.md +102 -1398
  4. data/__mocks__/@floating-ui/dom.js +67 -0
  5. data/app/assets/javascripts/shadcn/controllers/base_menu_controller.js +266 -0
  6. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +34 -8
  7. data/app/assets/javascripts/shadcn/controllers/command_controller.js +5 -1
  8. data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +64 -135
  9. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +56 -186
  10. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
  11. data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +10 -7
  12. data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +10 -6
  13. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +35 -60
  14. data/app/assets/javascripts/shadcn/controllers/select_controller.js +37 -17
  15. data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +24 -14
  16. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
  17. data/app/assets/javascripts/shadcn/index.js +9 -1
  18. data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
  19. data/app/assets/stylesheets/shadcn/base.css +32 -0
  20. data/app/assets/stylesheets/shadcn/components.css +12 -0
  21. data/app/components/shadcn/accordion_component.html.erb +8 -0
  22. data/app/components/shadcn/accordion_component.rb +6 -15
  23. data/app/components/shadcn/alert_component.html.erb +6 -0
  24. data/app/components/shadcn/alert_component.rb +0 -18
  25. data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
  26. data/app/components/shadcn/alert_dialog_component.rb +7 -27
  27. data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
  28. data/app/components/shadcn/aspect_ratio_component.rb +4 -19
  29. data/app/components/shadcn/avatar_component.html.erb +20 -0
  30. data/app/components/shadcn/avatar_component.rb +8 -36
  31. data/app/components/shadcn/badge_component.html.erb +1 -0
  32. data/app/components/shadcn/badge_component.rb +0 -11
  33. data/app/components/shadcn/base_component.rb +15 -2
  34. data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
  35. data/app/components/shadcn/breadcrumb_component.rb +6 -16
  36. data/app/components/shadcn/button_component.html.erb +18 -0
  37. data/app/components/shadcn/button_component.rb +1 -41
  38. data/app/components/shadcn/card_component.html.erb +8 -0
  39. data/app/components/shadcn/card_component.rb +2 -6
  40. data/app/components/shadcn/checkbox_component.html.erb +32 -0
  41. data/app/components/shadcn/checkbox_component.rb +4 -43
  42. data/app/components/shadcn/collapsible_component.html.erb +8 -0
  43. data/app/components/shadcn/collapsible_component.rb +6 -15
  44. data/app/components/shadcn/command_list_component.rb +29 -14
  45. data/app/components/shadcn/context_menu_checkbox_item_component.rb +76 -0
  46. data/app/components/shadcn/context_menu_component.html.erb +11 -0
  47. data/app/components/shadcn/context_menu_component.rb +6 -26
  48. data/app/components/shadcn/context_menu_content_component.rb +37 -14
  49. data/app/components/shadcn/context_menu_item_component.rb +3 -2
  50. data/app/components/shadcn/context_menu_radio_group_component.rb +42 -0
  51. data/app/components/shadcn/context_menu_radio_item_component.rb +76 -0
  52. data/app/components/shadcn/dialog_component.html.erb +14 -0
  53. data/app/components/shadcn/dialog_component.rb +8 -29
  54. data/app/components/shadcn/drawer_component.html.erb +12 -0
  55. data/app/components/shadcn/drawer_component.rb +7 -27
  56. data/app/components/shadcn/dropdown_menu_checkbox_item_component.rb +76 -0
  57. data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
  58. data/app/components/shadcn/dropdown_menu_component.rb +9 -29
  59. data/app/components/shadcn/dropdown_menu_content_component.rb +45 -16
  60. data/app/components/shadcn/dropdown_menu_radio_group_component.rb +42 -0
  61. data/app/components/shadcn/dropdown_menu_radio_item_component.rb +76 -0
  62. data/app/components/shadcn/field_component.rb +7 -8
  63. data/app/components/shadcn/hover_card_component.html.erb +12 -0
  64. data/app/components/shadcn/hover_card_component.rb +7 -26
  65. data/app/components/shadcn/input_component.html.erb +18 -0
  66. data/app/components/shadcn/input_component.rb +2 -27
  67. data/app/components/shadcn/input_otp_component.rb +3 -3
  68. data/app/components/shadcn/kbd_component.html.erb +1 -0
  69. data/app/components/shadcn/kbd_component.rb +3 -10
  70. data/app/components/shadcn/label_component.html.erb +3 -0
  71. data/app/components/shadcn/label_component.rb +2 -18
  72. data/app/components/shadcn/menubar_component.html.erb +6 -0
  73. data/app/components/shadcn/menubar_component.rb +4 -15
  74. data/app/components/shadcn/menubar_content_component.rb +45 -20
  75. data/app/components/shadcn/menubar_sub_content_component.rb +21 -8
  76. data/app/components/shadcn/native_select_component.html.erb +22 -0
  77. data/app/components/shadcn/native_select_component.rb +9 -39
  78. data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
  79. data/app/components/shadcn/navigation_menu_component.rb +4 -15
  80. data/app/components/shadcn/pagination_component.html.erb +5 -0
  81. data/app/components/shadcn/pagination_component.rb +11 -15
  82. data/app/components/shadcn/popover_component.html.erb +15 -0
  83. data/app/components/shadcn/popover_component.rb +10 -30
  84. data/app/components/shadcn/progress_component.html.erb +13 -0
  85. data/app/components/shadcn/progress_component.rb +6 -26
  86. data/app/components/shadcn/radio_group_component.html.erb +8 -0
  87. data/app/components/shadcn/radio_group_component.rb +12 -26
  88. data/app/components/shadcn/radio_group_item_component.rb +32 -6
  89. data/app/components/shadcn/resizable_panel_group_component.rb +27 -16
  90. data/app/components/shadcn/scroll_area_component.html.erb +7 -0
  91. data/app/components/shadcn/scroll_area_component.rb +4 -16
  92. data/app/components/shadcn/select_component.html.erb +46 -0
  93. data/app/components/shadcn/select_component.rb +29 -86
  94. data/app/components/shadcn/separator_component.html.erb +5 -0
  95. data/app/components/shadcn/separator_component.rb +6 -14
  96. data/app/components/shadcn/sheet_component.html.erb +12 -0
  97. data/app/components/shadcn/sheet_component.rb +7 -27
  98. data/app/components/shadcn/sidebar_component.rb +2 -2
  99. data/app/components/shadcn/skeleton_component.html.erb +1 -0
  100. data/app/components/shadcn/skeleton_component.rb +4 -2
  101. data/app/components/shadcn/slider_component.html.erb +12 -0
  102. data/app/components/shadcn/slider_component.rb +2 -21
  103. data/app/components/shadcn/spinner_component.html.erb +18 -0
  104. data/app/components/shadcn/spinner_component.rb +2 -30
  105. data/app/components/shadcn/switch_component.html.erb +72 -0
  106. data/app/components/shadcn/switch_component.rb +4 -82
  107. data/app/components/shadcn/table_component.html.erb +9 -0
  108. data/app/components/shadcn/table_component.rb +2 -10
  109. data/app/components/shadcn/tabs_component.html.erb +8 -0
  110. data/app/components/shadcn/tabs_component.rb +4 -17
  111. data/app/components/shadcn/textarea_component.html.erb +13 -0
  112. data/app/components/shadcn/textarea_component.rb +6 -22
  113. data/app/components/shadcn/toast_component.html.erb +36 -0
  114. data/app/components/shadcn/toast_component.rb +6 -54
  115. data/app/components/shadcn/toggle_component.html.erb +12 -0
  116. data/app/components/shadcn/toggle_component.rb +6 -21
  117. data/app/components/shadcn/toggle_group_component.html.erb +14 -0
  118. data/app/components/shadcn/toggle_group_component.rb +6 -29
  119. data/app/components/shadcn/tooltip_component.html.erb +20 -0
  120. data/app/components/shadcn/tooltip_component.rb +13 -38
  121. data/lib/generators/shadcn/add/USAGE +24 -0
  122. data/lib/generators/shadcn/add/add_generator.rb +279 -0
  123. data/lib/generators/shadcn/install/USAGE +22 -0
  124. data/lib/generators/shadcn/install/install_generator.rb +8 -3
  125. data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
  126. data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
  127. data/lib/shadcn/rails/version.rb +1 -1
  128. metadata +54 -42
  129. data/.dockerignore +0 -40
  130. data/CLAUDE.md +0 -463
  131. data/PROGRESS.md +0 -485
  132. data/Rakefile +0 -29
  133. data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
  134. data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
  135. data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
  136. data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
  137. data/__tests__/controllers/accordion_controller.test.js +0 -904
  138. data/__tests__/controllers/calendar_controller.test.js +0 -1370
  139. data/__tests__/controllers/carousel_controller.test.js +0 -912
  140. data/__tests__/controllers/checkbox_controller.test.js +0 -454
  141. data/__tests__/controllers/collapsible_controller.test.js +0 -407
  142. data/__tests__/controllers/combobox_controller.test.js +0 -966
  143. data/__tests__/controllers/context_menu_controller.test.js +0 -627
  144. data/__tests__/controllers/date_picker_controller.test.js +0 -636
  145. data/__tests__/controllers/dialog_controller.test.js +0 -878
  146. data/__tests__/controllers/drawer_controller.test.js +0 -995
  147. data/__tests__/controllers/menubar_controller.test.js +0 -736
  148. data/__tests__/controllers/navigation_menu_controller.test.js +0 -598
  149. data/__tests__/controllers/popover_controller.test.js +0 -1007
  150. data/__tests__/controllers/radio_group_controller.test.js +0 -640
  151. data/__tests__/controllers/resizable_controller.test.js +0 -680
  152. data/__tests__/controllers/select_controller.test.js +0 -674
  153. data/__tests__/controllers/sheet_controller.test.js +0 -986
  154. data/__tests__/controllers/slider_controller.test.js +0 -1036
  155. data/__tests__/controllers/switch_controller.test.js +0 -424
  156. data/__tests__/controllers/tabs_controller.test.js +0 -907
  157. data/__tests__/controllers/toggle_group_controller.test.js +0 -839
  158. data/__tests__/controllers/tooltip_controller.test.js +0 -808
  159. data/__tests__/helpers/stimulus-test-helper.js +0 -203
  160. data/babel.config.cjs +0 -5
  161. data/bin/console +0 -11
  162. data/bin/setup +0 -8
  163. data/jest.config.js +0 -19
  164. data/jest.setup.js +0 -8
  165. data/lib/generators/shadcn/component/component_generator.rb +0 -188
  166. data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
  167. data/package-lock.json +0 -7415
  168. data/package.json +0 -68
  169. data/rollup.config.js +0 -29
@@ -1,454 +0,0 @@
1
- import { Application } from "@hotwired/stimulus"
2
- import CheckboxController from "../../app/assets/javascripts/shadcn/controllers/checkbox_controller.js"
3
- import { setupController, cleanupController, click, nextFrame, keydown } from '../helpers/stimulus-test-helper.js'
4
-
5
- describe("CheckboxController", () => {
6
- let application
7
- let element
8
- let controller
9
-
10
- afterEach(() => {
11
- cleanupController(application)
12
- })
13
-
14
- describe("basic rendering and initialization", () => {
15
- const basicHTML = `
16
- <button data-controller="shadcn--checkbox"
17
- data-shadcn--checkbox-checked-value="false"
18
- data-shadcn--checkbox-name-value="agree"
19
- type="button"
20
- role="checkbox"
21
- aria-checked="false"
22
- data-action="click->shadcn--checkbox#toggle">
23
- <svg style="opacity: 0;">✓</svg>
24
- </button>
25
- `
26
-
27
- beforeEach(async () => {
28
- const setup = await setupController(CheckboxController, basicHTML, 'shadcn--checkbox')
29
- application = setup.application
30
- element = setup.element
31
- controller = setup.controller
32
- })
33
-
34
- test("initializes with unchecked state", () => {
35
- expect(controller.checkedValue).toBe(false)
36
- })
37
-
38
- test("sets data-state unchecked on element", () => {
39
- expect(element.dataset.state).toBe("unchecked")
40
- })
41
-
42
- test("sets aria-checked false on element", () => {
43
- expect(element.getAttribute("aria-checked")).toBe("false")
44
- })
45
-
46
- test("hides checkmark icon initially", () => {
47
- const svg = element.querySelector("svg")
48
- expect(svg.style.opacity).toBe("0")
49
- })
50
-
51
- test("initializes with name value", () => {
52
- expect(controller.nameValue).toBe("agree")
53
- })
54
- })
55
-
56
- describe("toggle functionality", () => {
57
- const toggleHTML = `
58
- <div>
59
- <button data-controller="shadcn--checkbox"
60
- data-shadcn--checkbox-checked-value="false"
61
- data-shadcn--checkbox-name-value="terms"
62
- type="button"
63
- role="checkbox"
64
- data-action="click->shadcn--checkbox#toggle">
65
- <svg style="opacity: 0;">✓</svg>
66
- </button>
67
- <input type="hidden" name="terms" value="0">
68
- </div>
69
- `
70
-
71
- beforeEach(async () => {
72
- const setup = await setupController(CheckboxController, toggleHTML, 'shadcn--checkbox')
73
- application = setup.application
74
- element = setup.element
75
- controller = setup.controller
76
- })
77
-
78
- test("toggles from unchecked to checked", async () => {
79
- controller.toggle()
80
- await nextFrame()
81
-
82
- expect(controller.checkedValue).toBe(true)
83
- })
84
-
85
- test("toggles from checked to unchecked", async () => {
86
- controller.checkedValue = true
87
- controller.toggle()
88
- await nextFrame()
89
-
90
- expect(controller.checkedValue).toBe(false)
91
- })
92
-
93
- test("updates data-state on toggle", async () => {
94
- controller.toggle()
95
- await nextFrame()
96
-
97
- expect(element.dataset.state).toBe("checked")
98
- })
99
-
100
- test("updates aria-checked on toggle", async () => {
101
- controller.toggle()
102
- await nextFrame()
103
-
104
- expect(element.getAttribute("aria-checked")).toBe("true")
105
- })
106
-
107
- test("shows checkmark icon when checked", async () => {
108
- controller.toggle()
109
- await nextFrame()
110
-
111
- const svg = element.querySelector("svg")
112
- expect(svg.style.opacity).toBe("1")
113
- })
114
-
115
- test("hides checkmark icon when unchecked", async () => {
116
- controller.checkedValue = true
117
- controller.updateState()
118
- controller.toggle()
119
- await nextFrame()
120
-
121
- const svg = element.querySelector("svg")
122
- expect(svg.style.opacity).toBe("0")
123
- })
124
-
125
- test("dispatches change event on toggle", async () => {
126
- let eventDetail = null
127
- element.addEventListener("shadcn--checkbox:change", (e) => {
128
- eventDetail = e.detail
129
- })
130
-
131
- controller.toggle()
132
- await nextFrame()
133
-
134
- expect(eventDetail).not.toBeNull()
135
- expect(eventDetail.checked).toBe(true)
136
- })
137
-
138
- test("dispatches change event with false when unchecking", async () => {
139
- controller.checkedValue = true
140
- let eventDetail = null
141
- element.addEventListener("shadcn--checkbox:change", (e) => {
142
- eventDetail = e.detail
143
- })
144
-
145
- controller.toggle()
146
- await nextFrame()
147
-
148
- expect(eventDetail.checked).toBe(false)
149
- })
150
- })
151
-
152
- describe("hidden input synchronization", () => {
153
- const inputSyncHTML = `
154
- <div>
155
- <button data-controller="shadcn--checkbox"
156
- data-shadcn--checkbox-checked-value="false"
157
- data-shadcn--checkbox-name-value="subscribe"
158
- type="button"
159
- data-action="click->shadcn--checkbox#toggle">
160
- <svg style="opacity: 0;">✓</svg>
161
- </button>
162
- <input type="hidden" name="subscribe" value="0">
163
- </div>
164
- `
165
-
166
- beforeEach(async () => {
167
- const setup = await setupController(CheckboxController, inputSyncHTML, 'shadcn--checkbox')
168
- application = setup.application
169
- element = setup.element
170
- controller = setup.controller
171
- })
172
-
173
- test("updates hidden input to 1 when checked", async () => {
174
- controller.toggle()
175
- await nextFrame()
176
-
177
- const input = element.parentElement.querySelector('input[name="subscribe"]')
178
- expect(input.value).toBe("1")
179
- })
180
-
181
- test("updates hidden input to 0 when unchecked", async () => {
182
- controller.checkedValue = true
183
- controller.updateHiddenInput()
184
-
185
- controller.toggle()
186
- await nextFrame()
187
-
188
- const input = element.parentElement.querySelector('input[name="subscribe"]')
189
- expect(input.value).toBe("0")
190
- })
191
- })
192
-
193
- describe("initial checked state", () => {
194
- const checkedHTML = `
195
- <div>
196
- <button data-controller="shadcn--checkbox"
197
- data-shadcn--checkbox-checked-value="true"
198
- data-shadcn--checkbox-name-value="remember"
199
- type="button"
200
- role="checkbox"
201
- aria-checked="true"
202
- data-action="click->shadcn--checkbox#toggle">
203
- <svg style="opacity: 1;">✓</svg>
204
- </button>
205
- <input type="hidden" name="remember" value="1">
206
- </div>
207
- `
208
-
209
- beforeEach(async () => {
210
- const setup = await setupController(CheckboxController, checkedHTML, 'shadcn--checkbox')
211
- application = setup.application
212
- element = setup.element
213
- controller = setup.controller
214
- })
215
-
216
- test("initializes with checked state", () => {
217
- expect(controller.checkedValue).toBe(true)
218
- })
219
-
220
- test("sets data-state checked on init", () => {
221
- expect(element.dataset.state).toBe("checked")
222
- })
223
-
224
- test("sets aria-checked true on init", () => {
225
- expect(element.getAttribute("aria-checked")).toBe("true")
226
- })
227
-
228
- test("shows checkmark on init", () => {
229
- const svg = element.querySelector("svg")
230
- expect(svg.style.opacity).toBe("1")
231
- })
232
- })
233
-
234
- describe("programmatic value change", () => {
235
- const programmaticHTML = `
236
- <button data-controller="shadcn--checkbox"
237
- data-shadcn--checkbox-checked-value="false"
238
- type="button">
239
- <svg style="opacity: 0;">✓</svg>
240
- </button>
241
- `
242
-
243
- beforeEach(async () => {
244
- const setup = await setupController(CheckboxController, programmaticHTML, 'shadcn--checkbox')
245
- application = setup.application
246
- element = setup.element
247
- controller = setup.controller
248
- })
249
-
250
- test("updates UI when checkedValue changes", async () => {
251
- controller.checkedValue = true
252
- await nextFrame()
253
-
254
- expect(element.dataset.state).toBe("checked")
255
- expect(element.getAttribute("aria-checked")).toBe("true")
256
- })
257
-
258
- test("checkedValueChanged callback updates state", async () => {
259
- const updateStateSpy = jest.spyOn(controller, 'updateState')
260
-
261
- controller.checkedValue = true
262
- await nextFrame()
263
-
264
- expect(updateStateSpy).toHaveBeenCalled()
265
- })
266
- })
267
-
268
- describe("without name value", () => {
269
- const noNameHTML = `
270
- <div>
271
- <button data-controller="shadcn--checkbox"
272
- data-shadcn--checkbox-checked-value="false"
273
- type="button"
274
- data-action="click->shadcn--checkbox#toggle">
275
- <svg style="opacity: 0;">✓</svg>
276
- </button>
277
- </div>
278
- `
279
-
280
- beforeEach(async () => {
281
- const setup = await setupController(CheckboxController, noNameHTML, 'shadcn--checkbox')
282
- application = setup.application
283
- element = setup.element
284
- controller = setup.controller
285
- })
286
-
287
- test("works without name value", async () => {
288
- expect(() => {
289
- controller.toggle()
290
- }).not.toThrow()
291
-
292
- expect(controller.checkedValue).toBe(true)
293
- })
294
-
295
- test("does not try to update non-existent hidden input", () => {
296
- expect(() => {
297
- controller.updateHiddenInput()
298
- }).not.toThrow()
299
- })
300
- })
301
-
302
- describe("without SVG icon", () => {
303
- const noIconHTML = `
304
- <button data-controller="shadcn--checkbox"
305
- data-shadcn--checkbox-checked-value="false"
306
- type="button"
307
- data-action="click->shadcn--checkbox#toggle">
308
- Check
309
- </button>
310
- `
311
-
312
- beforeEach(async () => {
313
- const setup = await setupController(CheckboxController, noIconHTML, 'shadcn--checkbox')
314
- application = setup.application
315
- element = setup.element
316
- controller = setup.controller
317
- })
318
-
319
- test("works without SVG icon", async () => {
320
- expect(() => {
321
- controller.toggle()
322
- }).not.toThrow()
323
-
324
- expect(controller.checkedValue).toBe(true)
325
- })
326
-
327
- test("updateState does not throw without SVG", () => {
328
- expect(() => {
329
- controller.updateState()
330
- }).not.toThrow()
331
- })
332
- })
333
-
334
- describe("multiple toggles", () => {
335
- const multipleHTML = `
336
- <button data-controller="shadcn--checkbox"
337
- data-shadcn--checkbox-checked-value="false"
338
- type="button"
339
- data-action="click->shadcn--checkbox#toggle">
340
- <svg style="opacity: 0;">✓</svg>
341
- </button>
342
- `
343
-
344
- beforeEach(async () => {
345
- const setup = await setupController(CheckboxController, multipleHTML, 'shadcn--checkbox')
346
- application = setup.application
347
- element = setup.element
348
- controller = setup.controller
349
- })
350
-
351
- test("handles multiple rapid toggles", async () => {
352
- controller.toggle() // true
353
- controller.toggle() // false
354
- controller.toggle() // true
355
- await nextFrame()
356
-
357
- expect(controller.checkedValue).toBe(true)
358
- })
359
-
360
- test("emits change event for each toggle", async () => {
361
- let changeCount = 0
362
- element.addEventListener("shadcn--checkbox:change", () => {
363
- changeCount++
364
- })
365
-
366
- controller.toggle()
367
- controller.toggle()
368
- controller.toggle()
369
- await nextFrame()
370
-
371
- expect(changeCount).toBe(3)
372
- })
373
-
374
- test("final state is correct after even number of toggles", async () => {
375
- controller.toggle()
376
- controller.toggle()
377
- controller.toggle()
378
- controller.toggle()
379
- await nextFrame()
380
-
381
- expect(controller.checkedValue).toBe(false)
382
- })
383
- })
384
-
385
- describe("click handler", () => {
386
- const clickHTML = `
387
- <button data-controller="shadcn--checkbox"
388
- data-shadcn--checkbox-checked-value="false"
389
- type="button"
390
- data-action="click->shadcn--checkbox#toggle">
391
- <svg style="opacity: 0;">✓</svg>
392
- </button>
393
- `
394
-
395
- beforeEach(async () => {
396
- const setup = await setupController(CheckboxController, clickHTML, 'shadcn--checkbox')
397
- application = setup.application
398
- element = setup.element
399
- controller = setup.controller
400
- })
401
-
402
- test("toggles on click", async () => {
403
- click(element)
404
- await nextFrame()
405
-
406
- expect(controller.checkedValue).toBe(true)
407
- })
408
-
409
- test("toggles again on second click", async () => {
410
- click(element)
411
- await nextFrame()
412
- click(element)
413
- await nextFrame()
414
-
415
- expect(controller.checkedValue).toBe(false)
416
- })
417
- })
418
-
419
- describe("edge cases", () => {
420
- const edgeCaseHTML = `
421
- <div>
422
- <button data-controller="shadcn--checkbox"
423
- data-shadcn--checkbox-checked-value="false"
424
- data-shadcn--checkbox-name-value="test"
425
- type="button"
426
- data-action="click->shadcn--checkbox#toggle">
427
- <svg style="opacity: 0;">✓</svg>
428
- </button>
429
- <input type="hidden" name="other" value="0">
430
- </div>
431
- `
432
-
433
- beforeEach(async () => {
434
- const setup = await setupController(CheckboxController, edgeCaseHTML, 'shadcn--checkbox')
435
- application = setup.application
436
- element = setup.element
437
- controller = setup.controller
438
- })
439
-
440
- test("does not update input with different name", async () => {
441
- controller.toggle()
442
- await nextFrame()
443
-
444
- const otherInput = element.parentElement.querySelector('input[name="other"]')
445
- expect(otherInput.value).toBe("0")
446
- })
447
-
448
- test("gracefully handles missing input with matching name", async () => {
449
- expect(() => {
450
- controller.toggle()
451
- }).not.toThrow()
452
- })
453
- })
454
- })