@hakumi-dev/hakumi-components 0.1.17-pre → 0.1.19-pre
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.
- package/README.md +218 -369
- package/app/javascript/hakumi_components/controllers/hakumi/admin_panel_controller.js +5 -7
- package/app/javascript/hakumi_components/controllers/hakumi/back_top_controller.js +1 -1
- package/app/javascript/hakumi_components/controllers/hakumi/button_controller.js +108 -2
- package/app/javascript/hakumi_components/controllers/hakumi/calendar_controller.js +183 -95
- package/app/javascript/hakumi_components/controllers/hakumi/color_picker_controller.js +23 -285
- package/app/javascript/hakumi_components/controllers/hakumi/date_picker_controller.js +274 -262
- package/app/javascript/hakumi_components/controllers/hakumi/float_button_group_controller.js +2 -2
- package/app/javascript/hakumi_components/controllers/hakumi/message_controller.js +4 -2
- package/app/javascript/hakumi_components/controllers/hakumi/modal_controller.js +119 -125
- package/app/javascript/hakumi_components/controllers/hakumi/table/editable.js +291 -0
- package/app/javascript/hakumi_components/controllers/hakumi/table_controller.js +166 -366
- package/app/javascript/hakumi_components/controllers/hakumi/tabs_controller.js +8 -2
- package/app/javascript/hakumi_components/controllers/hakumi/tag_controller.js +27 -25
- package/app/javascript/hakumi_components/controllers/hakumi/tag_group_controller.js +19 -18
- package/app/javascript/hakumi_components/controllers/hakumi/theme_controller.js +116 -117
- package/app/javascript/hakumi_components/controllers/hakumi/transfer_controller.js +17 -1
- package/app/javascript/hakumi_components/controllers/hakumi/tree_controller.js +363 -78
- package/app/javascript/hakumi_components/controllers/hakumi/typography_controller.js +3 -3
- package/app/javascript/hakumi_components/controllers/hakumi/upload_controller.js +320 -204
- package/app/javascript/hakumi_components/core/render_component.js +37 -11
- package/app/javascript/hakumi_components/utils/color_helper.js +262 -0
- package/app/javascript/stylesheets/_base.scss +9 -0
- package/app/javascript/stylesheets/_hakumi_components.scss +1 -0
- package/app/javascript/stylesheets/components/_breadcrumb.scss +2 -2
- package/app/javascript/stylesheets/components/_calendar.scss +13 -13
- package/app/javascript/stylesheets/components/_cascader.scss +5 -5
- package/app/javascript/stylesheets/components/_checkbox.scss +9 -11
- package/app/javascript/stylesheets/components/_color_picker.scss +11 -11
- package/app/javascript/stylesheets/components/_date_picker.scss +4 -4
- package/app/javascript/stylesheets/components/_descriptions.scss +2 -2
- package/app/javascript/stylesheets/components/_drawer.scss +3 -3
- package/app/javascript/stylesheets/components/_dropdown.scss +2 -2
- package/app/javascript/stylesheets/components/_flex.scss +1 -1
- package/app/javascript/stylesheets/components/_float_button.scss +5 -5
- package/app/javascript/stylesheets/components/_form_item.scss +92 -0
- package/app/javascript/stylesheets/components/_image.scss +15 -15
- package/app/javascript/stylesheets/components/_input.scss +23 -113
- package/app/javascript/stylesheets/components/_layout.scss +27 -26
- package/app/javascript/stylesheets/components/_menu.scss +15 -15
- package/app/javascript/stylesheets/components/_modal.scss +13 -13
- package/app/javascript/stylesheets/components/_notification.scss +3 -3
- package/app/javascript/stylesheets/components/_popover.scss +1 -1
- package/app/javascript/stylesheets/components/_segmented.scss +3 -3
- package/app/javascript/stylesheets/components/_select.scss +6 -6
- package/app/javascript/stylesheets/components/_slider.scss +1 -1
- package/app/javascript/stylesheets/components/_spin.scss +2 -2
- package/app/javascript/stylesheets/components/_steps.scss +10 -10
- package/app/javascript/stylesheets/components/_switch.scss +11 -10
- package/app/javascript/stylesheets/components/_table.scss +6 -6
- package/app/javascript/stylesheets/components/_tag.scss +2 -2
- package/app/javascript/stylesheets/components/_tooltip.scss +4 -4
- package/app/javascript/stylesheets/components/_tree_select.scss +3 -3
- package/app/javascript/stylesheets/components/_typography.scss +3 -3
- package/app/javascript/stylesheets/components/_upload.scss +4 -4
- package/package.json +2 -2
|
@@ -335,8 +335,14 @@ export default class extends RegistryController {
|
|
|
335
335
|
|
|
336
336
|
|
|
337
337
|
if (wasActive && this._tabs.length > 0) {
|
|
338
|
-
const
|
|
339
|
-
|
|
338
|
+
const candidates = [
|
|
339
|
+
...this._tabs.slice(tabIndex),
|
|
340
|
+
...this._tabs.slice(0, tabIndex)
|
|
341
|
+
]
|
|
342
|
+
const nextTab = candidates.find(tab => !tab.disabled)
|
|
343
|
+
if (nextTab) {
|
|
344
|
+
this.#activateTabByKey(nextTab.key)
|
|
345
|
+
}
|
|
340
346
|
}
|
|
341
347
|
|
|
342
348
|
this.#syncOverflow()
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import RegistryController from "../base/registry_controller.js"
|
|
2
2
|
|
|
3
|
-
export default class extends
|
|
3
|
+
export default class extends RegistryController {
|
|
4
4
|
static values = {
|
|
5
5
|
checkable: { type: Boolean, default: false },
|
|
6
6
|
checked: { type: Boolean, default: false }
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
setup() {
|
|
10
|
+
if (this.checkableValue) {
|
|
11
|
+
this.boundHandleClick = this.handleClick.bind(this)
|
|
12
|
+
this.element.addEventListener("click", this.boundHandleClick)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
teardown() {
|
|
17
|
+
if (this.boundHandleClick) {
|
|
18
|
+
this.element.removeEventListener("click", this.boundHandleClick)
|
|
19
|
+
this.boundHandleClick = null
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
registerApi() {
|
|
10
24
|
this.element.hakumiComponent = {
|
|
11
25
|
name: "tag",
|
|
12
26
|
version: 1,
|
|
@@ -19,18 +33,6 @@ export default class extends Controller {
|
|
|
19
33
|
isChecked: () => this.isChecked()
|
|
20
34
|
}
|
|
21
35
|
}
|
|
22
|
-
|
|
23
|
-
if (this.checkableValue) {
|
|
24
|
-
this.element.addEventListener("click", this.#handleClick)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
disconnect() {
|
|
29
|
-
delete this.element.hakumiComponent
|
|
30
|
-
|
|
31
|
-
if (this.checkableValue) {
|
|
32
|
-
this.element.removeEventListener("click", this.#handleClick)
|
|
33
|
-
}
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
close(event) {
|
|
@@ -60,8 +62,8 @@ export default class extends Controller {
|
|
|
60
62
|
if (!this.checkableValue) return
|
|
61
63
|
|
|
62
64
|
this.checkedValue = !this.checkedValue
|
|
63
|
-
this
|
|
64
|
-
|
|
65
|
+
this.updateCheckedState()
|
|
66
|
+
|
|
65
67
|
this.dispatch("change", {
|
|
66
68
|
detail: { checked: this.checkedValue, element: this.element }
|
|
67
69
|
})
|
|
@@ -69,10 +71,10 @@ export default class extends Controller {
|
|
|
69
71
|
|
|
70
72
|
check() {
|
|
71
73
|
if (!this.checkableValue || this.checkedValue) return
|
|
72
|
-
|
|
74
|
+
|
|
73
75
|
this.checkedValue = true
|
|
74
|
-
this
|
|
75
|
-
|
|
76
|
+
this.updateCheckedState()
|
|
77
|
+
|
|
76
78
|
this.dispatch("change", {
|
|
77
79
|
detail: { checked: true, element: this.element }
|
|
78
80
|
})
|
|
@@ -80,10 +82,10 @@ export default class extends Controller {
|
|
|
80
82
|
|
|
81
83
|
uncheck() {
|
|
82
84
|
if (!this.checkableValue || !this.checkedValue) return
|
|
83
|
-
|
|
85
|
+
|
|
84
86
|
this.checkedValue = false
|
|
85
|
-
this
|
|
86
|
-
|
|
87
|
+
this.updateCheckedState()
|
|
88
|
+
|
|
87
89
|
this.dispatch("change", {
|
|
88
90
|
detail: { checked: false, element: this.element }
|
|
89
91
|
})
|
|
@@ -93,12 +95,12 @@ export default class extends Controller {
|
|
|
93
95
|
return this.checkedValue
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
handleClick(event) {
|
|
97
99
|
if (event.target.closest(".hakumi-tag-close-icon")) return
|
|
98
100
|
this.toggle()
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
updateCheckedState() {
|
|
102
104
|
this.element.classList.toggle("hakumi-tag-checkable-checked", this.checkedValue)
|
|
103
105
|
}
|
|
104
106
|
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import
|
|
1
|
+
import RegistryController from "../base/registry_controller.js"
|
|
2
2
|
import Sortable from "sortablejs"
|
|
3
3
|
|
|
4
|
-
export default class extends
|
|
4
|
+
export default class extends RegistryController {
|
|
5
5
|
static values = {
|
|
6
6
|
sortable: { type: Boolean, default: false },
|
|
7
7
|
animation: { type: Number, default: 150 }
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
setup() {
|
|
11
11
|
this._sortable = null
|
|
12
12
|
|
|
13
13
|
if (this.sortableValue) {
|
|
14
|
-
this
|
|
14
|
+
this.setupSortable()
|
|
15
15
|
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
teardown() {
|
|
19
|
+
this.destroySortable()
|
|
20
|
+
}
|
|
16
21
|
|
|
22
|
+
registerApi() {
|
|
17
23
|
this.element.hakumiComponent = {
|
|
18
24
|
name: "tag_group",
|
|
19
25
|
version: 1,
|
|
@@ -28,16 +34,11 @@ export default class extends Controller {
|
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
disconnect() {
|
|
32
|
-
this.#destroySortable()
|
|
33
|
-
delete this.element.hakumiComponent
|
|
34
|
-
}
|
|
35
|
-
|
|
36
37
|
sortableValueChanged() {
|
|
37
38
|
if (this.sortableValue) {
|
|
38
|
-
this
|
|
39
|
+
this.setupSortable()
|
|
39
40
|
} else {
|
|
40
|
-
this
|
|
41
|
+
this.destroySortable()
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -61,7 +62,7 @@ export default class extends Controller {
|
|
|
61
62
|
return this.getTags().map(tag => tag.textContent.trim())
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
setupSortable() {
|
|
65
66
|
if (this._sortable) return
|
|
66
67
|
|
|
67
68
|
this._sortable = Sortable.create(this.element, {
|
|
@@ -74,19 +75,19 @@ export default class extends Controller {
|
|
|
74
75
|
this.dispatch("sortStart", { detail: { item: evt.item, oldIndex: evt.oldIndex } })
|
|
75
76
|
},
|
|
76
77
|
onEnd: (evt) => {
|
|
77
|
-
this.dispatch("sortEnd", {
|
|
78
|
-
detail: {
|
|
79
|
-
item: evt.item,
|
|
80
|
-
oldIndex: evt.oldIndex,
|
|
78
|
+
this.dispatch("sortEnd", {
|
|
79
|
+
detail: {
|
|
80
|
+
item: evt.item,
|
|
81
|
+
oldIndex: evt.oldIndex,
|
|
81
82
|
newIndex: evt.newIndex,
|
|
82
83
|
values: this.getTagValues()
|
|
83
|
-
}
|
|
84
|
+
}
|
|
84
85
|
})
|
|
85
86
|
}
|
|
86
87
|
})
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
destroySortable() {
|
|
90
91
|
if (this._sortable) {
|
|
91
92
|
this._sortable.destroy()
|
|
92
93
|
this._sortable = null
|
|
@@ -2,136 +2,135 @@ import RegistryController from "../base/registry_controller.js"
|
|
|
2
2
|
import { Persistence } from "../../core/persistence.js"
|
|
3
3
|
|
|
4
4
|
export default class extends RegistryController {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
static values = {
|
|
6
|
+
default: { type: String, default: "light" },
|
|
7
|
+
storageKey: { type: String, default: "theme" },
|
|
8
|
+
syncSandbox: { type: Boolean, default: true },
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static targets = ["sandboxFrame"]
|
|
12
|
+
|
|
13
|
+
static mount() {
|
|
14
|
+
Persistence.ensureHost({ id: "theme", controllerName: "hakumi--theme" })
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setup() {
|
|
18
|
+
if (window.__hakumiThemeActive && window.__hakumiThemeActive !== this.element.id) return
|
|
19
|
+
window.__hakumiThemeActive = this.element.id
|
|
20
|
+
|
|
21
|
+
this._mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
|
|
22
|
+
|
|
23
|
+
// Check if there's an existing explicit theme set in HTML
|
|
24
|
+
const existingTheme = document.documentElement.getAttribute("data-theme")
|
|
25
|
+
|
|
26
|
+
this.boundHandleSystemThemeChange = (e) => {
|
|
27
|
+
const currentTheme = document.documentElement.getAttribute("data-theme")
|
|
28
|
+
// If theme is "auto", don't change the attribute - let CSS media query handle it
|
|
29
|
+
// Only dispatch event for sync purposes
|
|
30
|
+
if (currentTheme === "auto") {
|
|
31
|
+
const effectiveTheme = e.matches ? "dark" : "light"
|
|
32
|
+
window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme: effectiveTheme } }))
|
|
33
|
+
if (this.syncSandboxValue) this.syncSandboxFrames(effectiveTheme)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
// For non-auto themes, only update if no stored preference
|
|
37
|
+
if (!Persistence.storage.get(this.storageKeyValue)) {
|
|
38
|
+
this.setTheme(e.matches ? "dark" : "light")
|
|
39
|
+
}
|
|
9
40
|
}
|
|
10
41
|
|
|
11
|
-
|
|
42
|
+
this._mediaQuery.addEventListener("change", this.boundHandleSystemThemeChange)
|
|
12
43
|
|
|
13
|
-
|
|
14
|
-
|
|
44
|
+
if (this.syncSandboxValue) {
|
|
45
|
+
this.sandboxFrameTargets.forEach((frame) => {
|
|
46
|
+
frame.addEventListener("load", this.handleSandboxLoad)
|
|
47
|
+
})
|
|
15
48
|
}
|
|
16
49
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this._handleSystemThemeChange = (e) => {
|
|
28
|
-
const currentTheme = document.documentElement.getAttribute("data-theme")
|
|
29
|
-
// If theme is "auto", don't change the attribute - let CSS media query handle it
|
|
30
|
-
// Only dispatch event for sync purposes
|
|
31
|
-
if (currentTheme === "auto") {
|
|
32
|
-
const effectiveTheme = e.matches ? "dark" : "light"
|
|
33
|
-
window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme: effectiveTheme } }))
|
|
34
|
-
if (this.syncSandboxValue) this.syncSandboxFrames(effectiveTheme)
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
// For non-auto themes, only update if no stored preference
|
|
38
|
-
if (!Persistence.storage.get(this.storageKeyValue)) {
|
|
39
|
-
this.setTheme(e.matches ? "dark" : "light")
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
this._mediaQuery.addEventListener("change", this._handleSystemThemeChange)
|
|
44
|
-
|
|
45
|
-
if (this.syncSandboxValue) {
|
|
46
|
-
this.sandboxFrameTargets.forEach((frame) => {
|
|
47
|
-
frame.addEventListener("load", this.handleSandboxLoad)
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Only set theme if there's no explicit theme
|
|
52
|
-
// If "auto", don't change the attribute - CSS media query handles it
|
|
53
|
-
if (!existingTheme) {
|
|
54
|
-
this.setTheme(this.detectInitialTheme())
|
|
55
|
-
} else if (existingTheme === "auto") {
|
|
56
|
-
// For "auto", just dispatch event and sync sandboxes without changing attribute
|
|
57
|
-
const effectiveTheme = this._mediaQuery.matches ? "dark" : "light"
|
|
58
|
-
window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme: effectiveTheme } }))
|
|
59
|
-
if (this.syncSandboxValue) this.syncSandboxFrames(effectiveTheme)
|
|
60
|
-
}
|
|
50
|
+
// Only set theme if there's no explicit theme
|
|
51
|
+
// If "auto", don't change the attribute - CSS media query handles it
|
|
52
|
+
if (!existingTheme) {
|
|
53
|
+
this.setTheme(this.detectInitialTheme())
|
|
54
|
+
} else if (existingTheme === "auto") {
|
|
55
|
+
// For "auto", just dispatch event and sync sandboxes without changing attribute
|
|
56
|
+
const effectiveTheme = this._mediaQuery.matches ? "dark" : "light"
|
|
57
|
+
window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme: effectiveTheme } }))
|
|
58
|
+
if (this.syncSandboxValue) this.syncSandboxFrames(effectiveTheme)
|
|
61
59
|
}
|
|
60
|
+
}
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
teardown() {
|
|
63
|
+
if (window.__hakumiThemeActive === this.element.id) delete window.__hakumiThemeActive
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (this.syncSandboxValue) {
|
|
71
|
-
this.sandboxFrameTargets.forEach((frame) => {
|
|
72
|
-
frame.removeEventListener("load", this.handleSandboxLoad)
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
registerApi() {
|
|
78
|
-
const api = {
|
|
79
|
-
get: () => this.getTheme(),
|
|
80
|
-
set: (theme) => this.setTheme(theme),
|
|
81
|
-
toggle: () => this.toggle(),
|
|
82
|
-
clearStored: () => Persistence.storage.remove(this.storageKeyValue),
|
|
83
|
-
detect: () => this.detectInitialTheme(),
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
this.element.hakumiComponent = {
|
|
87
|
-
name: "theme",
|
|
88
|
-
version: 1,
|
|
89
|
-
singleton: true,
|
|
90
|
-
api,
|
|
91
|
-
apply: (params = {}) => {
|
|
92
|
-
if (params.theme) this.setTheme(params.theme)
|
|
93
|
-
},
|
|
94
|
-
}
|
|
65
|
+
if (this._mediaQuery && this.boundHandleSystemThemeChange) {
|
|
66
|
+
this._mediaQuery.removeEventListener("change", this.boundHandleSystemThemeChange)
|
|
95
67
|
}
|
|
96
68
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Persistence.storage.set(this.storageKeyValue, next)
|
|
69
|
+
if (this.syncSandboxValue) {
|
|
70
|
+
this.sandboxFrameTargets.forEach((frame) => {
|
|
71
|
+
frame.removeEventListener("load", this.handleSandboxLoad)
|
|
72
|
+
})
|
|
102
73
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
registerApi() {
|
|
77
|
+
const api = {
|
|
78
|
+
get: () => this.getTheme(),
|
|
79
|
+
set: (theme) => this.setTheme(theme),
|
|
80
|
+
toggle: () => this.toggle(),
|
|
81
|
+
clearStored: () => Persistence.storage.remove(this.storageKeyValue),
|
|
82
|
+
detect: () => this.detectInitialTheme(),
|
|
112
83
|
}
|
|
113
84
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
85
|
+
this.element.hakumiComponent = {
|
|
86
|
+
name: "theme",
|
|
87
|
+
version: 1,
|
|
88
|
+
singleton: true,
|
|
89
|
+
api,
|
|
90
|
+
apply: (params = {}) => {
|
|
91
|
+
if (params.theme) this.setTheme(params.theme)
|
|
92
|
+
},
|
|
119
93
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
toggle() {
|
|
97
|
+
const current = this.getTheme()
|
|
98
|
+
const next = current === "dark" ? "light" : "dark"
|
|
99
|
+
this.setTheme(next)
|
|
100
|
+
Persistence.storage.set(this.storageKeyValue, next)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getTheme() {
|
|
104
|
+
return document.documentElement.getAttribute("data-theme") || this.defaultValue
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
setTheme(theme) {
|
|
108
|
+
document.documentElement.setAttribute("data-theme", theme)
|
|
109
|
+
window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme } }))
|
|
110
|
+
if (this.syncSandboxValue) this.syncSandboxFrames(theme)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
detectInitialTheme() {
|
|
114
|
+
const savedTheme = Persistence.storage.get(this.storageKeyValue)
|
|
115
|
+
if (savedTheme) return savedTheme
|
|
116
|
+
if (this._mediaQuery?.matches) return "dark"
|
|
117
|
+
return this.defaultValue
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
syncSandboxFrames(theme) {
|
|
121
|
+
this._currentTheme = theme
|
|
122
|
+
this.sandboxFrameTargets.forEach((frame) => this.postThemeToFrame(frame, theme))
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
handleSandboxLoad = (event) => {
|
|
126
|
+
const frame = event.currentTarget
|
|
127
|
+
const theme = this._currentTheme || this.getTheme()
|
|
128
|
+
this.postThemeToFrame(frame, theme)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
postThemeToFrame(frame, theme) {
|
|
132
|
+
if (frame?.contentWindow) {
|
|
133
|
+
frame.contentWindow.postMessage({ theme }, "*")
|
|
136
134
|
}
|
|
135
|
+
}
|
|
137
136
|
}
|
|
@@ -27,6 +27,7 @@ export default class extends RegistryController {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
setup() {
|
|
30
|
+
this.#syncHiddenInputs()
|
|
30
31
|
this.#updateCounts()
|
|
31
32
|
this.#syncSelectAll("source")
|
|
32
33
|
this.#syncSelectAll("target")
|
|
@@ -71,6 +72,7 @@ export default class extends RegistryController {
|
|
|
71
72
|
if (item.parentElement !== destination) {
|
|
72
73
|
destination.appendChild(item)
|
|
73
74
|
}
|
|
75
|
+
this.#syncHiddenInput(item, targetSet.has(key))
|
|
74
76
|
this.#setItemSelected(item, false)
|
|
75
77
|
})
|
|
76
78
|
|
|
@@ -176,6 +178,7 @@ export default class extends RegistryController {
|
|
|
176
178
|
items.forEach((item) => {
|
|
177
179
|
this.#setItemSelected(item, false)
|
|
178
180
|
this.#listContainer(to).appendChild(item)
|
|
181
|
+
this.#syncHiddenInput(item, to === "target")
|
|
179
182
|
})
|
|
180
183
|
|
|
181
184
|
this.targetKeysValue = this.getTargetKeys()
|
|
@@ -211,7 +214,8 @@ export default class extends RegistryController {
|
|
|
211
214
|
}
|
|
212
215
|
|
|
213
216
|
#isItemDisabled(item) {
|
|
214
|
-
|
|
217
|
+
const checkbox = item.querySelector(".hakumi-checkbox-input")
|
|
218
|
+
return item.dataset.disabled === "true" || checkbox?.disabled
|
|
215
219
|
}
|
|
216
220
|
|
|
217
221
|
#isItemSelected(item) {
|
|
@@ -279,6 +283,18 @@ export default class extends RegistryController {
|
|
|
279
283
|
return Array.from(container.querySelectorAll(".hakumi-transfer-list-item"))
|
|
280
284
|
}
|
|
281
285
|
|
|
286
|
+
#syncHiddenInputs() {
|
|
287
|
+
this.#listItems("source").forEach((item) => this.#syncHiddenInput(item, false))
|
|
288
|
+
this.#listItems("target").forEach((item) => this.#syncHiddenInput(item, true))
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#syncHiddenInput(item, enabled) {
|
|
292
|
+
const hiddenInput = item.querySelector("[data-hakumi--transfer-hidden-input='true']")
|
|
293
|
+
if (!hiddenInput) return
|
|
294
|
+
|
|
295
|
+
hiddenInput.disabled = !enabled
|
|
296
|
+
}
|
|
297
|
+
|
|
282
298
|
#listKeys(list) {
|
|
283
299
|
return this.#listItems(list).map((item) => item.dataset.key)
|
|
284
300
|
}
|