@radioactive-labs/plutonium 0.2.1 → 0.3.0
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/package.json +6 -2
- package/src/css/plutonium.css +3 -0
- package/src/dist/css/plutonium.css +9 -1
- package/src/dist/js/plutonium.js +23273 -9599
- package/src/dist/js/plutonium.js.map +4 -4
- package/src/dist/js/plutonium.min.js +159 -49
- package/src/dist/js/plutonium.min.js.map +4 -4
- package/src/js/controllers/attachment_input_controller.js +241 -0
- package/src/js/controllers/attachment_preview_container_controller.js +15 -0
- package/src/js/controllers/attachment_preview_controller.js +63 -0
- package/src/js/controllers/color_mode_controller.js +0 -1
- package/src/js/controllers/easymde_controller.js +0 -1
- package/src/js/controllers/flatpickr_controller.js +0 -1
- package/src/js/controllers/form_controller.js +0 -1
- package/src/js/controllers/frame_navigator_controller.js +16 -12
- package/src/js/controllers/intl_tel_input_controller.js +0 -1
- package/src/js/controllers/register_controllers.js +12 -30
- package/src/js/controllers/resource_collapse_controller.js +0 -1
- package/src/js/controllers/resource_dismiss_controller.js +0 -1
- package/src/js/controllers/resource_drop_down_controller.js +161 -9
- package/src/js/controllers/{header_controller.js → resource_header_controller.js} +1 -0
- package/src/js/controllers/resource_tab_list_controller.js +64 -0
- package/src/js/controllers/select_navigator.js +16 -0
- package/src/js/controllers/slim_select_controller.js +0 -1
- package/src/js/support/dom_element.js +78 -0
- package/src/js/support/mime_icon.js +127 -0
- package/src/js/controllers/has_many_panel_controller.js +0 -8
- package/src/js/controllers/interactive_action_form_controller.js +0 -13
- package/src/js/controllers/nav_grid_menu_controller.js +0 -8
- package/src/js/controllers/nav_grid_menu_item_controller.js +0 -8
- package/src/js/controllers/nav_user_controller.js +0 -8
- package/src/js/controllers/nav_user_link_controller.js +0 -8
- package/src/js/controllers/nav_user_section_controller.js +0 -8
- package/src/js/controllers/resource_layout_controller.js +0 -8
- package/src/js/controllers/sidebar_controller.js +0 -8
- package/src/js/controllers/sidebar_menu_controller.js +0 -8
- package/src/js/controllers/sidebar_menu_item_controller.js +0 -8
- package/src/js/controllers/table_controller.js +0 -8
- package/src/js/controllers/table_search_input_controller.js +0 -8
- package/src/js/controllers/table_toolbar_controller.js +0 -8
- package/src/js/controllers/toolbar_controller.js +0 -8
|
@@ -1,31 +1,183 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { createPopper } from '@popperjs/core'
|
|
4
3
|
|
|
5
4
|
// Connects to data-controller="resource-drop-down"
|
|
6
5
|
export default class extends Controller {
|
|
7
6
|
static targets = ["trigger", "menu"]
|
|
8
7
|
|
|
9
8
|
connect() {
|
|
10
|
-
|
|
9
|
+
this.visible = false
|
|
10
|
+
this.initialized = false
|
|
11
|
+
|
|
12
|
+
// Default options matching Flowbite's defaults
|
|
13
|
+
this.options = {
|
|
14
|
+
placement: 'bottom',
|
|
15
|
+
triggerType: 'click',
|
|
16
|
+
offsetSkidding: 0,
|
|
17
|
+
offsetDistance: 10,
|
|
18
|
+
delay: 300,
|
|
19
|
+
ignoreClickOutsideClass: false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.init()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
init() {
|
|
26
|
+
if (this.triggerTarget && this.menuTarget && !this.initialized) {
|
|
27
|
+
// Initialize popper instance
|
|
28
|
+
this.popperInstance = createPopper(this.triggerTarget, this.menuTarget, {
|
|
29
|
+
placement: this.options.placement,
|
|
30
|
+
modifiers: [
|
|
31
|
+
{
|
|
32
|
+
name: 'offset',
|
|
33
|
+
options: {
|
|
34
|
+
offset: [this.options.offsetSkidding, this.options.offsetDistance],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
})
|
|
11
39
|
|
|
12
|
-
|
|
13
|
-
|
|
40
|
+
this.setupEventListeners()
|
|
41
|
+
this.initialized = true
|
|
42
|
+
}
|
|
14
43
|
}
|
|
15
44
|
|
|
16
45
|
disconnect() {
|
|
17
|
-
this.
|
|
46
|
+
if (this.initialized) {
|
|
47
|
+
// Remove click event listeners
|
|
48
|
+
if (this.options.triggerType === 'click') {
|
|
49
|
+
this.triggerTarget.removeEventListener('click', this.clickHandler)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Remove hover event listeners
|
|
53
|
+
if (this.options.triggerType === 'hover') {
|
|
54
|
+
this.triggerTarget.removeEventListener('mouseenter', this.hoverShowTriggerHandler)
|
|
55
|
+
this.menuTarget.removeEventListener('mouseenter', this.hoverShowMenuHandler)
|
|
56
|
+
this.triggerTarget.removeEventListener('mouseleave', this.hoverHideHandler)
|
|
57
|
+
this.menuTarget.removeEventListener('mouseleave', this.hoverHideHandler)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Remove click outside listener
|
|
61
|
+
this.removeClickOutsideListener()
|
|
62
|
+
|
|
63
|
+
// Destroy popper instance
|
|
64
|
+
this.popperInstance.destroy()
|
|
65
|
+
this.initialized = false
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setupEventListeners() {
|
|
70
|
+
// Bind handlers to preserve context
|
|
71
|
+
this.clickHandler = this.toggle.bind(this)
|
|
72
|
+
this.hoverShowTriggerHandler = (ev) => {
|
|
73
|
+
if (ev.type === 'click') {
|
|
74
|
+
this.toggle()
|
|
75
|
+
} else {
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
this.show()
|
|
78
|
+
}, this.options.delay)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this.hoverShowMenuHandler = () => {
|
|
82
|
+
this.show()
|
|
83
|
+
}
|
|
84
|
+
this.hoverHideHandler = () => {
|
|
85
|
+
setTimeout(() => {
|
|
86
|
+
if (!this.menuTarget.matches(':hover')) {
|
|
87
|
+
this.hide()
|
|
88
|
+
}
|
|
89
|
+
}, this.options.delay)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Set up click or hover events based on trigger type
|
|
93
|
+
if (this.options.triggerType === 'click') {
|
|
94
|
+
this.triggerTarget.addEventListener('click', this.clickHandler)
|
|
95
|
+
} else if (this.options.triggerType === 'hover') {
|
|
96
|
+
this.triggerTarget.addEventListener('mouseenter', this.hoverShowTriggerHandler)
|
|
97
|
+
this.menuTarget.addEventListener('mouseenter', this.hoverShowMenuHandler)
|
|
98
|
+
this.triggerTarget.addEventListener('mouseleave', this.hoverHideHandler)
|
|
99
|
+
this.menuTarget.addEventListener('mouseleave', this.hoverHideHandler)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
setupClickOutsideListener() {
|
|
104
|
+
this.clickOutsideHandler = (ev) => {
|
|
105
|
+
const clickedEl = ev.target
|
|
106
|
+
const ignoreClickOutsideClass = this.options.ignoreClickOutsideClass
|
|
107
|
+
|
|
108
|
+
let isIgnored = false
|
|
109
|
+
if (ignoreClickOutsideClass) {
|
|
110
|
+
const ignoredEls = document.querySelectorAll(`.${ignoreClickOutsideClass}`)
|
|
111
|
+
ignoredEls.forEach((el) => {
|
|
112
|
+
if (el.contains(clickedEl)) {
|
|
113
|
+
isIgnored = true
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (
|
|
120
|
+
clickedEl !== this.menuTarget &&
|
|
121
|
+
!this.menuTarget.contains(clickedEl) &&
|
|
122
|
+
!this.triggerTarget.contains(clickedEl) &&
|
|
123
|
+
!isIgnored &&
|
|
124
|
+
this.visible
|
|
125
|
+
) {
|
|
126
|
+
this.hide()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
document.body.addEventListener('click', this.clickOutsideHandler, true)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
removeClickOutsideListener() {
|
|
134
|
+
if (this.clickOutsideHandler) {
|
|
135
|
+
document.body.removeEventListener('click', this.clickOutsideHandler, true)
|
|
136
|
+
}
|
|
18
137
|
}
|
|
19
138
|
|
|
20
139
|
toggle() {
|
|
21
|
-
this.
|
|
140
|
+
if (this.visible) {
|
|
141
|
+
this.hide()
|
|
142
|
+
} else {
|
|
143
|
+
this.show()
|
|
144
|
+
}
|
|
22
145
|
}
|
|
23
146
|
|
|
24
147
|
show() {
|
|
25
|
-
this.
|
|
148
|
+
this.menuTarget.classList.remove('hidden')
|
|
149
|
+
this.menuTarget.classList.add('block')
|
|
150
|
+
this.menuTarget.removeAttribute('aria-hidden')
|
|
151
|
+
|
|
152
|
+
// Enable popper event listeners
|
|
153
|
+
this.popperInstance.setOptions((options) => ({
|
|
154
|
+
...options,
|
|
155
|
+
modifiers: [
|
|
156
|
+
...options.modifiers,
|
|
157
|
+
{ name: 'eventListeners', enabled: true },
|
|
158
|
+
],
|
|
159
|
+
}))
|
|
160
|
+
|
|
161
|
+
this.setupClickOutsideListener()
|
|
162
|
+
this.popperInstance.update()
|
|
163
|
+
this.visible = true
|
|
26
164
|
}
|
|
27
165
|
|
|
28
166
|
hide() {
|
|
29
|
-
this.
|
|
167
|
+
this.menuTarget.classList.remove('block')
|
|
168
|
+
this.menuTarget.classList.add('hidden')
|
|
169
|
+
this.menuTarget.setAttribute('aria-hidden', 'true')
|
|
170
|
+
|
|
171
|
+
// Disable popper event listeners
|
|
172
|
+
this.popperInstance.setOptions((options) => ({
|
|
173
|
+
...options,
|
|
174
|
+
modifiers: [
|
|
175
|
+
...options.modifiers,
|
|
176
|
+
{ name: 'eventListeners', enabled: false },
|
|
177
|
+
],
|
|
178
|
+
}))
|
|
179
|
+
|
|
180
|
+
this.removeClickOutsideListener()
|
|
181
|
+
this.visible = false
|
|
30
182
|
}
|
|
31
183
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="resource-tab-list"
|
|
4
|
+
export default class extends Controller {
|
|
5
|
+
static targets = ["btn", "tab"]
|
|
6
|
+
static values = {
|
|
7
|
+
defaultTab: String,
|
|
8
|
+
activeClasses: String,
|
|
9
|
+
inActiveClasses: String
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
connect() {
|
|
13
|
+
this.activeClasses = this.hasActiveClassesValue ? this.activeClassesValue.split(" ") : []
|
|
14
|
+
this.inActiveClasses = this.hasInActiveClassesValue ? this.inActiveClassesValue.split(" ") : []
|
|
15
|
+
|
|
16
|
+
this.#selectInternal(this.defaultTabValue || this.btnTargets[0].id)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
select(event) {
|
|
20
|
+
this.#selectInternal(event.currentTarget.id)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#selectInternal(id) {
|
|
24
|
+
const selectedBtn = this.btnTargets.find(element => element.id === id)
|
|
25
|
+
if (!selectedBtn) {
|
|
26
|
+
console.error(`Tab Button with id "${id}" not found`)
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const selectedTab = this.tabTargets.find(element => element.id === selectedBtn.dataset.target)
|
|
31
|
+
if (!selectedTab) {
|
|
32
|
+
console.error(`Tab Panel with id "${selectedBtn.dataset.target}" not found`)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Update tab visibility and ARIA states
|
|
37
|
+
this.tabTargets.forEach(tab => {
|
|
38
|
+
tab.hidden = true
|
|
39
|
+
tab.setAttribute('aria-hidden', 'true')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Update button states and classes
|
|
43
|
+
this.btnTargets.forEach(btn => {
|
|
44
|
+
btn.setAttribute('aria-selected', 'false')
|
|
45
|
+
btn.setAttribute('tabindex', '-1')
|
|
46
|
+
btn.classList.remove(...this.activeClasses)
|
|
47
|
+
btn.classList.add(...this.inActiveClasses)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// Activate selected tab and button
|
|
51
|
+
selectedBtn.setAttribute('aria-selected', 'true')
|
|
52
|
+
selectedBtn.setAttribute('tabindex', '0')
|
|
53
|
+
selectedBtn.classList.remove(...this.inActiveClasses)
|
|
54
|
+
selectedBtn.classList.add(...this.activeClasses)
|
|
55
|
+
|
|
56
|
+
selectedTab.hidden = false
|
|
57
|
+
selectedTab.setAttribute('aria-hidden', 'false')
|
|
58
|
+
|
|
59
|
+
// Focus management
|
|
60
|
+
if (selectedBtn !== document.activeElement) {
|
|
61
|
+
selectedBtn.focus()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="select-navigator"
|
|
4
|
+
export default class extends Controller {
|
|
5
|
+
static targets = ["select"]
|
|
6
|
+
|
|
7
|
+
navigate(_) {
|
|
8
|
+
const url = this.selectTarget.value
|
|
9
|
+
const anchor = document.createElement('a')
|
|
10
|
+
anchor.href = url
|
|
11
|
+
|
|
12
|
+
this.element.appendChild(anchor)
|
|
13
|
+
anchor.click()
|
|
14
|
+
anchor.remove()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -3,7 +3,6 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
3
3
|
// Connects to data-controller="slim-select"
|
|
4
4
|
export default class extends Controller {
|
|
5
5
|
connect() {
|
|
6
|
-
console.log(`slim-select connected: ${this.element}`)
|
|
7
6
|
this.slimSelect = new SlimSelect({
|
|
8
7
|
select: this.element
|
|
9
8
|
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
2
|
+
|
|
3
|
+
export default class {
|
|
4
|
+
static fromTemplate(template) {
|
|
5
|
+
if (DOMPurify.isSupported) {
|
|
6
|
+
return DOMPurify.sanitize(template, { USE_PROFILES: { html: true, svg: true }, RETURN_DOM: true }).children[0]
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
const html = new DOMParser().parseFromString(template, 'text/html').body.children[0]
|
|
10
|
+
return santizeHTML(html)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
// https://vanillajstoolkit.com/helpers/cleanhtml/
|
|
17
|
+
|
|
18
|
+
/*!
|
|
19
|
+
* Sanitize an HTML node
|
|
20
|
+
*/
|
|
21
|
+
function santizeHTML(html) {
|
|
22
|
+
// Sanitize it
|
|
23
|
+
removeScripts(html)
|
|
24
|
+
cleanAttributes(html)
|
|
25
|
+
|
|
26
|
+
return html
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Remove <script> elements
|
|
31
|
+
* @param {Node} html The HTML
|
|
32
|
+
*/
|
|
33
|
+
function removeScripts(html) {
|
|
34
|
+
let scripts = html.querySelectorAll('script')
|
|
35
|
+
for (let script of scripts) {
|
|
36
|
+
script.remove()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if the attribute is potentially dangerous
|
|
42
|
+
* @param {String} name The attribute name
|
|
43
|
+
* @param {String} value The attribute value
|
|
44
|
+
* @return {Boolean} If true, the attribute is potentially dangerous
|
|
45
|
+
*/
|
|
46
|
+
function isPossiblyDangerous(name, value) {
|
|
47
|
+
let val = value.replace(/\s+/g, '').toLowerCase()
|
|
48
|
+
if (['src', 'href', 'xlink:href'].includes(name)) {
|
|
49
|
+
if (val.includes('javascript:') || val.includes('data:')) return true
|
|
50
|
+
}
|
|
51
|
+
if (name.startsWith('on')) return true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Remove potentially dangerous attributes from an element
|
|
56
|
+
* @param {Node} elem The element
|
|
57
|
+
*/
|
|
58
|
+
function removePossiblyDangerousAttributes(elem) {
|
|
59
|
+
// Loop through each attribute
|
|
60
|
+
// If it's dangerous, remove it
|
|
61
|
+
let atts = elem.attributes
|
|
62
|
+
for (let { name, value } of atts) {
|
|
63
|
+
if (!isPossiblyDangerous(name, value)) continue
|
|
64
|
+
elem.removeAttribute(name)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Remove dangerous stuff from the HTML document's nodes
|
|
70
|
+
* @param {Node} html The HTML document
|
|
71
|
+
*/
|
|
72
|
+
function cleanAttributes(html) {
|
|
73
|
+
let nodes = html.children
|
|
74
|
+
for (let node of nodes) {
|
|
75
|
+
removePossiblyDangerousAttributes(node)
|
|
76
|
+
cleanAttributes(node)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import DomElement from "./dom_element"
|
|
2
|
+
|
|
3
|
+
function iconImage() {
|
|
4
|
+
return DomElement.fromTemplate(`
|
|
5
|
+
<svg aria-hidden="true" focusable="false" width="25" height="25" viewBox="0 0 25 25">
|
|
6
|
+
<g fill="#686DE0" fillRule="evenodd">
|
|
7
|
+
<path d="M5 7v10h15V7H5zm0-1h15a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z" fillRule="nonzero" />
|
|
8
|
+
<path d="M6.35 17.172l4.994-5.026a.5.5 0 0 1 .707 0l2.16 2.16 3.505-3.505a.5.5 0 0 1 .707 0l2.336 2.31-.707.72-1.983-1.97-3.505 3.505a.5.5 0 0 1-.707 0l-2.16-2.159-3.938 3.939-1.409.026z" fillRule="nonzero" />
|
|
9
|
+
<circle cx="7.5" cy="9.5" r="1.5" />
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
|
12
|
+
`)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function iconAudio() {
|
|
16
|
+
return DomElement.fromTemplate(`
|
|
17
|
+
<svg aria-hidden="true" focusable="false" className="uppy-c-icon" width="25" height="25" viewBox="0 0 25 25">
|
|
18
|
+
<path d="M9.5 18.64c0 1.14-1.145 2-2.5 2s-2.5-.86-2.5-2c0-1.14 1.145-2 2.5-2 .557 0 1.079.145 1.5.396V7.25a.5.5 0 0 1 .379-.485l9-2.25A.5.5 0 0 1 18.5 5v11.64c0 1.14-1.145 2-2.5 2s-2.5-.86-2.5-2c0-1.14 1.145-2 2.5-2 .557 0 1.079.145 1.5.396V8.67l-8 2v7.97zm8-11v-2l-8 2v2l8-2zM7 19.64c.855 0 1.5-.484 1.5-1s-.645-1-1.5-1-1.5.484-1.5 1 .645 1 1.5 1zm9-2c.855 0 1.5-.484 1.5-1s-.645-1-1.5-1-1.5.484-1.5 1 .645 1 1.5 1z" fill="#049BCF" fillRule="nonzero" />
|
|
19
|
+
</svg>
|
|
20
|
+
`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function iconVideo() {
|
|
24
|
+
return DomElement.fromTemplate(`
|
|
25
|
+
<svg aria-hidden="true" focusable="false" className="uppy-c-icon" width="25" height="25" viewBox="0 0 25 25">
|
|
26
|
+
<path d="M16 11.834l4.486-2.691A1 1 0 0 1 22 10v6a1 1 0 0 1-1.514.857L16 14.167V17a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v2.834zM15 9H5v8h10V9zm1 4l5 3v-6l-5 3z" fill="#19AF67" fillRule="nonzero" />
|
|
27
|
+
</svg>
|
|
28
|
+
`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function iconPDF() {
|
|
32
|
+
return DomElement.fromTemplate(`
|
|
33
|
+
<svg aria-hidden="true" focusable="false" className="uppy-c-icon" width="25" height="25" viewBox="0 0 25 25">
|
|
34
|
+
<path d="M9.766 8.295c-.691-1.843-.539-3.401.747-3.726 1.643-.414 2.505.938 2.39 3.299-.039.79-.194 1.662-.537 3.148.324.49.66.967 1.055 1.51.17.231.382.488.629.757 1.866-.128 3.653.114 4.918.655 1.487.635 2.192 1.685 1.614 2.84-.566 1.133-1.839 1.084-3.416.249-1.141-.604-2.457-1.634-3.51-2.707a13.467 13.467 0 0 0-2.238.426c-1.392 4.051-4.534 6.453-5.707 4.572-.986-1.58 1.38-4.206 4.914-5.375.097-.322.185-.656.264-1.001.08-.353.306-1.31.407-1.737-.678-1.059-1.2-2.031-1.53-2.91zm2.098 4.87c-.033.144-.068.287-.104.427l.033-.01-.012.038a14.065 14.065 0 0 1 1.02-.197l-.032-.033.052-.004a7.902 7.902 0 0 1-.208-.271c-.197-.27-.38-.526-.555-.775l-.006.028-.002-.003c-.076.323-.148.632-.186.8zm5.77 2.978c1.143.605 1.832.632 2.054.187.26-.519-.087-1.034-1.113-1.473-.911-.39-2.175-.608-3.55-.608.845.766 1.787 1.459 2.609 1.894zM6.559 18.789c.14.223.693.16 1.425-.413.827-.648 1.61-1.747 2.208-3.206-2.563 1.064-4.102 2.867-3.633 3.62zm5.345-10.97c.088-1.793-.351-2.48-1.146-2.28-.473.119-.564 1.05-.056 2.405.213.566.52 1.188.908 1.859.18-.858.268-1.453.294-1.984z" fill="#E2514A" fillRule="nonzero" />
|
|
35
|
+
</svg>
|
|
36
|
+
`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function iconArchive() {
|
|
40
|
+
return DomElement.fromTemplate(`
|
|
41
|
+
<svg aria-hidden="true" focusable="false" width="25" height="25" viewBox="0 0 25 25">
|
|
42
|
+
<path d="M10.45 2.05h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5V2.55a.5.5 0 0 1 .5-.5zm2.05 1.024h1.05a.5.5 0 0 1 .5.5V3.6a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5v-.001zM10.45 0h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5V.5a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-2.05 3.074h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-2.05 1.024h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm-2.05 1.025h1.05a.5.5 0 0 1 .5.5v.025a.5.5 0 0 1-.5.5h-1.05a.5.5 0 0 1-.5-.5v-.025a.5.5 0 0 1 .5-.5zm2.05 1.025h1.05a.5.5 0 0 1 .5.5v.024a.5.5 0 0 1-.5.5H12.5a.5.5 0 0 1-.5-.5v-.024a.5.5 0 0 1 .5-.5zm-1.656 3.074l-.82 5.946c.52.302 1.174.458 1.976.458.803 0 1.455-.156 1.975-.458l-.82-5.946h-2.311zm0-1.025h2.312c.512 0 .946.378 1.015.885l.82 5.946c.056.412-.142.817-.501 1.026-.686.398-1.515.597-2.49.597-.974 0-1.804-.199-2.49-.597a1.025 1.025 0 0 1-.5-1.026l.819-5.946c.07-.507.503-.885 1.015-.885zm.545 6.6a.5.5 0 0 1-.397-.561l.143-.999a.5.5 0 0 1 .495-.429h.74a.5.5 0 0 1 .495.43l.143.998a.5.5 0 0 1-.397.561c-.404.08-.819.08-1.222 0z" fill="#00C469" fillRule="nonzero" />
|
|
43
|
+
</svg>
|
|
44
|
+
`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function iconFile() {
|
|
48
|
+
return DomElement.fromTemplate(`
|
|
49
|
+
<svg aria-hidden="true" focusable="false" className="uppy-c-icon" width="25" height="25" viewBox="0 0 25 25">
|
|
50
|
+
<g fill="#A7AFB7" fillRule="nonzero">
|
|
51
|
+
<path d="M5.5 22a.5.5 0 0 1-.5-.5v-18a.5.5 0 0 1 .5-.5h10.719a.5.5 0 0 1 .367.16l3.281 3.556a.5.5 0 0 1 .133.339V21.5a.5.5 0 0 1-.5.5h-14zm.5-1h13V7.25L16 4H6v17z" />
|
|
52
|
+
<path d="M15 4v3a1 1 0 0 0 1 1h3V7h-3V4h-1z" />
|
|
53
|
+
</g>
|
|
54
|
+
</svg>
|
|
55
|
+
`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function iconText() {
|
|
59
|
+
return DomElement.fromTemplate(`
|
|
60
|
+
<svg aria-hidden="true" focusable="false" className="uppy-c-icon" width="25" height="25" viewBox="0 0 25 25">
|
|
61
|
+
<path d="M4.5 7h13a.5.5 0 1 1 0 1h-13a.5.5 0 0 1 0-1zm0 3h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 3h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 3h10a.5.5 0 1 1 0 1h-10a.5.5 0 1 1 0-1z" fill="#5A5E69" fillRule="nonzero" />
|
|
62
|
+
</svg>
|
|
63
|
+
`)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default function getIconByMime(fileType) {
|
|
67
|
+
const defaultChoice = {
|
|
68
|
+
color: '#838999',
|
|
69
|
+
icon: iconFile(),
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!fileType) return defaultChoice
|
|
73
|
+
|
|
74
|
+
const fileTypeGeneral = fileType.split('/')[0]
|
|
75
|
+
const fileTypeSpecific = fileType.split('/')[1]
|
|
76
|
+
|
|
77
|
+
// Text
|
|
78
|
+
if (fileTypeGeneral === 'text') {
|
|
79
|
+
return {
|
|
80
|
+
color: '#5a5e69',
|
|
81
|
+
icon: iconText(),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Image
|
|
86
|
+
if (fileTypeGeneral === 'image') {
|
|
87
|
+
return {
|
|
88
|
+
color: '#686de0',
|
|
89
|
+
icon: iconImage(),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Audio
|
|
94
|
+
if (fileTypeGeneral === 'audio') {
|
|
95
|
+
return {
|
|
96
|
+
color: '#068dbb',
|
|
97
|
+
icon: iconAudio(),
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Video
|
|
102
|
+
if (fileTypeGeneral === 'video') {
|
|
103
|
+
return {
|
|
104
|
+
color: '#19af67',
|
|
105
|
+
icon: iconVideo(),
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// PDF
|
|
110
|
+
if (fileTypeGeneral === 'application' && fileTypeSpecific === 'pdf') {
|
|
111
|
+
return {
|
|
112
|
+
color: '#e25149',
|
|
113
|
+
icon: iconPDF(),
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Archive
|
|
118
|
+
const archiveTypes = ['zip', 'x-7z-compressed', 'x-rar-compressed', 'x-tar', 'x-gzip', 'x-apple-diskimage']
|
|
119
|
+
if (fileTypeGeneral === 'application' && archiveTypes.indexOf(fileTypeSpecific) !== -1) {
|
|
120
|
+
return {
|
|
121
|
+
color: '#00C469',
|
|
122
|
+
icon: iconArchive(),
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return defaultChoice
|
|
127
|
+
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import debounce from "lodash.debounce";
|
|
3
|
-
|
|
4
|
-
// Connects to data-controller="interactive-action-form"
|
|
5
|
-
export default class extends Controller {
|
|
6
|
-
connect() {
|
|
7
|
-
console.log(`interactive-action-form connected: ${this.element}`)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
submit() {
|
|
11
|
-
this.element.requestSubmit()
|
|
12
|
-
}
|
|
13
|
-
}
|