shadcn_phlexcomponents 0.1.11 → 0.1.14
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/app/javascript/controllers/accordion_controller.ts +65 -62
- data/app/javascript/controllers/alert_dialog_controller.ts +12 -0
- data/app/javascript/controllers/avatar_controller.ts +7 -2
- data/app/javascript/controllers/checkbox_controller.ts +11 -4
- data/app/javascript/controllers/collapsible_controller.ts +12 -5
- data/app/javascript/controllers/combobox_controller.ts +270 -39
- data/app/javascript/controllers/command_controller.ts +223 -51
- data/app/javascript/controllers/date_picker_controller.ts +185 -125
- data/app/javascript/controllers/date_range_picker_controller.ts +89 -79
- data/app/javascript/controllers/dialog_controller.ts +59 -57
- data/app/javascript/controllers/dropdown_menu_controller.ts +212 -36
- data/app/javascript/controllers/dropdown_menu_sub_controller.ts +31 -29
- data/app/javascript/controllers/form_field_controller.ts +6 -1
- data/app/javascript/controllers/hover_card_controller.ts +36 -26
- data/app/javascript/controllers/loading_button_controller.ts +6 -1
- data/app/javascript/controllers/popover_controller.ts +42 -65
- data/app/javascript/controllers/progress_controller.ts +9 -3
- data/app/javascript/controllers/radio_group_controller.ts +16 -9
- data/app/javascript/controllers/select_controller.ts +206 -65
- data/app/javascript/controllers/slider_controller.ts +23 -16
- data/app/javascript/controllers/switch_controller.ts +11 -4
- data/app/javascript/controllers/tabs_controller.ts +26 -18
- data/app/javascript/controllers/theme_switcher_controller.ts +6 -1
- data/app/javascript/controllers/toast_container_controller.ts +6 -1
- data/app/javascript/controllers/toast_controller.ts +7 -1
- data/app/javascript/controllers/toggle_controller.ts +28 -0
- data/app/javascript/controllers/toggle_group_controller.ts +28 -0
- data/app/javascript/controllers/tooltip_controller.ts +43 -31
- data/app/javascript/shadcn_phlexcomponents.ts +29 -25
- data/app/javascript/utils/command.ts +544 -0
- data/app/javascript/utils/floating_ui.ts +196 -0
- data/app/javascript/utils/index.ts +417 -0
- data/app/stylesheets/date_picker.css +118 -0
- data/lib/shadcn_phlexcomponents/alias.rb +3 -0
- data/lib/shadcn_phlexcomponents/components/accordion.rb +2 -1
- data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +18 -15
- data/lib/shadcn_phlexcomponents/components/base.rb +14 -0
- data/lib/shadcn_phlexcomponents/components/collapsible.rb +1 -2
- data/lib/shadcn_phlexcomponents/components/combobox.rb +87 -57
- data/lib/shadcn_phlexcomponents/components/command.rb +77 -47
- data/lib/shadcn_phlexcomponents/components/date_picker.rb +25 -81
- data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +21 -4
- data/lib/shadcn_phlexcomponents/components/dialog.rb +14 -12
- data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +5 -4
- data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +2 -1
- data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +64 -0
- data/lib/shadcn_phlexcomponents/components/form.rb +14 -0
- data/lib/shadcn_phlexcomponents/components/hover_card.rb +3 -2
- data/lib/shadcn_phlexcomponents/components/popover.rb +3 -3
- data/lib/shadcn_phlexcomponents/components/select.rb +10 -25
- data/lib/shadcn_phlexcomponents/components/sheet.rb +15 -11
- data/lib/shadcn_phlexcomponents/components/table.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/tabs.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/toast_container.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/toggle.rb +54 -0
- data/lib/shadcn_phlexcomponents/components/tooltip.rb +3 -2
- data/lib/shadcn_phlexcomponents/engine.rb +1 -5
- data/lib/shadcn_phlexcomponents/version.rb +1 -1
- metadata +9 -4
- data/app/javascript/controllers/command_root_controller.ts +0 -355
- data/app/javascript/controllers/dropdown_menu_root_controller.ts +0 -234
- data/app/javascript/utils.ts +0 -437
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6ead95ebdeef8eac55b2ee6101b2fbdb7fb90c7d12f8f489bdb2f45ad507915
|
4
|
+
data.tar.gz: 6f067373fd86d04f7e2478b639c3d5021a265931b648a6729869d1c9bb472bee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9ca6aacc79c59cc008ca03043616c4483dcc65c9858b0134d61ab0d53497fda9e8f2be85f05e9b1d030fc74af0524f725524d3a6830f79333fd14894188cb89
|
7
|
+
data.tar.gz: e1d3d10691bef9568c16af2e2f23f1a7bccce7b512e72a6ef1a53e6db3ce85a95fdefaadbf86bcd9ecbe07f9f61a423cda24aa412ad60d849a99d4efc3501653
|
@@ -1,53 +1,33 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
showContent,
|
4
|
+
hideContent,
|
5
|
+
getNextEnabledIndex,
|
6
|
+
getPreviousEnabledIndex,
|
7
|
+
} from '../utils'
|
8
|
+
|
9
|
+
const AccordionController = class extends Controller<HTMLElement> {
|
10
|
+
// targets
|
11
|
+
static targets = ['item', 'trigger', 'content']
|
12
|
+
declare itemTargets: HTMLElement[]
|
13
|
+
declare triggerTargets: HTMLButtonElement[]
|
14
|
+
declare contentTargets: HTMLElement[]
|
3
15
|
|
4
|
-
|
5
|
-
static targets = ['item']
|
16
|
+
// values
|
6
17
|
static values = { openItems: Array }
|
7
|
-
declare itemTargets: HTMLElement[]
|
8
|
-
declare multiple: boolean
|
9
18
|
declare openItemsValue: string[]
|
10
19
|
|
20
|
+
// custom properties
|
21
|
+
declare multiple: boolean
|
22
|
+
|
11
23
|
connect() {
|
12
24
|
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
25
|
}
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
27
|
+
contentTargetConnected(content: HTMLElement) {
|
28
|
+
setTimeout(() => {
|
29
|
+
this.setContentHeight(content)
|
30
|
+
}, 100)
|
51
31
|
}
|
52
32
|
|
53
33
|
toggle(event: MouseEvent) {
|
@@ -75,30 +55,27 @@ export default class extends Controller<HTMLElement> {
|
|
75
55
|
|
76
56
|
focusTrigger(event: KeyboardEvent) {
|
77
57
|
const trigger = event.currentTarget as HTMLButtonElement
|
78
|
-
const key = event.key
|
58
|
+
const key = event.key
|
79
59
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
)
|
84
|
-
}) as HTMLButtonElement[]
|
60
|
+
const focusableTriggers = this.triggerTargets.filter(
|
61
|
+
(trigger) => !trigger.disabled,
|
62
|
+
)
|
85
63
|
|
86
|
-
focusableTriggers = focusableTriggers.filter((trigger) => !trigger.disabled)
|
87
64
|
const index = focusableTriggers.indexOf(trigger)
|
88
65
|
let newIndex = 0
|
89
66
|
|
90
67
|
if (key === 'ArrowUp') {
|
91
|
-
newIndex =
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
}
|
68
|
+
newIndex = getPreviousEnabledIndex({
|
69
|
+
items: focusableTriggers,
|
70
|
+
currentIndex: index,
|
71
|
+
wrapAround: true,
|
72
|
+
})
|
96
73
|
} else {
|
97
|
-
newIndex =
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
}
|
74
|
+
newIndex = getNextEnabledIndex({
|
75
|
+
items: focusableTriggers,
|
76
|
+
currentIndex: index,
|
77
|
+
wrapAround: true,
|
78
|
+
})
|
102
79
|
}
|
103
80
|
|
104
81
|
focusableTriggers[newIndex].focus()
|
@@ -108,11 +85,11 @@ export default class extends Controller<HTMLElement> {
|
|
108
85
|
this.itemTargets.forEach((item) => {
|
109
86
|
const itemValue = item.dataset.value as string
|
110
87
|
|
111
|
-
const trigger =
|
112
|
-
|
88
|
+
const trigger = this.triggerTargets.find((trigger) =>
|
89
|
+
item.contains(trigger),
|
113
90
|
) as HTMLElement
|
114
|
-
const content =
|
115
|
-
|
91
|
+
const content = this.contentTargets.find((content) =>
|
92
|
+
item.contains(content),
|
116
93
|
) as HTMLElement
|
117
94
|
|
118
95
|
if (openItems.includes(itemValue)) {
|
@@ -130,4 +107,30 @@ export default class extends Controller<HTMLElement> {
|
|
130
107
|
}
|
131
108
|
})
|
132
109
|
}
|
110
|
+
|
111
|
+
protected setContentHeight(element: HTMLElement) {
|
112
|
+
const height =
|
113
|
+
this.getContentHeight(element) || element.getBoundingClientRect().height
|
114
|
+
element.style.setProperty('--radix-accordion-content-height', `${height}px`)
|
115
|
+
}
|
116
|
+
|
117
|
+
getContentHeight(el: HTMLElement) {
|
118
|
+
const clone = el.cloneNode(true) as HTMLElement
|
119
|
+
Object.assign(clone.style, {
|
120
|
+
display: 'block',
|
121
|
+
position: 'absolute',
|
122
|
+
visibility: 'hidden',
|
123
|
+
})
|
124
|
+
|
125
|
+
document.body.appendChild(clone)
|
126
|
+
const height = clone.getBoundingClientRect().height
|
127
|
+
document.body.removeChild(clone)
|
128
|
+
|
129
|
+
return height
|
130
|
+
}
|
133
131
|
}
|
132
|
+
|
133
|
+
type Accordion = InstanceType<typeof AccordionController>
|
134
|
+
|
135
|
+
export { AccordionController }
|
136
|
+
export type { Accordion }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { DialogController } from './dialog_controller'
|
2
|
+
|
3
|
+
const AlertDialogController = class extends DialogController {
|
4
|
+
protected onDOMClick() {
|
5
|
+
return
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
type AlertDialog = InstanceType<typeof AlertDialogController>
|
10
|
+
|
11
|
+
export { AlertDialogController }
|
12
|
+
export type { AlertDialog }
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
|
-
|
3
|
+
const AvatarController = class extends Controller {
|
4
|
+
// targets
|
4
5
|
static targets = ['image', 'fallback']
|
5
|
-
|
6
6
|
declare readonly imageTarget: HTMLElement
|
7
7
|
declare readonly fallbackTarget: HTMLElement
|
8
8
|
declare readonly hasFallbackTarget: boolean
|
@@ -17,3 +17,8 @@ export default class extends Controller {
|
|
17
17
|
}
|
18
18
|
}
|
19
19
|
}
|
20
|
+
|
21
|
+
type Avatar = InstanceType<typeof AvatarController>
|
22
|
+
|
23
|
+
export { AvatarController }
|
24
|
+
export type { Avatar }
|
@@ -1,13 +1,15 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
|
-
|
3
|
+
const CheckboxController = class extends Controller<HTMLElement> {
|
4
|
+
// targets
|
4
5
|
static targets = ['input', 'indicator']
|
6
|
+
declare readonly inputTarget: HTMLInputElement
|
7
|
+
declare readonly indicatorTarget: HTMLInputElement
|
8
|
+
|
9
|
+
// values
|
5
10
|
static values = {
|
6
11
|
isChecked: Boolean,
|
7
12
|
}
|
8
|
-
|
9
|
-
declare readonly inputTarget: HTMLInputElement
|
10
|
-
declare readonly indicatorTarget: HTMLInputElement
|
11
13
|
declare isCheckedValue: boolean
|
12
14
|
|
13
15
|
toggle() {
|
@@ -32,3 +34,8 @@ export default class extends Controller<HTMLElement> {
|
|
32
34
|
}
|
33
35
|
}
|
34
36
|
}
|
37
|
+
|
38
|
+
type Checkbox = InstanceType<typeof CheckboxController>
|
39
|
+
|
40
|
+
export { CheckboxController }
|
41
|
+
export type { Checkbox }
|
@@ -1,14 +1,16 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
|
-
import { hideContent, showContent } from '
|
2
|
+
import { hideContent, showContent } from '../utils'
|
3
3
|
|
4
|
-
|
4
|
+
const CollapsibleController = class extends Controller {
|
5
|
+
// targets
|
5
6
|
static targets = ['trigger', 'content']
|
7
|
+
declare readonly triggerTarget: HTMLElement
|
8
|
+
declare readonly contentTarget: HTMLElement
|
9
|
+
|
10
|
+
// values
|
6
11
|
static values = {
|
7
12
|
isOpen: Boolean,
|
8
13
|
}
|
9
|
-
|
10
|
-
declare readonly triggerTarget: HTMLElement
|
11
|
-
declare readonly contentTarget: HTMLElement
|
12
14
|
declare isOpenValue: boolean
|
13
15
|
|
14
16
|
toggle() {
|
@@ -43,3 +45,8 @@ export default class extends Controller {
|
|
43
45
|
}
|
44
46
|
}
|
45
47
|
}
|
48
|
+
|
49
|
+
type Collapsible = InstanceType<typeof CollapsibleController>
|
50
|
+
|
51
|
+
export { CollapsibleController }
|
52
|
+
export type { Collapsible }
|
@@ -2,73 +2,191 @@ import {
|
|
2
2
|
ON_OPEN_FOCUS_DELAY,
|
3
3
|
lockScroll,
|
4
4
|
showContent,
|
5
|
-
initFloatingUi,
|
6
5
|
unlockScroll,
|
7
6
|
hideContent,
|
8
7
|
focusTrigger,
|
8
|
+
setGroupLabelsId,
|
9
|
+
onClickOutside,
|
9
10
|
} from '../utils'
|
10
|
-
import
|
11
|
+
import { initFloatingUi } from '../utils/floating_ui'
|
12
|
+
import { Controller } from '@hotwired/stimulus'
|
13
|
+
import Fuse from 'fuse.js'
|
14
|
+
import {
|
15
|
+
scrollToItem,
|
16
|
+
highlightItem,
|
17
|
+
highlightItemByIndex,
|
18
|
+
filteredItemsChanged,
|
19
|
+
setItemsGroupId,
|
20
|
+
search,
|
21
|
+
clearRemoteResults,
|
22
|
+
resetState,
|
23
|
+
} from '../utils/command'
|
24
|
+
|
25
|
+
import { useClickOutside, useDebounce } from 'stimulus-use'
|
11
26
|
|
12
|
-
|
27
|
+
const ComboboxController = class extends Controller<HTMLElement> {
|
28
|
+
// targets
|
13
29
|
static targets = [
|
14
30
|
'trigger',
|
31
|
+
'triggerText',
|
15
32
|
'contentContainer',
|
16
33
|
'content',
|
17
34
|
'item',
|
18
|
-
'triggerText',
|
19
35
|
'group',
|
20
|
-
'label',
|
21
36
|
'hiddenInput',
|
22
37
|
'searchInput',
|
23
|
-
'
|
38
|
+
'list',
|
39
|
+
'listContainer',
|
24
40
|
'empty',
|
41
|
+
'loading',
|
42
|
+
'error',
|
25
43
|
]
|
44
|
+
declare readonly triggerTarget: HTMLElement
|
45
|
+
declare readonly triggerTextTarget: HTMLElement
|
46
|
+
declare readonly contentContainerTarget: HTMLElement
|
47
|
+
declare readonly contentTarget: HTMLElement
|
48
|
+
declare readonly itemTargets: HTMLElement[]
|
49
|
+
declare readonly groupTargets: HTMLElement[]
|
50
|
+
declare readonly hiddenInputTarget: HTMLInputElement
|
51
|
+
declare readonly searchInputTarget: HTMLInputElement
|
52
|
+
declare readonly listTarget: HTMLElement
|
53
|
+
declare readonly listContainerTarget: HTMLElement
|
54
|
+
declare readonly emptyTarget: HTMLElement
|
55
|
+
declare readonly loadingTarget: HTMLElement
|
56
|
+
declare readonly errorTarget: HTMLElement
|
26
57
|
|
58
|
+
// values
|
27
59
|
static values = {
|
28
60
|
isOpen: Boolean,
|
29
61
|
selected: String,
|
30
62
|
filteredItemIndexes: Array,
|
31
63
|
}
|
32
|
-
|
33
|
-
declare readonly contentContainerTarget: HTMLElement
|
34
|
-
declare readonly triggerTextTarget: HTMLElement
|
35
|
-
declare readonly hiddenInputTarget: HTMLInputElement
|
64
|
+
declare isOpenValue: boolean
|
36
65
|
declare selectedValue: string
|
37
|
-
declare
|
66
|
+
declare filteredItemIndexesValue: number[]
|
38
67
|
|
39
|
-
|
40
|
-
|
41
|
-
|
68
|
+
// custom properties
|
69
|
+
declare orderedItems: HTMLElement[]
|
70
|
+
declare itemsInnerText: string[]
|
71
|
+
declare filteredItems: HTMLElement[]
|
72
|
+
declare fuse: Fuse<string>
|
73
|
+
declare scrollingViaKeyboard: boolean
|
74
|
+
declare keyboardScrollTimeout: number
|
75
|
+
declare abortController?: AbortController
|
76
|
+
declare searchPath?: string
|
77
|
+
declare isDirty: boolean
|
78
|
+
declare isLoading: boolean
|
79
|
+
declare DOMKeydownListener: (event: KeyboardEvent) => void
|
80
|
+
declare cleanup: () => void
|
42
81
|
|
43
|
-
|
82
|
+
static debounces = ['search']
|
44
83
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
84
|
+
connect() {
|
85
|
+
this.orderedItems = [...this.itemTargets]
|
86
|
+
this.itemsInnerText = this.itemTargets.map((i) => i.innerText.trim())
|
87
|
+
this.fuse = new Fuse(this.itemsInnerText)
|
88
|
+
this.filteredItemIndexesValue = Array.from(
|
89
|
+
{ length: this.itemTargets.length },
|
90
|
+
(_, i) => i,
|
91
|
+
)
|
92
|
+
this.isLoading = false
|
93
|
+
this.filteredItems = this.itemTargets
|
94
|
+
this.isDirty = false
|
95
|
+
this.searchPath = this.element.dataset.searchPath
|
96
|
+
setGroupLabelsId(this)
|
97
|
+
setItemsGroupId(this)
|
98
|
+
useDebounce(this)
|
99
|
+
useClickOutside(this, { element: this.contentTarget, dispatchEvent: false })
|
100
|
+
this.DOMKeydownListener = this.onDOMKeydown.bind(this)
|
101
|
+
}
|
49
102
|
|
50
|
-
|
51
|
-
|
52
|
-
|
103
|
+
toggle() {
|
104
|
+
if (this.isOpenValue) {
|
105
|
+
this.close()
|
106
|
+
} else {
|
107
|
+
this.open()
|
53
108
|
}
|
109
|
+
}
|
54
110
|
|
55
|
-
|
111
|
+
open() {
|
112
|
+
this.isOpenValue = true
|
56
113
|
|
57
114
|
setTimeout(() => {
|
58
115
|
this.searchInputTarget.focus()
|
116
|
+
|
117
|
+
let index = 0
|
118
|
+
console.log('this.selectedValue', this.selectedValue)
|
119
|
+
if (this.selectedValue) {
|
120
|
+
const item = this.filteredItems.find(
|
121
|
+
(i) => i.dataset.value === this.selectedValue,
|
122
|
+
)
|
123
|
+
|
124
|
+
if (item && !item.dataset.disabled) {
|
125
|
+
index = this.filteredItems.indexOf(item)
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
this.highlightItemByIndex(index)
|
59
130
|
}, ON_OPEN_FOCUS_DELAY)
|
60
131
|
}
|
61
132
|
|
62
|
-
|
63
|
-
|
64
|
-
|
133
|
+
close() {
|
134
|
+
this.isOpenValue = false
|
135
|
+
resetState(this)
|
136
|
+
}
|
137
|
+
|
138
|
+
scrollToItem(index: number) {
|
139
|
+
scrollToItem(this, index)
|
140
|
+
}
|
141
|
+
|
142
|
+
highlightItem(
|
143
|
+
event: MouseEvent | KeyboardEvent | null = null,
|
144
|
+
index: number | null = null,
|
145
|
+
) {
|
146
|
+
highlightItem(this, event, index)
|
147
|
+
}
|
148
|
+
|
149
|
+
highlightItemByIndex(index: number) {
|
150
|
+
highlightItemByIndex(this, index)
|
151
|
+
}
|
152
|
+
|
153
|
+
select(event: MouseEvent | KeyboardEvent) {
|
154
|
+
let item = undefined as HTMLElement | undefined
|
155
|
+
|
156
|
+
if (event instanceof KeyboardEvent) {
|
157
|
+
item = this.filteredItems.find((i) => i.dataset.highlighted === 'true')
|
65
158
|
} else {
|
66
|
-
|
159
|
+
// mouse event
|
160
|
+
item = event.currentTarget as HTMLElement
|
161
|
+
}
|
162
|
+
|
163
|
+
if (item) {
|
164
|
+
this.selectedValue = item.dataset.value as string
|
165
|
+
|
166
|
+
// setTimeout is needed for selectedValueChanged to finish executing
|
167
|
+
setTimeout(() => {
|
168
|
+
this.close()
|
169
|
+
}, 100)
|
67
170
|
}
|
68
171
|
}
|
69
172
|
|
70
|
-
|
71
|
-
this.
|
173
|
+
inputKeydown(event: KeyboardEvent) {
|
174
|
+
if (event.key === ' ' && this.searchInputTarget.value.length === 0) {
|
175
|
+
event.preventDefault()
|
176
|
+
}
|
177
|
+
|
178
|
+
this.hideError()
|
179
|
+
this.showList()
|
180
|
+
}
|
181
|
+
|
182
|
+
search(event: InputEvent) {
|
183
|
+
this.isDirty = true
|
184
|
+
clearRemoteResults(this)
|
185
|
+
search(this, event)
|
186
|
+
}
|
187
|
+
|
188
|
+
clickOutside(event: MouseEvent) {
|
189
|
+
onClickOutside(this, event)
|
72
190
|
}
|
73
191
|
|
74
192
|
selectedValueChanged(value: string) {
|
@@ -99,7 +217,7 @@ export default class extends CommandRootController {
|
|
99
217
|
|
100
218
|
isOpenValueChanged(isOpen: boolean, previousIsOpen: boolean) {
|
101
219
|
if (isOpen) {
|
102
|
-
lockScroll()
|
220
|
+
lockScroll(this.contentTarget.id)
|
103
221
|
|
104
222
|
showContent({
|
105
223
|
trigger: this.triggerTarget,
|
@@ -118,7 +236,7 @@ export default class extends CommandRootController {
|
|
118
236
|
|
119
237
|
this.setupEventListeners()
|
120
238
|
} else {
|
121
|
-
unlockScroll()
|
239
|
+
unlockScroll(this.contentTarget.id)
|
122
240
|
|
123
241
|
hideContent({
|
124
242
|
trigger: this.triggerTarget,
|
@@ -126,20 +244,133 @@ export default class extends CommandRootController {
|
|
126
244
|
contentContainer: this.contentContainerTarget,
|
127
245
|
})
|
128
246
|
|
129
|
-
this.cleanupEventListeners()
|
130
|
-
|
131
|
-
// Only focus trigger when is previously opened
|
132
247
|
if (previousIsOpen) {
|
133
248
|
focusTrigger(this.triggerTarget)
|
134
249
|
}
|
250
|
+
|
251
|
+
this.cleanupEventListeners()
|
135
252
|
}
|
136
253
|
}
|
137
254
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
255
|
+
filteredItemIndexesValueChanged(filteredItemIndexes: number[]) {
|
256
|
+
filteredItemsChanged(this, filteredItemIndexes)
|
257
|
+
}
|
258
|
+
|
259
|
+
disconnect() {
|
260
|
+
this.cleanupEventListeners()
|
261
|
+
resetState(this)
|
262
|
+
}
|
263
|
+
|
264
|
+
showLoading() {
|
265
|
+
this.isLoading = true
|
266
|
+
this.loadingTarget.classList.remove('hidden')
|
267
|
+
}
|
268
|
+
|
269
|
+
hideLoading() {
|
270
|
+
this.isLoading = false
|
271
|
+
this.loadingTarget.classList.add('hidden')
|
272
|
+
}
|
273
|
+
|
274
|
+
showList() {
|
275
|
+
this.listTarget.classList.remove('hidden')
|
276
|
+
}
|
142
277
|
|
143
|
-
|
278
|
+
hideList() {
|
279
|
+
this.listTarget.classList.add('hidden')
|
280
|
+
}
|
281
|
+
|
282
|
+
showError() {
|
283
|
+
this.errorTarget.classList.remove('hidden')
|
284
|
+
}
|
285
|
+
|
286
|
+
hideError() {
|
287
|
+
this.errorTarget.classList.add('hidden')
|
288
|
+
}
|
289
|
+
|
290
|
+
showEmpty() {
|
291
|
+
this.emptyTarget.classList.remove('hidden')
|
292
|
+
}
|
293
|
+
|
294
|
+
hideEmpty() {
|
295
|
+
this.emptyTarget.classList.add('hidden')
|
296
|
+
}
|
297
|
+
|
298
|
+
showSelectedRemoteItems() {
|
299
|
+
const remoteItems = Array.from(
|
300
|
+
this.element.querySelectorAll(
|
301
|
+
`[data-shadcn-phlexcomponents="${this.identifier}-item"][data-remote='true']`,
|
302
|
+
),
|
303
|
+
)
|
304
|
+
|
305
|
+
remoteItems.forEach((i) => {
|
306
|
+
const isInsideGroup =
|
307
|
+
i.parentElement?.dataset?.shadcnPhlexcomponents ===
|
308
|
+
`${this.identifier}-group`
|
309
|
+
|
310
|
+
if (isInsideGroup) {
|
311
|
+
const isRemoteGroup = i.parentElement.dataset.remote === 'true'
|
312
|
+
|
313
|
+
if (isRemoteGroup) {
|
314
|
+
i.parentElement.classList.remove('hidden')
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
i.ariaHidden = 'false'
|
319
|
+
i.classList.remove('hidden')
|
320
|
+
})
|
321
|
+
}
|
322
|
+
|
323
|
+
hideSelectedRemoteItems() {
|
324
|
+
const remoteItems = Array.from(
|
325
|
+
this.element.querySelectorAll(
|
326
|
+
`[data-shadcn-phlexcomponents="${this.identifier}-item"][data-remote='true']`,
|
327
|
+
),
|
328
|
+
)
|
329
|
+
|
330
|
+
remoteItems.forEach((i) => {
|
331
|
+
const isInsideGroup =
|
332
|
+
i.parentElement?.dataset?.shadcnPhlexcomponents ===
|
333
|
+
`${this.identifier}-group`
|
334
|
+
|
335
|
+
if (isInsideGroup) {
|
336
|
+
const isRemoteGroup = i.parentElement.dataset.remote === 'true'
|
337
|
+
|
338
|
+
if (isRemoteGroup) {
|
339
|
+
i.parentElement.classList.add('hidden')
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
i.ariaHidden = 'true'
|
344
|
+
i.classList.add('hidden')
|
345
|
+
})
|
346
|
+
}
|
347
|
+
|
348
|
+
protected setupEventListeners() {
|
349
|
+
document.addEventListener('keydown', this.DOMKeydownListener)
|
350
|
+
}
|
351
|
+
|
352
|
+
protected cleanupEventListeners() {
|
353
|
+
document.removeEventListener('keydown', this.DOMKeydownListener)
|
354
|
+
|
355
|
+
if (this.abortController) {
|
356
|
+
this.abortController.abort()
|
357
|
+
}
|
358
|
+
}
|
359
|
+
|
360
|
+
protected onDOMKeydown(event: KeyboardEvent) {
|
361
|
+
if (!this.isOpenValue) return
|
362
|
+
|
363
|
+
const key = event.key
|
364
|
+
|
365
|
+
if (['Tab', 'Enter'].includes(key)) event.preventDefault()
|
366
|
+
|
367
|
+
if (key === 'Escape') {
|
368
|
+
this.close()
|
369
|
+
}
|
144
370
|
}
|
145
371
|
}
|
372
|
+
|
373
|
+
type Combobox = InstanceType<typeof ComboboxController>
|
374
|
+
|
375
|
+
export { ComboboxController }
|
376
|
+
export type { Combobox }
|