shadcn-rails 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -2
- data/README.md +21 -8
- data/__mocks__/@floating-ui/dom.js +67 -0
- data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +23 -2
- data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +4 -31
- data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +32 -41
- data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
- data/app/assets/javascripts/shadcn/controllers/popover_controller.js +29 -54
- data/app/assets/javascripts/shadcn/controllers/select_controller.js +26 -8
- data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
- data/app/assets/javascripts/shadcn/index.js +7 -1
- data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
- data/app/assets/stylesheets/shadcn/base.css +32 -0
- data/app/components/shadcn/accordion_component.html.erb +8 -0
- data/app/components/shadcn/accordion_component.rb +6 -15
- data/app/components/shadcn/alert_component.html.erb +6 -0
- data/app/components/shadcn/alert_component.rb +0 -18
- data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
- data/app/components/shadcn/alert_dialog_component.rb +7 -27
- data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
- data/app/components/shadcn/aspect_ratio_component.rb +4 -19
- data/app/components/shadcn/avatar_component.html.erb +20 -0
- data/app/components/shadcn/avatar_component.rb +8 -36
- data/app/components/shadcn/badge_component.html.erb +1 -0
- data/app/components/shadcn/badge_component.rb +0 -11
- data/app/components/shadcn/base_component.rb +15 -2
- data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
- data/app/components/shadcn/breadcrumb_component.rb +6 -16
- data/app/components/shadcn/button_component.html.erb +18 -0
- data/app/components/shadcn/button_component.rb +1 -41
- data/app/components/shadcn/card_component.html.erb +8 -0
- data/app/components/shadcn/card_component.rb +2 -6
- data/app/components/shadcn/checkbox_component.html.erb +32 -0
- data/app/components/shadcn/checkbox_component.rb +4 -43
- data/app/components/shadcn/collapsible_component.html.erb +8 -0
- data/app/components/shadcn/collapsible_component.rb +6 -15
- data/app/components/shadcn/context_menu_component.html.erb +11 -0
- data/app/components/shadcn/context_menu_component.rb +6 -26
- data/app/components/shadcn/dialog_component.html.erb +14 -0
- data/app/components/shadcn/dialog_component.rb +8 -29
- data/app/components/shadcn/drawer_component.html.erb +12 -0
- data/app/components/shadcn/drawer_component.rb +7 -27
- data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
- data/app/components/shadcn/dropdown_menu_component.rb +9 -29
- data/app/components/shadcn/field_component.rb +7 -8
- data/app/components/shadcn/hover_card_component.html.erb +12 -0
- data/app/components/shadcn/hover_card_component.rb +7 -26
- data/app/components/shadcn/input_component.html.erb +18 -0
- data/app/components/shadcn/input_component.rb +2 -27
- data/app/components/shadcn/input_otp_component.rb +3 -3
- data/app/components/shadcn/kbd_component.html.erb +1 -0
- data/app/components/shadcn/kbd_component.rb +3 -10
- data/app/components/shadcn/label_component.html.erb +3 -0
- data/app/components/shadcn/label_component.rb +2 -18
- data/app/components/shadcn/menubar_component.html.erb +6 -0
- data/app/components/shadcn/menubar_component.rb +4 -15
- data/app/components/shadcn/native_select_component.html.erb +22 -0
- data/app/components/shadcn/native_select_component.rb +9 -39
- data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
- data/app/components/shadcn/navigation_menu_component.rb +4 -15
- data/app/components/shadcn/pagination_component.html.erb +5 -0
- data/app/components/shadcn/pagination_component.rb +11 -15
- data/app/components/shadcn/popover_component.html.erb +15 -0
- data/app/components/shadcn/popover_component.rb +10 -30
- data/app/components/shadcn/progress_component.html.erb +13 -0
- data/app/components/shadcn/progress_component.rb +6 -26
- data/app/components/shadcn/radio_group_component.html.erb +8 -0
- data/app/components/shadcn/radio_group_component.rb +12 -26
- data/app/components/shadcn/scroll_area_component.html.erb +7 -0
- data/app/components/shadcn/scroll_area_component.rb +4 -16
- data/app/components/shadcn/select_component.html.erb +46 -0
- data/app/components/shadcn/select_component.rb +6 -80
- data/app/components/shadcn/separator_component.html.erb +5 -0
- data/app/components/shadcn/separator_component.rb +6 -14
- data/app/components/shadcn/sheet_component.html.erb +12 -0
- data/app/components/shadcn/sheet_component.rb +7 -27
- data/app/components/shadcn/sidebar_component.rb +2 -2
- data/app/components/shadcn/skeleton_component.html.erb +1 -0
- data/app/components/shadcn/skeleton_component.rb +4 -2
- data/app/components/shadcn/slider_component.html.erb +12 -0
- data/app/components/shadcn/slider_component.rb +2 -21
- data/app/components/shadcn/spinner_component.html.erb +18 -0
- data/app/components/shadcn/spinner_component.rb +2 -30
- data/app/components/shadcn/switch_component.html.erb +72 -0
- data/app/components/shadcn/switch_component.rb +4 -82
- data/app/components/shadcn/table_component.html.erb +9 -0
- data/app/components/shadcn/table_component.rb +2 -10
- data/app/components/shadcn/tabs_component.html.erb +8 -0
- data/app/components/shadcn/tabs_component.rb +4 -17
- data/app/components/shadcn/textarea_component.html.erb +13 -0
- data/app/components/shadcn/textarea_component.rb +6 -22
- data/app/components/shadcn/toast_component.html.erb +36 -0
- data/app/components/shadcn/toast_component.rb +6 -54
- data/app/components/shadcn/toggle_component.html.erb +12 -0
- data/app/components/shadcn/toggle_component.rb +6 -21
- data/app/components/shadcn/toggle_group_component.html.erb +14 -0
- data/app/components/shadcn/toggle_group_component.rb +6 -29
- data/app/components/shadcn/tooltip_component.html.erb +20 -0
- data/app/components/shadcn/tooltip_component.rb +13 -38
- data/lib/generators/shadcn/add/USAGE +24 -0
- data/lib/generators/shadcn/add/add_generator.rb +279 -0
- data/lib/generators/shadcn/install/USAGE +22 -0
- data/lib/generators/shadcn/install/install_generator.rb +8 -3
- data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
- data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
- data/lib/shadcn/rails/version.rb +1 -1
- metadata +47 -45
- data/.dockerignore +0 -40
- data/CLAUDE.md +0 -612
- data/PROGRESS.md +0 -495
- data/Rakefile +0 -95
- data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
- data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
- data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
- data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
- data/__tests__/controllers/accordion_controller.test.js +0 -904
- data/__tests__/controllers/calendar_controller.test.js +0 -1370
- data/__tests__/controllers/carousel_controller.test.js +0 -912
- data/__tests__/controllers/checkbox_controller.test.js +0 -454
- data/__tests__/controllers/collapsible_controller.test.js +0 -407
- data/__tests__/controllers/combobox_controller.test.js +0 -971
- data/__tests__/controllers/context_menu_controller.test.js +0 -905
- data/__tests__/controllers/date_picker_controller.test.js +0 -636
- data/__tests__/controllers/dialog_controller.test.js +0 -878
- data/__tests__/controllers/drawer_controller.test.js +0 -995
- data/__tests__/controllers/menubar_controller.test.js +0 -737
- data/__tests__/controllers/navigation_menu_controller.test.js +0 -599
- data/__tests__/controllers/popover_controller.test.js +0 -982
- data/__tests__/controllers/radio_group_controller.test.js +0 -640
- data/__tests__/controllers/resizable_controller.test.js +0 -680
- data/__tests__/controllers/select_controller.test.js +0 -678
- data/__tests__/controllers/sheet_controller.test.js +0 -986
- data/__tests__/controllers/slider_controller.test.js +0 -1036
- data/__tests__/controllers/switch_controller.test.js +0 -424
- data/__tests__/controllers/tabs_controller.test.js +0 -907
- data/__tests__/controllers/toggle_group_controller.test.js +0 -839
- data/__tests__/controllers/tooltip_controller.test.js +0 -808
- data/__tests__/helpers/stimulus-test-helper.js +0 -203
- data/babel.config.cjs +0 -5
- data/bin/bump +0 -321
- data/bin/console +0 -11
- data/bin/release +0 -205
- data/bin/setup +0 -8
- data/bin/test +0 -75
- data/jest.config.js +0 -19
- data/jest.setup.js +0 -8
- data/lib/generators/shadcn/component/component_generator.rb +0 -188
- data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
- data/package-lock.json +0 -7438
- data/package.json +0 -71
- 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
|
-
})
|