shadcn_phlexcomponents 0.1.5 → 0.1.11
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/README.md +14 -0
- data/app/javascript/controllers/accordion_controller.ts +133 -0
- data/app/javascript/controllers/{avatar_controller.js → avatar_controller.ts} +4 -0
- data/app/javascript/controllers/checkbox_controller.ts +34 -0
- data/app/javascript/controllers/collapsible_controller.ts +45 -0
- data/app/javascript/controllers/combobox_controller.ts +145 -0
- data/app/javascript/controllers/command_controller.ts +129 -0
- data/app/javascript/controllers/command_root_controller.ts +355 -0
- data/app/javascript/controllers/date_picker_controller.ts +274 -0
- data/app/javascript/controllers/date_range_picker_controller.ts +243 -0
- data/app/javascript/controllers/dialog_controller.ts +113 -0
- data/app/javascript/controllers/dropdown_menu_controller.ts +133 -0
- data/app/javascript/controllers/dropdown_menu_root_controller.ts +234 -0
- data/app/javascript/controllers/dropdown_menu_sub_controller.ts +150 -0
- data/app/javascript/controllers/form_field_controller.ts +22 -0
- data/app/javascript/controllers/hover_card_controller.ts +93 -0
- data/app/javascript/controllers/{loading_button_controller.js → loading_button_controller.ts} +2 -2
- data/app/javascript/controllers/popover_controller.ts +141 -0
- data/app/javascript/controllers/progress_controller.ts +17 -0
- data/app/javascript/controllers/radio_group_controller.ts +106 -0
- data/app/javascript/controllers/select_controller.ts +200 -0
- data/app/javascript/controllers/{sidebar_controller.js → sidebar_controller.ts} +6 -2
- data/app/javascript/controllers/sidebar_trigger_controller.ts +21 -0
- data/app/javascript/controllers/slider_controller.ts +107 -0
- data/app/javascript/controllers/switch_controller.ts +30 -0
- data/app/javascript/controllers/tabs_controller.ts +79 -0
- data/app/javascript/controllers/{theme_switcher_controller.js → theme_switcher_controller.ts} +12 -9
- data/app/javascript/controllers/toast_container_controller.ts +62 -0
- data/app/javascript/controllers/toast_controller.ts +28 -0
- data/app/javascript/controllers/tooltip_controller.ts +98 -0
- data/app/javascript/shadcn_phlexcomponents.ts +57 -0
- data/app/javascript/utils.ts +437 -0
- data/app/stylesheets/date_picker.css +74 -0
- data/app/stylesheets/nouislider.css +173 -0
- data/app/stylesheets/tw-animate.css +486 -0
- data/lib/install/install_shadcn_phlexcomponents.rb +22 -9
- data/lib/shadcn_phlexcomponents/alias.rb +3 -1
- data/lib/shadcn_phlexcomponents/components/accordion.rb +129 -0
- data/lib/shadcn_phlexcomponents/components/alert.rb +59 -0
- data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +276 -0
- data/lib/{components → shadcn_phlexcomponents/components}/aspect_ratio.rb +2 -2
- data/lib/shadcn_phlexcomponents/components/avatar.rb +63 -0
- data/lib/shadcn_phlexcomponents/components/badge.rb +35 -0
- data/lib/{components → shadcn_phlexcomponents/components}/base.rb +44 -7
- data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +150 -0
- data/lib/shadcn_phlexcomponents/components/button.rb +49 -0
- data/lib/shadcn_phlexcomponents/components/card.rb +88 -0
- data/lib/{components → shadcn_phlexcomponents/components}/checkbox.rb +21 -17
- data/lib/{components → shadcn_phlexcomponents/components}/checkbox_group.rb +27 -16
- data/lib/shadcn_phlexcomponents/components/collapsible.rb +91 -0
- data/lib/shadcn_phlexcomponents/components/combobox.rb +398 -0
- data/lib/shadcn_phlexcomponents/components/command.rb +351 -0
- data/lib/shadcn_phlexcomponents/components/date_picker.rb +264 -0
- data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +126 -0
- data/lib/shadcn_phlexcomponents/components/dialog.rb +234 -0
- data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +282 -0
- data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +135 -0
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +82 -0
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +116 -0
- data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +46 -0
- data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +82 -0
- data/lib/{components → shadcn_phlexcomponents/components/form}/form_error.rb +7 -3
- data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +143 -0
- data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +21 -0
- data/lib/{components → shadcn_phlexcomponents/components/form}/form_input.rb +3 -4
- data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +106 -0
- data/lib/shadcn_phlexcomponents/components/form/form_select.rb +64 -0
- data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +91 -0
- data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +67 -0
- data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +59 -0
- data/lib/shadcn_phlexcomponents/components/form.rb +157 -0
- data/lib/shadcn_phlexcomponents/components/hover_card.rb +110 -0
- data/lib/shadcn_phlexcomponents/components/input.rb +31 -0
- data/lib/shadcn_phlexcomponents/components/label.rb +16 -0
- data/lib/{components → shadcn_phlexcomponents/components}/link.rb +10 -3
- data/lib/shadcn_phlexcomponents/components/loading_button.rb +28 -0
- data/lib/shadcn_phlexcomponents/components/pagination.rb +166 -0
- data/lib/shadcn_phlexcomponents/components/popover.rb +116 -0
- data/lib/{components → shadcn_phlexcomponents/components}/progress.rb +5 -5
- data/lib/shadcn_phlexcomponents/components/radio_group.rb +155 -0
- data/lib/shadcn_phlexcomponents/components/select.rb +421 -0
- data/lib/{components → shadcn_phlexcomponents/components}/separator.rb +9 -8
- data/lib/shadcn_phlexcomponents/components/sheet.rb +239 -0
- data/lib/{components → shadcn_phlexcomponents/components}/skeleton.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/slider.rb +72 -0
- data/lib/shadcn_phlexcomponents/components/switch.rb +75 -0
- data/lib/shadcn_phlexcomponents/components/table.rb +140 -0
- data/lib/shadcn_phlexcomponents/components/tabs.rb +135 -0
- data/lib/shadcn_phlexcomponents/components/textarea.rb +24 -0
- data/lib/{components → shadcn_phlexcomponents/components}/theme_switcher.rb +2 -2
- data/lib/shadcn_phlexcomponents/components/toast.rb +153 -0
- data/lib/{components → shadcn_phlexcomponents/components}/toast_container.rb +24 -5
- data/lib/shadcn_phlexcomponents/components/tooltip.rb +131 -0
- data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +25 -0
- data/lib/shadcn_phlexcomponents/version.rb +1 -1
- data/lib/tasks/install.rake +1 -1
- metadata +92 -168
- data/app/assets/tailwind/choices.css +0 -324
- data/app/assets/tailwind/tailwindcss-animate.css +0 -318
- data/app/assets/tailwind/vanilla-calendar-pro.css +0 -466
- data/app/javascript/controllers/accordion_controller.js +0 -133
- data/app/javascript/controllers/alert_dialog_controller.js +0 -157
- data/app/javascript/controllers/checkbox_controller.js +0 -28
- data/app/javascript/controllers/collapsible_controller.js +0 -35
- data/app/javascript/controllers/combobox_controller.js +0 -34
- data/app/javascript/controllers/date_picker_controller.js +0 -118
- data/app/javascript/controllers/date_range_picker_controller.js +0 -231
- data/app/javascript/controllers/dialog_controller.js +0 -159
- data/app/javascript/controllers/dropdown_menu_controller.js +0 -193
- data/app/javascript/controllers/hover_card_controller.js +0 -42
- data/app/javascript/controllers/popover_controller.js +0 -124
- data/app/javascript/controllers/progress_controller.js +0 -14
- data/app/javascript/controllers/radio_group_controller.js +0 -90
- data/app/javascript/controllers/select_controller.js +0 -294
- data/app/javascript/controllers/sheet_controller.js +0 -159
- data/app/javascript/controllers/sidebar_trigger_controller.js +0 -15
- data/app/javascript/controllers/switch_controller.js +0 -24
- data/app/javascript/controllers/tabs_controller.js +0 -73
- data/app/javascript/controllers/toast_container_controller.js +0 -22
- data/app/javascript/controllers/toast_controller.js +0 -45
- data/app/javascript/controllers/tooltip_controller.js +0 -41
- data/lib/components/accordion.rb +0 -38
- data/lib/components/accordion_content.rb +0 -30
- data/lib/components/accordion_item.rb +0 -26
- data/lib/components/accordion_trigger.rb +0 -45
- data/lib/components/alert.rb +0 -40
- data/lib/components/alert_description.rb +0 -11
- data/lib/components/alert_dialog.rb +0 -60
- data/lib/components/alert_dialog_action.rb +0 -22
- data/lib/components/alert_dialog_action_to.rb +0 -40
- data/lib/components/alert_dialog_cancel.rb +0 -22
- data/lib/components/alert_dialog_content.rb +0 -40
- data/lib/components/alert_dialog_description.rb +0 -22
- data/lib/components/alert_dialog_footer.rb +0 -11
- data/lib/components/alert_dialog_header.rb +0 -11
- data/lib/components/alert_dialog_title.rb +0 -22
- data/lib/components/alert_dialog_trigger.rb +0 -50
- data/lib/components/alert_title.rb +0 -11
- data/lib/components/avatar.rb +0 -31
- data/lib/components/avatar_fallback.rb +0 -21
- data/lib/components/avatar_image.rb +0 -19
- data/lib/components/badge.rb +0 -30
- data/lib/components/breadcrumb.rb +0 -51
- data/lib/components/breadcrumb_ellipsis.rb +0 -23
- data/lib/components/breadcrumb_item.rb +0 -11
- data/lib/components/breadcrumb_link.rb +0 -7
- data/lib/components/breadcrumb_page.rb +0 -21
- data/lib/components/breadcrumb_separator.rb +0 -26
- data/lib/components/button.rb +0 -53
- data/lib/components/card.rb +0 -31
- data/lib/components/card_content.rb +0 -11
- data/lib/components/card_description.rb +0 -11
- data/lib/components/card_footer.rb +0 -11
- data/lib/components/card_header.rb +0 -11
- data/lib/components/card_title.rb +0 -11
- data/lib/components/collapsible.rb +0 -31
- data/lib/components/collapsible_content.rb +0 -24
- data/lib/components/collapsible_trigger.rb +0 -50
- data/lib/components/combobox.rb +0 -57
- data/lib/components/combobox_item.rb +0 -9
- data/lib/components/date_picker.rb +0 -94
- data/lib/components/date_range_picker.rb +0 -113
- data/lib/components/dialog.rb +0 -52
- data/lib/components/dialog_close.rb +0 -42
- data/lib/components/dialog_content.rb +0 -54
- data/lib/components/dialog_description.rb +0 -22
- data/lib/components/dialog_footer.rb +0 -11
- data/lib/components/dialog_header.rb +0 -11
- data/lib/components/dialog_title.rb +0 -22
- data/lib/components/dialog_trigger.rb +0 -50
- data/lib/components/dropdown_menu.rb +0 -50
- data/lib/components/dropdown_menu_content.rb +0 -52
- data/lib/components/dropdown_menu_item.rb +0 -56
- data/lib/components/dropdown_menu_item_to.rb +0 -28
- data/lib/components/dropdown_menu_label.rb +0 -11
- data/lib/components/dropdown_menu_separator.rb +0 -20
- data/lib/components/dropdown_menu_trigger.rb +0 -57
- data/lib/components/form.rb +0 -59
- data/lib/components/form_hint.rb +0 -17
- data/lib/components/hover_card.rb +0 -33
- data/lib/components/hover_card_content.rb +0 -32
- data/lib/components/hover_card_trigger.rb +0 -44
- data/lib/components/input.rb +0 -32
- data/lib/components/label.rb +0 -14
- data/lib/components/loading_button.rb +0 -21
- data/lib/components/pagination.rb +0 -38
- data/lib/components/pagination_ellipsis.rb +0 -24
- data/lib/components/pagination_link.rb +0 -34
- data/lib/components/pagination_next.rb +0 -32
- data/lib/components/pagination_previous.rb +0 -32
- data/lib/components/popover.rb +0 -34
- data/lib/components/popover_content.rb +0 -40
- data/lib/components/popover_trigger.rb +0 -51
- data/lib/components/radio_group.rb +0 -62
- data/lib/components/radio_group_item.rb +0 -66
- data/lib/components/select.rb +0 -184
- data/lib/components/select_content.rb +0 -64
- data/lib/components/select_group.rb +0 -23
- data/lib/components/select_item.rb +0 -59
- data/lib/components/select_label.rb +0 -24
- data/lib/components/select_trigger.rb +0 -56
- data/lib/components/sheet.rb +0 -53
- data/lib/components/sheet_close.rb +0 -42
- data/lib/components/sheet_content.rb +0 -65
- data/lib/components/sheet_description.rb +0 -22
- data/lib/components/sheet_footer.rb +0 -11
- data/lib/components/sheet_header.rb +0 -11
- data/lib/components/sheet_title.rb +0 -22
- data/lib/components/sheet_trigger.rb +0 -50
- data/lib/components/sidebar.rb +0 -108
- data/lib/components/sidebar_container.rb +0 -11
- data/lib/components/sidebar_content.rb +0 -11
- data/lib/components/sidebar_footer.rb +0 -11
- data/lib/components/sidebar_group.rb +0 -11
- data/lib/components/sidebar_group_content.rb +0 -11
- data/lib/components/sidebar_group_label.rb +0 -16
- data/lib/components/sidebar_header.rb +0 -11
- data/lib/components/sidebar_inset.rb +0 -15
- data/lib/components/sidebar_menu.rb +0 -11
- data/lib/components/sidebar_menu_button.rb +0 -61
- data/lib/components/sidebar_menu_item.rb +0 -9
- data/lib/components/sidebar_menu_sub.rb +0 -14
- data/lib/components/sidebar_menu_sub_button.rb +0 -48
- data/lib/components/sidebar_menu_sub_item.rb +0 -9
- data/lib/components/sidebar_trigger.rb +0 -40
- data/lib/components/switch.rb +0 -66
- data/lib/components/table.rb +0 -75
- data/lib/components/table_body.rb +0 -11
- data/lib/components/table_caption.rb +0 -11
- data/lib/components/table_cell.rb +0 -11
- data/lib/components/table_footer.rb +0 -11
- data/lib/components/table_head.rb +0 -14
- data/lib/components/table_header.rb +0 -11
- data/lib/components/table_row.rb +0 -11
- data/lib/components/tabs.rb +0 -38
- data/lib/components/tabs_content.rb +0 -35
- data/lib/components/tabs_list.rb +0 -23
- data/lib/components/tabs_trigger.rb +0 -45
- data/lib/components/textarea.rb +0 -28
- data/lib/components/toast.rb +0 -101
- data/lib/components/toast_action.rb +0 -39
- data/lib/components/toast_action_to.rb +0 -28
- data/lib/components/toast_content.rb +0 -11
- data/lib/components/toast_description.rb +0 -11
- data/lib/components/toast_title.rb +0 -11
- data/lib/components/tooltip.rb +0 -34
- data/lib/components/tooltip_content.rb +0 -39
- data/lib/components/tooltip_trigger.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e69ba212a41e6644e473fa1e443b1114b7095bec0b682399932d1d41451ba8fa
|
4
|
+
data.tar.gz: 686b0e0582a7c277eb1ddaa5476edf08d300e8aa6ce1d0e0c8ceca7ed2dc3cdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99248f0f5d9ec5d554d86aa24a4340f8fb9232b7a4618bfc689e2aa0fe6e2f355a426ac5b04549ac3548453c1be17623c3f8d0fab6158c18a80c9fadfbabaddc
|
7
|
+
data.tar.gz: e285a996a8aa294d3fda26d16b9e2cf3108fec5c256faa13a123e5bff949c9ff6837cc38752006acc4824df3a2c1492c653a7674f17f85935c8330f7fb4da761
|
data/README.md
CHANGED
@@ -37,3 +37,17 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERN
|
|
37
37
|
## Code of Conduct
|
38
38
|
|
39
39
|
Everyone interacting in the ShadcnPhlexcomponents project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/shadcn_phlexcomponents/blob/main/CODE_OF_CONDUCT.md).
|
40
|
+
|
41
|
+
## [Unreleased] - YYYY-MM-DD
|
42
|
+
|
43
|
+
### Added
|
44
|
+
|
45
|
+
### Changed
|
46
|
+
|
47
|
+
### Deprecated
|
48
|
+
|
49
|
+
### Removed
|
50
|
+
|
51
|
+
### Fixed
|
52
|
+
|
53
|
+
### Security
|
@@ -0,0 +1,133 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
import { showContent, hideContent } from '../utils'
|
3
|
+
|
4
|
+
export default class extends Controller<HTMLElement> {
|
5
|
+
static targets = ['item']
|
6
|
+
static values = { openItems: Array }
|
7
|
+
declare itemTargets: HTMLElement[]
|
8
|
+
declare multiple: boolean
|
9
|
+
declare openItemsValue: string[]
|
10
|
+
|
11
|
+
connect() {
|
12
|
+
this.multiple = this.element.dataset.multiple === 'true'
|
13
|
+
|
14
|
+
setTimeout(() => {
|
15
|
+
this.itemTargets.forEach((item) => {
|
16
|
+
const content = item.querySelector(
|
17
|
+
'[data-shadcn-phlexcomponents="accordion-content-container"]',
|
18
|
+
) as HTMLElement
|
19
|
+
this.setContentHeight(content)
|
20
|
+
})
|
21
|
+
}, 250)
|
22
|
+
}
|
23
|
+
|
24
|
+
setContentHeight(element: HTMLElement) {
|
25
|
+
const height = this.getContentHeight(element)
|
26
|
+
element.style.setProperty('--radix-accordion-content-height', `${height}px`)
|
27
|
+
}
|
28
|
+
|
29
|
+
getContentHeight(element: HTMLElement) {
|
30
|
+
// Store the original styles we need to modify
|
31
|
+
const originalStyles = {
|
32
|
+
display: element.style.display,
|
33
|
+
visibility: element.style.visibility,
|
34
|
+
position: element.style.position,
|
35
|
+
}
|
36
|
+
|
37
|
+
// Make the element visible but not displayed
|
38
|
+
element.style.display = 'block' // or whatever is appropriate (flex, inline, etc.)
|
39
|
+
element.style.visibility = 'hidden'
|
40
|
+
element.style.position = 'absolute'
|
41
|
+
|
42
|
+
// Get the height
|
43
|
+
const height = element.offsetHeight
|
44
|
+
|
45
|
+
// Restore the original styles
|
46
|
+
element.style.display = originalStyles.display
|
47
|
+
element.style.visibility = originalStyles.visibility
|
48
|
+
element.style.position = originalStyles.position
|
49
|
+
|
50
|
+
return height
|
51
|
+
}
|
52
|
+
|
53
|
+
toggle(event: MouseEvent) {
|
54
|
+
const trigger = event.currentTarget as HTMLElement
|
55
|
+
|
56
|
+
const item = this.itemTargets.find((item) => {
|
57
|
+
return item.contains(trigger)
|
58
|
+
})
|
59
|
+
|
60
|
+
if (!item) return
|
61
|
+
|
62
|
+
const value = item.dataset.value as string
|
63
|
+
const isOpen = this.openItemsValue.includes(value)
|
64
|
+
|
65
|
+
if (isOpen) {
|
66
|
+
this.openItemsValue = this.openItemsValue.filter((v) => v !== value)
|
67
|
+
} else {
|
68
|
+
if (this.multiple) {
|
69
|
+
this.openItemsValue = [...this.openItemsValue, value]
|
70
|
+
} else {
|
71
|
+
this.openItemsValue = [value]
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
focusTrigger(event: KeyboardEvent) {
|
77
|
+
const trigger = event.currentTarget as HTMLButtonElement
|
78
|
+
const key = event.key as 'ArrowUp' | 'ArrowDown'
|
79
|
+
|
80
|
+
let focusableTriggers = this.itemTargets.map((item) => {
|
81
|
+
return item.querySelector(
|
82
|
+
'[data-shadcn-phlexcomponents="accordion-trigger"]',
|
83
|
+
)
|
84
|
+
}) as HTMLButtonElement[]
|
85
|
+
|
86
|
+
focusableTriggers = focusableTriggers.filter((trigger) => !trigger.disabled)
|
87
|
+
const index = focusableTriggers.indexOf(trigger)
|
88
|
+
let newIndex = 0
|
89
|
+
|
90
|
+
if (key === 'ArrowUp') {
|
91
|
+
newIndex = index - 1
|
92
|
+
|
93
|
+
if (newIndex < 0) {
|
94
|
+
newIndex = focusableTriggers.length - 1
|
95
|
+
}
|
96
|
+
} else {
|
97
|
+
newIndex = index + 1
|
98
|
+
|
99
|
+
if (newIndex > focusableTriggers.length - 1) {
|
100
|
+
newIndex = 0
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
focusableTriggers[newIndex].focus()
|
105
|
+
}
|
106
|
+
|
107
|
+
openItemsValueChanged(openItems: string[]) {
|
108
|
+
this.itemTargets.forEach((item) => {
|
109
|
+
const itemValue = item.dataset.value as string
|
110
|
+
|
111
|
+
const trigger = item.querySelector(
|
112
|
+
'[data-shadcn-phlexcomponents="accordion-trigger"]',
|
113
|
+
) as HTMLElement
|
114
|
+
const content = item.querySelector(
|
115
|
+
'[data-shadcn-phlexcomponents="accordion-content-container"]',
|
116
|
+
) as HTMLElement
|
117
|
+
|
118
|
+
if (openItems.includes(itemValue)) {
|
119
|
+
showContent({
|
120
|
+
trigger,
|
121
|
+
content: content,
|
122
|
+
contentContainer: content,
|
123
|
+
})
|
124
|
+
} else {
|
125
|
+
hideContent({
|
126
|
+
trigger,
|
127
|
+
content: content,
|
128
|
+
contentContainer: content,
|
129
|
+
})
|
130
|
+
}
|
131
|
+
})
|
132
|
+
}
|
133
|
+
}
|
@@ -3,6 +3,10 @@ import { Controller } from '@hotwired/stimulus'
|
|
3
3
|
export default class extends Controller {
|
4
4
|
static targets = ['image', 'fallback']
|
5
5
|
|
6
|
+
declare readonly imageTarget: HTMLElement
|
7
|
+
declare readonly fallbackTarget: HTMLElement
|
8
|
+
declare readonly hasFallbackTarget: boolean
|
9
|
+
|
6
10
|
connect() {
|
7
11
|
this.imageTarget.onerror = () => {
|
8
12
|
if (this.hasFallbackTarget) {
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
|
3
|
+
export default class extends Controller<HTMLElement> {
|
4
|
+
static targets = ['input', 'indicator']
|
5
|
+
static values = {
|
6
|
+
isChecked: Boolean,
|
7
|
+
}
|
8
|
+
|
9
|
+
declare readonly inputTarget: HTMLInputElement
|
10
|
+
declare readonly indicatorTarget: HTMLInputElement
|
11
|
+
declare isCheckedValue: boolean
|
12
|
+
|
13
|
+
toggle() {
|
14
|
+
this.isCheckedValue = !this.isCheckedValue
|
15
|
+
}
|
16
|
+
|
17
|
+
preventDefault(event: KeyboardEvent) {
|
18
|
+
event.preventDefault()
|
19
|
+
}
|
20
|
+
|
21
|
+
isCheckedValueChanged(isChecked: boolean) {
|
22
|
+
if (isChecked) {
|
23
|
+
this.element.ariaChecked = 'true'
|
24
|
+
this.element.dataset.state = 'checked'
|
25
|
+
this.inputTarget.checked = true
|
26
|
+
this.indicatorTarget.classList.remove('hidden')
|
27
|
+
} else {
|
28
|
+
this.element.ariaChecked = 'false'
|
29
|
+
this.element.dataset.state = 'unchecked'
|
30
|
+
this.inputTarget.checked = false
|
31
|
+
this.indicatorTarget.classList.add('hidden')
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
import { hideContent, showContent } from '@shadcn_phlexcomponents/utils'
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ['trigger', 'content']
|
6
|
+
static values = {
|
7
|
+
isOpen: Boolean,
|
8
|
+
}
|
9
|
+
|
10
|
+
declare readonly triggerTarget: HTMLElement
|
11
|
+
declare readonly contentTarget: HTMLElement
|
12
|
+
declare isOpenValue: boolean
|
13
|
+
|
14
|
+
toggle() {
|
15
|
+
if (this.isOpenValue) {
|
16
|
+
this.close()
|
17
|
+
} else {
|
18
|
+
this.open()
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
open() {
|
23
|
+
this.isOpenValue = true
|
24
|
+
}
|
25
|
+
|
26
|
+
close() {
|
27
|
+
this.isOpenValue = false
|
28
|
+
}
|
29
|
+
|
30
|
+
isOpenValueChanged(isOpen: boolean) {
|
31
|
+
if (isOpen) {
|
32
|
+
showContent({
|
33
|
+
trigger: this.triggerTarget,
|
34
|
+
content: this.contentTarget,
|
35
|
+
contentContainer: this.contentTarget,
|
36
|
+
})
|
37
|
+
} else {
|
38
|
+
hideContent({
|
39
|
+
trigger: this.triggerTarget,
|
40
|
+
content: this.contentTarget,
|
41
|
+
contentContainer: this.contentTarget,
|
42
|
+
})
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import {
|
2
|
+
ON_OPEN_FOCUS_DELAY,
|
3
|
+
lockScroll,
|
4
|
+
showContent,
|
5
|
+
initFloatingUi,
|
6
|
+
unlockScroll,
|
7
|
+
hideContent,
|
8
|
+
focusTrigger,
|
9
|
+
} from '../utils'
|
10
|
+
import CommandRootController from './command_root_controller'
|
11
|
+
|
12
|
+
export default class extends CommandRootController {
|
13
|
+
static targets = [
|
14
|
+
'trigger',
|
15
|
+
'contentContainer',
|
16
|
+
'content',
|
17
|
+
'item',
|
18
|
+
'triggerText',
|
19
|
+
'group',
|
20
|
+
'label',
|
21
|
+
'hiddenInput',
|
22
|
+
'searchInput',
|
23
|
+
'results',
|
24
|
+
'empty',
|
25
|
+
]
|
26
|
+
|
27
|
+
static values = {
|
28
|
+
isOpen: Boolean,
|
29
|
+
selected: String,
|
30
|
+
filteredItemIndexes: Array,
|
31
|
+
}
|
32
|
+
|
33
|
+
declare readonly contentContainerTarget: HTMLElement
|
34
|
+
declare readonly triggerTextTarget: HTMLElement
|
35
|
+
declare readonly hiddenInputTarget: HTMLInputElement
|
36
|
+
declare selectedValue: string
|
37
|
+
declare cleanup: () => void
|
38
|
+
|
39
|
+
open() {
|
40
|
+
this.isOpenValue = true
|
41
|
+
this.highlightItemByIndex(0)
|
42
|
+
|
43
|
+
let index = 0
|
44
|
+
|
45
|
+
if (this.selectedValue) {
|
46
|
+
const item = this.itemTargets.find(
|
47
|
+
(i) => i.dataset.value === this.selectedValue,
|
48
|
+
)
|
49
|
+
|
50
|
+
if (item && !item.dataset.disabled) {
|
51
|
+
index = this.items.indexOf(item)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
this.highlightItemByIndex(index)
|
56
|
+
|
57
|
+
setTimeout(() => {
|
58
|
+
this.searchInputTarget.focus()
|
59
|
+
}, ON_OPEN_FOCUS_DELAY)
|
60
|
+
}
|
61
|
+
|
62
|
+
toggle() {
|
63
|
+
if (this.isOpenValue) {
|
64
|
+
this.close()
|
65
|
+
} else {
|
66
|
+
this.open()
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
onSelect(value: string): void {
|
71
|
+
this.selectedValue = value
|
72
|
+
}
|
73
|
+
|
74
|
+
selectedValueChanged(value: string) {
|
75
|
+
const item = this.itemTargets.find((i) => i.dataset.value === value)
|
76
|
+
|
77
|
+
if (item) {
|
78
|
+
this.triggerTextTarget.textContent = item.textContent
|
79
|
+
|
80
|
+
this.itemTargets.forEach((i) => {
|
81
|
+
if (i.dataset.value === value) {
|
82
|
+
i.setAttribute('aria-selected', 'true')
|
83
|
+
} else {
|
84
|
+
i.setAttribute('aria-selected', 'false')
|
85
|
+
}
|
86
|
+
})
|
87
|
+
|
88
|
+
this.hiddenInputTarget.value = value
|
89
|
+
}
|
90
|
+
|
91
|
+
this.triggerTarget.dataset.hasValue = `${!!value && value.length > 0}`
|
92
|
+
|
93
|
+
const placeholder = this.triggerTarget.dataset.placeholder
|
94
|
+
|
95
|
+
if (placeholder && this.triggerTarget.dataset.hasValue === 'false') {
|
96
|
+
this.triggerTextTarget.textContent = placeholder
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
isOpenValueChanged(isOpen: boolean, previousIsOpen: boolean) {
|
101
|
+
if (isOpen) {
|
102
|
+
lockScroll()
|
103
|
+
|
104
|
+
showContent({
|
105
|
+
trigger: this.triggerTarget,
|
106
|
+
content: this.contentTarget,
|
107
|
+
contentContainer: this.contentContainerTarget,
|
108
|
+
setEqualWidth: true,
|
109
|
+
})
|
110
|
+
|
111
|
+
this.cleanup = initFloatingUi({
|
112
|
+
referenceElement: this.triggerTarget,
|
113
|
+
floatingElement: this.contentContainerTarget,
|
114
|
+
side: this.contentTarget.dataset.side,
|
115
|
+
align: this.contentTarget.dataset.align,
|
116
|
+
sideOffset: 4,
|
117
|
+
})
|
118
|
+
|
119
|
+
this.setupEventListeners()
|
120
|
+
} else {
|
121
|
+
unlockScroll()
|
122
|
+
|
123
|
+
hideContent({
|
124
|
+
trigger: this.triggerTarget,
|
125
|
+
content: this.contentTarget,
|
126
|
+
contentContainer: this.contentContainerTarget,
|
127
|
+
})
|
128
|
+
|
129
|
+
this.cleanupEventListeners()
|
130
|
+
|
131
|
+
// Only focus trigger when is previously opened
|
132
|
+
if (previousIsOpen) {
|
133
|
+
focusTrigger(this.triggerTarget)
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
clickOutside(event: MouseEvent) {
|
139
|
+
const target = event.target
|
140
|
+
// Let #toggle to handle state when clicked on trigger
|
141
|
+
if (target === this.triggerTarget) return
|
142
|
+
|
143
|
+
this.close()
|
144
|
+
}
|
145
|
+
}
|
@@ -0,0 +1,129 @@
|
|
1
|
+
import hotkeys from 'hotkeys-js'
|
2
|
+
import {
|
3
|
+
openWithOverlay,
|
4
|
+
showContent,
|
5
|
+
closeWithOverlay,
|
6
|
+
hideContent,
|
7
|
+
focusTrigger,
|
8
|
+
} from '../utils'
|
9
|
+
import CommandRootController from './command_root_controller'
|
10
|
+
|
11
|
+
declare global {
|
12
|
+
interface Window {
|
13
|
+
Turbo: any
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
export default class extends CommandRootController {
|
18
|
+
static targets = [
|
19
|
+
'trigger',
|
20
|
+
'content',
|
21
|
+
'item',
|
22
|
+
'group',
|
23
|
+
'label',
|
24
|
+
'searchInput',
|
25
|
+
'results',
|
26
|
+
'empty',
|
27
|
+
'modifierKey',
|
28
|
+
]
|
29
|
+
|
30
|
+
declare readonly modifierKeyTarget: HTMLElement
|
31
|
+
declare readonly hasModifierKeyTarget: boolean
|
32
|
+
declare modifierKey?: string
|
33
|
+
declare shortcutKey?: string
|
34
|
+
declare resultsTarget: HTMLElement
|
35
|
+
declare searchInputTarget: HTMLInputElement
|
36
|
+
declare emptyTarget: HTMLElement
|
37
|
+
declare filteredItems: HTMLElement[]
|
38
|
+
declare hotkeyListener: (event: KeyboardEvent) => void
|
39
|
+
declare keybinds: string
|
40
|
+
|
41
|
+
connect() {
|
42
|
+
super.connect()
|
43
|
+
this.hotkeyListener = this.onHotkeyPressed.bind(this)
|
44
|
+
this.setupHotkeys()
|
45
|
+
this.replaceModifierKeyIcon()
|
46
|
+
}
|
47
|
+
|
48
|
+
setupHotkeys() {
|
49
|
+
const modifierKey = this.element.dataset.modifierKey
|
50
|
+
const shortcutKey = this.element.dataset.shortcutKey
|
51
|
+
let keybinds = ''
|
52
|
+
|
53
|
+
if (modifierKey && shortcutKey) {
|
54
|
+
keybinds = `${modifierKey}+${shortcutKey}`
|
55
|
+
|
56
|
+
if (modifierKey === 'ctrl') {
|
57
|
+
keybinds + `,cmd-${shortcutKey}`
|
58
|
+
}
|
59
|
+
} else if (shortcutKey) {
|
60
|
+
keybinds = shortcutKey
|
61
|
+
}
|
62
|
+
|
63
|
+
this.keybinds = keybinds
|
64
|
+
hotkeys(keybinds, this.hotkeyListener)
|
65
|
+
}
|
66
|
+
|
67
|
+
onHotkeyPressed(event: KeyboardEvent) {
|
68
|
+
event.preventDefault()
|
69
|
+
this.open()
|
70
|
+
}
|
71
|
+
|
72
|
+
replaceModifierKeyIcon() {
|
73
|
+
if (this.hasModifierKeyTarget && this.isMac()) {
|
74
|
+
this.modifierKeyTarget.innerHTML = '⌘'
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
isMac() {
|
79
|
+
const navigator = window.navigator as any
|
80
|
+
|
81
|
+
if (navigator.userAgentData) {
|
82
|
+
return navigator.userAgentData.platform === 'macOS'
|
83
|
+
}
|
84
|
+
|
85
|
+
// Fallback to traditional methods
|
86
|
+
return navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
87
|
+
}
|
88
|
+
|
89
|
+
onSelect(value: string) {
|
90
|
+
window.Turbo.visit(value)
|
91
|
+
}
|
92
|
+
|
93
|
+
disconnect() {
|
94
|
+
super.disconnect()
|
95
|
+
|
96
|
+
if (this.keybinds) {
|
97
|
+
hotkeys.unbind(this.keybinds)
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
isOpenValueChanged(isOpen: boolean, previousIsOpen: boolean) {
|
102
|
+
if (isOpen) {
|
103
|
+
openWithOverlay(this.contentTarget.id)
|
104
|
+
|
105
|
+
showContent({
|
106
|
+
trigger: this.triggerTarget,
|
107
|
+
content: this.contentTarget,
|
108
|
+
contentContainer: this.contentTarget,
|
109
|
+
})
|
110
|
+
|
111
|
+
this.setupEventListeners()
|
112
|
+
} else {
|
113
|
+
closeWithOverlay(this.contentTarget.id)
|
114
|
+
|
115
|
+
hideContent({
|
116
|
+
trigger: this.triggerTarget,
|
117
|
+
content: this.contentTarget,
|
118
|
+
contentContainer: this.contentTarget,
|
119
|
+
})
|
120
|
+
|
121
|
+
this.cleanupEventListeners()
|
122
|
+
|
123
|
+
// Only focus trigger when is previously opened
|
124
|
+
if (previousIsOpen) {
|
125
|
+
focusTrigger(this.triggerTarget)
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|