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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -2
- data/README.md +102 -1398
- data/__mocks__/@floating-ui/dom.js +67 -0
- data/app/assets/javascripts/shadcn/controllers/base_menu_controller.js +266 -0
- data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +34 -8
- data/app/assets/javascripts/shadcn/controllers/command_controller.js +5 -1
- data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +64 -135
- data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +56 -186
- data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
- data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +10 -7
- data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +10 -6
- data/app/assets/javascripts/shadcn/controllers/popover_controller.js +35 -60
- data/app/assets/javascripts/shadcn/controllers/select_controller.js +37 -17
- data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +24 -14
- data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
- data/app/assets/javascripts/shadcn/index.js +9 -1
- data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
- data/app/assets/stylesheets/shadcn/base.css +32 -0
- data/app/assets/stylesheets/shadcn/components.css +12 -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/command_list_component.rb +29 -14
- data/app/components/shadcn/context_menu_checkbox_item_component.rb +76 -0
- 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/context_menu_content_component.rb +37 -14
- data/app/components/shadcn/context_menu_item_component.rb +3 -2
- data/app/components/shadcn/context_menu_radio_group_component.rb +42 -0
- data/app/components/shadcn/context_menu_radio_item_component.rb +76 -0
- 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_checkbox_item_component.rb +76 -0
- 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/dropdown_menu_content_component.rb +45 -16
- data/app/components/shadcn/dropdown_menu_radio_group_component.rb +42 -0
- data/app/components/shadcn/dropdown_menu_radio_item_component.rb +76 -0
- 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/menubar_content_component.rb +45 -20
- data/app/components/shadcn/menubar_sub_content_component.rb +21 -8
- 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/radio_group_item_component.rb +32 -6
- data/app/components/shadcn/resizable_panel_group_component.rb +27 -16
- 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 +29 -86
- 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 +54 -42
- data/.dockerignore +0 -40
- data/CLAUDE.md +0 -463
- data/PROGRESS.md +0 -485
- data/Rakefile +0 -29
- 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 -966
- data/__tests__/controllers/context_menu_controller.test.js +0 -627
- 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 -736
- data/__tests__/controllers/navigation_menu_controller.test.js +0 -598
- data/__tests__/controllers/popover_controller.test.js +0 -1007
- 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 -674
- 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/console +0 -11
- data/bin/setup +0 -8
- 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 -7415
- data/package.json +0 -68
- data/rollup.config.js +0 -29
|
@@ -1,680 +0,0 @@
|
|
|
1
|
-
import { Application } from "@hotwired/stimulus"
|
|
2
|
-
import ResizableController from "../../app/assets/javascripts/shadcn/controllers/resizable_controller.js"
|
|
3
|
-
import { setupController, cleanupController, click, nextFrame, wait } from '../helpers/stimulus-test-helper.js'
|
|
4
|
-
|
|
5
|
-
describe("ResizableController", () => {
|
|
6
|
-
let application
|
|
7
|
-
let element
|
|
8
|
-
let controller
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
cleanupController(application)
|
|
12
|
-
// Clean up localStorage
|
|
13
|
-
localStorage.clear()
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
describe("basic rendering and initialization", () => {
|
|
17
|
-
const basicHTML = `
|
|
18
|
-
<div data-controller="shadcn--resizable"
|
|
19
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
20
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
21
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
22
|
-
<div data-shadcn--resizable-target="handle"
|
|
23
|
-
role="separator"
|
|
24
|
-
tabindex="0"
|
|
25
|
-
data-action="mousedown->shadcn--resizable#startResize touchstart->shadcn--resizable#startResize"
|
|
26
|
-
style="width: 4px; cursor: col-resize;"></div>
|
|
27
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
28
|
-
</div>
|
|
29
|
-
`
|
|
30
|
-
|
|
31
|
-
beforeEach(async () => {
|
|
32
|
-
const setup = await setupController(ResizableController, basicHTML, 'shadcn--resizable')
|
|
33
|
-
application = setup.application
|
|
34
|
-
element = setup.element
|
|
35
|
-
controller = setup.controller
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
test("initializes with horizontal direction", () => {
|
|
39
|
-
expect(controller.directionValue).toBe("horizontal")
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test("initializes isDragging to false", () => {
|
|
43
|
-
expect(controller.isDragging).toBe(false)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test("isHorizontal returns true for horizontal direction", () => {
|
|
47
|
-
expect(controller.isHorizontal).toBe(true)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test("has panel targets", () => {
|
|
51
|
-
expect(controller.panelTargets.length).toBe(2)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test("has handle target", () => {
|
|
55
|
-
expect(controller.handleTargets.length).toBe(1)
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
describe("vertical direction", () => {
|
|
60
|
-
const verticalHTML = `
|
|
61
|
-
<div data-controller="shadcn--resizable"
|
|
62
|
-
data-shadcn--resizable-direction-value="vertical"
|
|
63
|
-
style="display: flex; flex-direction: column; width: 500px; height: 300px;">
|
|
64
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
65
|
-
<div data-shadcn--resizable-target="handle"
|
|
66
|
-
role="separator"
|
|
67
|
-
tabindex="0"
|
|
68
|
-
style="height: 4px; cursor: row-resize;"></div>
|
|
69
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
70
|
-
</div>
|
|
71
|
-
`
|
|
72
|
-
|
|
73
|
-
beforeEach(async () => {
|
|
74
|
-
const setup = await setupController(ResizableController, verticalHTML, 'shadcn--resizable')
|
|
75
|
-
application = setup.application
|
|
76
|
-
element = setup.element
|
|
77
|
-
controller = setup.controller
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
test("initializes with vertical direction", () => {
|
|
81
|
-
expect(controller.directionValue).toBe("vertical")
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test("isHorizontal returns false for vertical direction", () => {
|
|
85
|
-
expect(controller.isHorizontal).toBe(false)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
describe("startResize", () => {
|
|
90
|
-
const startResizeHTML = `
|
|
91
|
-
<div data-controller="shadcn--resizable"
|
|
92
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
93
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
94
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
95
|
-
<div data-shadcn--resizable-target="handle"
|
|
96
|
-
role="separator"
|
|
97
|
-
tabindex="0"
|
|
98
|
-
data-action="mousedown->shadcn--resizable#startResize"
|
|
99
|
-
style="width: 4px;"></div>
|
|
100
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
101
|
-
</div>
|
|
102
|
-
`
|
|
103
|
-
|
|
104
|
-
beforeEach(async () => {
|
|
105
|
-
const setup = await setupController(ResizableController, startResizeHTML, 'shadcn--resizable')
|
|
106
|
-
application = setup.application
|
|
107
|
-
element = setup.element
|
|
108
|
-
controller = setup.controller
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test("sets isDragging to true", async () => {
|
|
112
|
-
const handle = controller.handleTargets[0]
|
|
113
|
-
controller.startResize({
|
|
114
|
-
currentTarget: handle,
|
|
115
|
-
type: 'mousedown',
|
|
116
|
-
clientX: 250,
|
|
117
|
-
clientY: 150,
|
|
118
|
-
preventDefault: jest.fn()
|
|
119
|
-
})
|
|
120
|
-
await nextFrame()
|
|
121
|
-
|
|
122
|
-
expect(controller.isDragging).toBe(true)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
test("sets currentHandle", async () => {
|
|
126
|
-
const handle = controller.handleTargets[0]
|
|
127
|
-
controller.startResize({
|
|
128
|
-
currentTarget: handle,
|
|
129
|
-
type: 'mousedown',
|
|
130
|
-
clientX: 250,
|
|
131
|
-
clientY: 150,
|
|
132
|
-
preventDefault: jest.fn()
|
|
133
|
-
})
|
|
134
|
-
await nextFrame()
|
|
135
|
-
|
|
136
|
-
expect(controller.currentHandle).toBe(handle)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
test("sets handle data-state to dragging", async () => {
|
|
140
|
-
const handle = controller.handleTargets[0]
|
|
141
|
-
controller.startResize({
|
|
142
|
-
currentTarget: handle,
|
|
143
|
-
type: 'mousedown',
|
|
144
|
-
clientX: 250,
|
|
145
|
-
clientY: 150,
|
|
146
|
-
preventDefault: jest.fn()
|
|
147
|
-
})
|
|
148
|
-
await nextFrame()
|
|
149
|
-
|
|
150
|
-
expect(handle.dataset.state).toBe("dragging")
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
test("stores start position for horizontal", async () => {
|
|
154
|
-
const handle = controller.handleTargets[0]
|
|
155
|
-
controller.startResize({
|
|
156
|
-
currentTarget: handle,
|
|
157
|
-
type: 'mousedown',
|
|
158
|
-
clientX: 250,
|
|
159
|
-
clientY: 150,
|
|
160
|
-
preventDefault: jest.fn()
|
|
161
|
-
})
|
|
162
|
-
await nextFrame()
|
|
163
|
-
|
|
164
|
-
expect(controller.startPosition).toBe(250)
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
test("prevents default", async () => {
|
|
168
|
-
const handle = controller.handleTargets[0]
|
|
169
|
-
const preventDefault = jest.fn()
|
|
170
|
-
controller.startResize({
|
|
171
|
-
currentTarget: handle,
|
|
172
|
-
type: 'mousedown',
|
|
173
|
-
clientX: 250,
|
|
174
|
-
clientY: 150,
|
|
175
|
-
preventDefault
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
expect(preventDefault).toHaveBeenCalled()
|
|
179
|
-
})
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
describe("stopResize", () => {
|
|
183
|
-
const stopResizeHTML = `
|
|
184
|
-
<div data-controller="shadcn--resizable"
|
|
185
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
186
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
187
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
188
|
-
<div data-shadcn--resizable-target="handle"
|
|
189
|
-
role="separator"
|
|
190
|
-
tabindex="0"
|
|
191
|
-
style="width: 4px;"></div>
|
|
192
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
193
|
-
</div>
|
|
194
|
-
`
|
|
195
|
-
|
|
196
|
-
beforeEach(async () => {
|
|
197
|
-
const setup = await setupController(ResizableController, stopResizeHTML, 'shadcn--resizable')
|
|
198
|
-
application = setup.application
|
|
199
|
-
element = setup.element
|
|
200
|
-
controller = setup.controller
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
test("sets isDragging to false", async () => {
|
|
204
|
-
const handle = controller.handleTargets[0]
|
|
205
|
-
controller.startResize({
|
|
206
|
-
currentTarget: handle,
|
|
207
|
-
type: 'mousedown',
|
|
208
|
-
clientX: 250,
|
|
209
|
-
clientY: 150,
|
|
210
|
-
preventDefault: jest.fn()
|
|
211
|
-
})
|
|
212
|
-
await nextFrame()
|
|
213
|
-
|
|
214
|
-
controller.stopResize()
|
|
215
|
-
await nextFrame()
|
|
216
|
-
|
|
217
|
-
expect(controller.isDragging).toBe(false)
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
test("clears handle data-state", async () => {
|
|
221
|
-
const handle = controller.handleTargets[0]
|
|
222
|
-
controller.startResize({
|
|
223
|
-
currentTarget: handle,
|
|
224
|
-
type: 'mousedown',
|
|
225
|
-
clientX: 250,
|
|
226
|
-
clientY: 150,
|
|
227
|
-
preventDefault: jest.fn()
|
|
228
|
-
})
|
|
229
|
-
await nextFrame()
|
|
230
|
-
|
|
231
|
-
controller.stopResize()
|
|
232
|
-
await nextFrame()
|
|
233
|
-
|
|
234
|
-
expect(handle.dataset.state).toBe("")
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
test("clears currentHandle", async () => {
|
|
238
|
-
const handle = controller.handleTargets[0]
|
|
239
|
-
controller.startResize({
|
|
240
|
-
currentTarget: handle,
|
|
241
|
-
type: 'mousedown',
|
|
242
|
-
clientX: 250,
|
|
243
|
-
clientY: 150,
|
|
244
|
-
preventDefault: jest.fn()
|
|
245
|
-
})
|
|
246
|
-
await nextFrame()
|
|
247
|
-
|
|
248
|
-
controller.stopResize()
|
|
249
|
-
await nextFrame()
|
|
250
|
-
|
|
251
|
-
expect(controller.currentHandle).toBeNull()
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
test("does nothing if not dragging", async () => {
|
|
255
|
-
// Should not throw
|
|
256
|
-
expect(() => {
|
|
257
|
-
controller.stopResize()
|
|
258
|
-
}).not.toThrow()
|
|
259
|
-
})
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
describe("keyboard navigation", () => {
|
|
263
|
-
const keyboardHTML = `
|
|
264
|
-
<div data-controller="shadcn--resizable"
|
|
265
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
266
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
267
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
268
|
-
data-min-size="10" data-max-size="90"
|
|
269
|
-
style="flex-basis: 50%;">Panel 1</div>
|
|
270
|
-
<div data-shadcn--resizable-target="handle"
|
|
271
|
-
role="separator"
|
|
272
|
-
tabindex="0"
|
|
273
|
-
style="width: 4px;"></div>
|
|
274
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
275
|
-
data-min-size="10" data-max-size="90"
|
|
276
|
-
style="flex-basis: 50%;">Panel 2</div>
|
|
277
|
-
</div>
|
|
278
|
-
`
|
|
279
|
-
|
|
280
|
-
beforeEach(async () => {
|
|
281
|
-
const setup = await setupController(ResizableController, keyboardHTML, 'shadcn--resizable')
|
|
282
|
-
application = setup.application
|
|
283
|
-
element = setup.element
|
|
284
|
-
controller = setup.controller
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
test("ArrowRight calls findAdjacentPanels and storePanelSizes", async () => {
|
|
288
|
-
const handle = controller.handleTargets[0]
|
|
289
|
-
const findAdjacentSpy = jest.spyOn(controller, 'findAdjacentPanels')
|
|
290
|
-
const storeSizesSpy = jest.spyOn(controller, 'storePanelSizes')
|
|
291
|
-
|
|
292
|
-
controller.handleKeydown.call(controller, {
|
|
293
|
-
currentTarget: handle,
|
|
294
|
-
key: "ArrowRight",
|
|
295
|
-
shiftKey: false,
|
|
296
|
-
preventDefault: jest.fn()
|
|
297
|
-
})
|
|
298
|
-
await nextFrame()
|
|
299
|
-
|
|
300
|
-
expect(findAdjacentSpy).toHaveBeenCalled()
|
|
301
|
-
expect(storeSizesSpy).toHaveBeenCalled()
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
test("ArrowLeft calls findAdjacentPanels and storePanelSizes", async () => {
|
|
305
|
-
const handle = controller.handleTargets[0]
|
|
306
|
-
const findAdjacentSpy = jest.spyOn(controller, 'findAdjacentPanels')
|
|
307
|
-
const storeSizesSpy = jest.spyOn(controller, 'storePanelSizes')
|
|
308
|
-
|
|
309
|
-
controller.handleKeydown.call(controller, {
|
|
310
|
-
currentTarget: handle,
|
|
311
|
-
key: "ArrowLeft",
|
|
312
|
-
shiftKey: false,
|
|
313
|
-
preventDefault: jest.fn()
|
|
314
|
-
})
|
|
315
|
-
await nextFrame()
|
|
316
|
-
|
|
317
|
-
expect(findAdjacentSpy).toHaveBeenCalled()
|
|
318
|
-
expect(storeSizesSpy).toHaveBeenCalled()
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
test("Shift key modifies step size calculation", async () => {
|
|
322
|
-
const handle = controller.handleTargets[0]
|
|
323
|
-
|
|
324
|
-
// Without shift
|
|
325
|
-
controller.handleKeydown.call(controller, {
|
|
326
|
-
currentTarget: handle,
|
|
327
|
-
key: "ArrowRight",
|
|
328
|
-
shiftKey: false,
|
|
329
|
-
preventDefault: jest.fn()
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
// With shift - step is 10 instead of 1
|
|
333
|
-
controller.handleKeydown.call(controller, {
|
|
334
|
-
currentTarget: handle,
|
|
335
|
-
key: "ArrowRight",
|
|
336
|
-
shiftKey: true,
|
|
337
|
-
preventDefault: jest.fn()
|
|
338
|
-
})
|
|
339
|
-
await nextFrame()
|
|
340
|
-
|
|
341
|
-
// Just verify it doesn't throw
|
|
342
|
-
expect(true).toBe(true)
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
test("prevents default on arrow keys", async () => {
|
|
346
|
-
const handle = controller.handleTargets[0]
|
|
347
|
-
const preventDefault = jest.fn()
|
|
348
|
-
|
|
349
|
-
controller.handleKeydown.call(controller, {
|
|
350
|
-
currentTarget: handle,
|
|
351
|
-
key: "ArrowRight",
|
|
352
|
-
shiftKey: false,
|
|
353
|
-
preventDefault
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
expect(preventDefault).toHaveBeenCalled()
|
|
357
|
-
})
|
|
358
|
-
})
|
|
359
|
-
|
|
360
|
-
describe("panel size constraints", () => {
|
|
361
|
-
const constraintsHTML = `
|
|
362
|
-
<div data-controller="shadcn--resizable"
|
|
363
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
364
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
365
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
366
|
-
data-min-size="20" data-max-size="80"
|
|
367
|
-
style="flex-basis: 50%;">Panel 1</div>
|
|
368
|
-
<div data-shadcn--resizable-target="handle"
|
|
369
|
-
role="separator"
|
|
370
|
-
tabindex="0"
|
|
371
|
-
style="width: 4px;"></div>
|
|
372
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
373
|
-
data-min-size="20" data-max-size="80"
|
|
374
|
-
style="flex-basis: 50%;">Panel 2</div>
|
|
375
|
-
</div>
|
|
376
|
-
`
|
|
377
|
-
|
|
378
|
-
beforeEach(async () => {
|
|
379
|
-
const setup = await setupController(ResizableController, constraintsHTML, 'shadcn--resizable')
|
|
380
|
-
application = setup.application
|
|
381
|
-
element = setup.element
|
|
382
|
-
controller = setup.controller
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
test("respects min-size constraint", async () => {
|
|
386
|
-
const handle = controller.handleTargets[0]
|
|
387
|
-
const prevPanel = controller.panelTargets[0]
|
|
388
|
-
|
|
389
|
-
controller.setPanelSize(prevPanel, 50)
|
|
390
|
-
controller.setPanelSize(controller.panelTargets[1], 50)
|
|
391
|
-
|
|
392
|
-
// Try to resize below min
|
|
393
|
-
for (let i = 0; i < 50; i++) {
|
|
394
|
-
controller.handleKeydown.call(controller, {
|
|
395
|
-
currentTarget: handle,
|
|
396
|
-
key: "ArrowLeft",
|
|
397
|
-
shiftKey: false,
|
|
398
|
-
preventDefault: jest.fn()
|
|
399
|
-
})
|
|
400
|
-
}
|
|
401
|
-
await nextFrame()
|
|
402
|
-
|
|
403
|
-
expect(parseFloat(prevPanel.dataset.panelSize)).toBeGreaterThanOrEqual(20)
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
test("respects max-size constraint", async () => {
|
|
407
|
-
const handle = controller.handleTargets[0]
|
|
408
|
-
const prevPanel = controller.panelTargets[0]
|
|
409
|
-
|
|
410
|
-
controller.setPanelSize(prevPanel, 50)
|
|
411
|
-
controller.setPanelSize(controller.panelTargets[1], 50)
|
|
412
|
-
|
|
413
|
-
// Try to resize above max
|
|
414
|
-
for (let i = 0; i < 50; i++) {
|
|
415
|
-
controller.handleKeydown.call(controller, {
|
|
416
|
-
currentTarget: handle,
|
|
417
|
-
key: "ArrowRight",
|
|
418
|
-
shiftKey: false,
|
|
419
|
-
preventDefault: jest.fn()
|
|
420
|
-
})
|
|
421
|
-
}
|
|
422
|
-
await nextFrame()
|
|
423
|
-
|
|
424
|
-
expect(parseFloat(prevPanel.dataset.panelSize)).toBeLessThanOrEqual(80)
|
|
425
|
-
})
|
|
426
|
-
})
|
|
427
|
-
|
|
428
|
-
describe("collapse functionality", () => {
|
|
429
|
-
const collapseHTML = `
|
|
430
|
-
<div data-controller="shadcn--resizable"
|
|
431
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
432
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
433
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
434
|
-
data-min-size="0" data-max-size="100"
|
|
435
|
-
style="flex-basis: 50%;">Panel 1</div>
|
|
436
|
-
<div data-shadcn--resizable-target="handle"
|
|
437
|
-
role="separator"
|
|
438
|
-
tabindex="0"
|
|
439
|
-
style="width: 4px;"></div>
|
|
440
|
-
<div data-shadcn--resizable-target="panel" data-panel
|
|
441
|
-
data-min-size="0" data-max-size="100"
|
|
442
|
-
style="flex-basis: 50%;">Panel 2</div>
|
|
443
|
-
</div>
|
|
444
|
-
`
|
|
445
|
-
|
|
446
|
-
beforeEach(async () => {
|
|
447
|
-
const setup = await setupController(ResizableController, collapseHTML, 'shadcn--resizable')
|
|
448
|
-
application = setup.application
|
|
449
|
-
element = setup.element
|
|
450
|
-
controller = setup.controller
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
test("Home calls collapsePanel with prev", async () => {
|
|
454
|
-
const handle = controller.handleTargets[0]
|
|
455
|
-
const collapseSpy = jest.spyOn(controller, 'collapsePanel')
|
|
456
|
-
|
|
457
|
-
controller.handleKeydown.call(controller, {
|
|
458
|
-
currentTarget: handle,
|
|
459
|
-
key: "Home",
|
|
460
|
-
shiftKey: false,
|
|
461
|
-
preventDefault: jest.fn()
|
|
462
|
-
})
|
|
463
|
-
await nextFrame()
|
|
464
|
-
|
|
465
|
-
expect(collapseSpy).toHaveBeenCalledWith('prev')
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
test("End calls collapsePanel with next", async () => {
|
|
469
|
-
const handle = controller.handleTargets[0]
|
|
470
|
-
const collapseSpy = jest.spyOn(controller, 'collapsePanel')
|
|
471
|
-
|
|
472
|
-
controller.handleKeydown.call(controller, {
|
|
473
|
-
currentTarget: handle,
|
|
474
|
-
key: "End",
|
|
475
|
-
shiftKey: false,
|
|
476
|
-
preventDefault: jest.fn()
|
|
477
|
-
})
|
|
478
|
-
await nextFrame()
|
|
479
|
-
|
|
480
|
-
expect(collapseSpy).toHaveBeenCalledWith('next')
|
|
481
|
-
})
|
|
482
|
-
|
|
483
|
-
test("Home prevents default", async () => {
|
|
484
|
-
const handle = controller.handleTargets[0]
|
|
485
|
-
const preventDefault = jest.fn()
|
|
486
|
-
|
|
487
|
-
controller.handleKeydown.call(controller, {
|
|
488
|
-
currentTarget: handle,
|
|
489
|
-
key: "Home",
|
|
490
|
-
shiftKey: false,
|
|
491
|
-
preventDefault
|
|
492
|
-
})
|
|
493
|
-
|
|
494
|
-
expect(preventDefault).toHaveBeenCalled()
|
|
495
|
-
})
|
|
496
|
-
|
|
497
|
-
test("End prevents default", async () => {
|
|
498
|
-
const handle = controller.handleTargets[0]
|
|
499
|
-
const preventDefault = jest.fn()
|
|
500
|
-
|
|
501
|
-
controller.handleKeydown.call(controller, {
|
|
502
|
-
currentTarget: handle,
|
|
503
|
-
key: "End",
|
|
504
|
-
shiftKey: false,
|
|
505
|
-
preventDefault
|
|
506
|
-
})
|
|
507
|
-
|
|
508
|
-
expect(preventDefault).toHaveBeenCalled()
|
|
509
|
-
})
|
|
510
|
-
})
|
|
511
|
-
|
|
512
|
-
describe("auto-save functionality", () => {
|
|
513
|
-
const autoSaveHTML = `
|
|
514
|
-
<div data-controller="shadcn--resizable"
|
|
515
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
516
|
-
data-shadcn--resizable-auto-save-id-value="test-layout"
|
|
517
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
518
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
519
|
-
<div data-shadcn--resizable-target="handle"
|
|
520
|
-
role="separator"
|
|
521
|
-
tabindex="0"
|
|
522
|
-
style="width: 4px;"></div>
|
|
523
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
524
|
-
</div>
|
|
525
|
-
`
|
|
526
|
-
|
|
527
|
-
beforeEach(async () => {
|
|
528
|
-
const setup = await setupController(ResizableController, autoSaveHTML, 'shadcn--resizable')
|
|
529
|
-
application = setup.application
|
|
530
|
-
element = setup.element
|
|
531
|
-
controller = setup.controller
|
|
532
|
-
})
|
|
533
|
-
|
|
534
|
-
test("has autoSaveId value", () => {
|
|
535
|
-
expect(controller.autoSaveIdValue).toBe("test-layout")
|
|
536
|
-
})
|
|
537
|
-
|
|
538
|
-
test("saves sizes to localStorage", async () => {
|
|
539
|
-
controller.setPanelSize(controller.panelTargets[0], 60)
|
|
540
|
-
controller.setPanelSize(controller.panelTargets[1], 40)
|
|
541
|
-
controller.saveSizes()
|
|
542
|
-
|
|
543
|
-
const saved = localStorage.getItem("resizable-test-layout")
|
|
544
|
-
expect(saved).not.toBeNull()
|
|
545
|
-
|
|
546
|
-
const sizes = JSON.parse(saved)
|
|
547
|
-
expect(sizes).toHaveLength(2)
|
|
548
|
-
})
|
|
549
|
-
|
|
550
|
-
test("loads sizes from localStorage", async () => {
|
|
551
|
-
localStorage.setItem("resizable-test-layout", JSON.stringify([70, 30]))
|
|
552
|
-
|
|
553
|
-
controller.loadSavedSizes()
|
|
554
|
-
await nextFrame()
|
|
555
|
-
|
|
556
|
-
expect(parseFloat(controller.panelTargets[0].dataset.panelSize)).toBe(70)
|
|
557
|
-
expect(parseFloat(controller.panelTargets[1].dataset.panelSize)).toBe(30)
|
|
558
|
-
})
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
describe("setPanelSize and getPanelSize", () => {
|
|
562
|
-
const sizeHTML = `
|
|
563
|
-
<div data-controller="shadcn--resizable"
|
|
564
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
565
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
566
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
567
|
-
<div data-shadcn--resizable-target="handle"
|
|
568
|
-
role="separator"
|
|
569
|
-
tabindex="0"
|
|
570
|
-
style="width: 4px;"></div>
|
|
571
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
572
|
-
</div>
|
|
573
|
-
`
|
|
574
|
-
|
|
575
|
-
beforeEach(async () => {
|
|
576
|
-
const setup = await setupController(ResizableController, sizeHTML, 'shadcn--resizable')
|
|
577
|
-
application = setup.application
|
|
578
|
-
element = setup.element
|
|
579
|
-
controller = setup.controller
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
test("setPanelSize sets flex-basis", async () => {
|
|
583
|
-
const panel = controller.panelTargets[0]
|
|
584
|
-
controller.setPanelSize(panel, 60)
|
|
585
|
-
|
|
586
|
-
expect(panel.style.flexBasis).toBe("60%")
|
|
587
|
-
})
|
|
588
|
-
|
|
589
|
-
test("setPanelSize sets data-panel-size", async () => {
|
|
590
|
-
const panel = controller.panelTargets[0]
|
|
591
|
-
controller.setPanelSize(panel, 60)
|
|
592
|
-
|
|
593
|
-
expect(panel.dataset.panelSize).toBe("60")
|
|
594
|
-
})
|
|
595
|
-
})
|
|
596
|
-
|
|
597
|
-
describe("findAdjacentPanels", () => {
|
|
598
|
-
const adjacentHTML = `
|
|
599
|
-
<div data-controller="shadcn--resizable"
|
|
600
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
601
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
602
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 33%;">Panel 1</div>
|
|
603
|
-
<div data-shadcn--resizable-target="handle"
|
|
604
|
-
role="separator"
|
|
605
|
-
tabindex="0"
|
|
606
|
-
style="width: 4px;"></div>
|
|
607
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 33%;">Panel 2</div>
|
|
608
|
-
<div data-shadcn--resizable-target="handle"
|
|
609
|
-
role="separator"
|
|
610
|
-
tabindex="0"
|
|
611
|
-
style="width: 4px;"></div>
|
|
612
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 33%;">Panel 3</div>
|
|
613
|
-
</div>
|
|
614
|
-
`
|
|
615
|
-
|
|
616
|
-
beforeEach(async () => {
|
|
617
|
-
const setup = await setupController(ResizableController, adjacentHTML, 'shadcn--resizable')
|
|
618
|
-
application = setup.application
|
|
619
|
-
element = setup.element
|
|
620
|
-
controller = setup.controller
|
|
621
|
-
})
|
|
622
|
-
|
|
623
|
-
test("finds correct adjacent panels for first handle", async () => {
|
|
624
|
-
controller.currentHandle = controller.handleTargets[0]
|
|
625
|
-
controller.findAdjacentPanels()
|
|
626
|
-
|
|
627
|
-
expect(controller.prevPanel).toBe(controller.panelTargets[0])
|
|
628
|
-
expect(controller.nextPanel).toBe(controller.panelTargets[1])
|
|
629
|
-
})
|
|
630
|
-
|
|
631
|
-
test("finds correct adjacent panels for second handle", async () => {
|
|
632
|
-
controller.currentHandle = controller.handleTargets[1]
|
|
633
|
-
controller.findAdjacentPanels()
|
|
634
|
-
|
|
635
|
-
expect(controller.prevPanel).toBe(controller.panelTargets[1])
|
|
636
|
-
expect(controller.nextPanel).toBe(controller.panelTargets[2])
|
|
637
|
-
})
|
|
638
|
-
})
|
|
639
|
-
|
|
640
|
-
describe("disconnect cleanup", () => {
|
|
641
|
-
const disconnectHTML = `
|
|
642
|
-
<div data-controller="shadcn--resizable"
|
|
643
|
-
data-shadcn--resizable-direction-value="horizontal"
|
|
644
|
-
style="display: flex; width: 500px; height: 300px;">
|
|
645
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 1</div>
|
|
646
|
-
<div data-shadcn--resizable-target="handle"
|
|
647
|
-
role="separator"
|
|
648
|
-
tabindex="0"
|
|
649
|
-
style="width: 4px;"></div>
|
|
650
|
-
<div data-shadcn--resizable-target="panel" data-panel style="flex-basis: 50%;">Panel 2</div>
|
|
651
|
-
</div>
|
|
652
|
-
`
|
|
653
|
-
|
|
654
|
-
beforeEach(async () => {
|
|
655
|
-
const setup = await setupController(ResizableController, disconnectHTML, 'shadcn--resizable')
|
|
656
|
-
application = setup.application
|
|
657
|
-
element = setup.element
|
|
658
|
-
controller = setup.controller
|
|
659
|
-
})
|
|
660
|
-
|
|
661
|
-
test("cleans up event listeners on disconnect", async () => {
|
|
662
|
-
const handle = controller.handleTargets[0]
|
|
663
|
-
|
|
664
|
-
// Start resize
|
|
665
|
-
controller.startResize({
|
|
666
|
-
currentTarget: handle,
|
|
667
|
-
type: 'mousedown',
|
|
668
|
-
clientX: 250,
|
|
669
|
-
clientY: 150,
|
|
670
|
-
preventDefault: jest.fn()
|
|
671
|
-
})
|
|
672
|
-
await nextFrame()
|
|
673
|
-
|
|
674
|
-
// Disconnect
|
|
675
|
-
expect(() => {
|
|
676
|
-
controller.disconnect()
|
|
677
|
-
}).not.toThrow()
|
|
678
|
-
})
|
|
679
|
-
})
|
|
680
|
-
})
|