Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F7112992
component-debugger.stimulus.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
component-debugger.stimulus.ts
View Options
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/consistent-type-assertions */
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
import
{
Controller
}
from
"stimulus"
;
export
default
class
ComponentDebugger
extends
Controller
{
declare
sizeSelectTarget
:
HTMLSelectElement
;
declare
gutterTarget
:
HTMLDivElement
;
declare
checkboxTarget
:
HTMLInputElement
;
declare
checkboxTargets
:
HTMLInputElement
[];
declare
previewTarget
:
HTMLDivElement
;
declare
componentBlockTargets
:
HTMLDivElement
[];
static
targets
=
[
"gutter"
,
"componentBlock"
,
"checkbox"
,
"preview"
,
"sizeSelect"
,
];
id
:
string
;
main_form
:
HTMLFormElement
;
origin_x
:
number
;
origin_width
:
number
;
connect
()
{
const
main_form
=
document
.
querySelector
(
"#component-debugger"
)
?
.
closest
(
"form"
);
if
(
!
main_form
)
{
throw
new
Error
(
"No main form"
);
}
this
.
main_form
=
main_form
;
document
.
documentElement
.
addEventListener
(
"ts-rebuilt"
,
()
=>
{
this
.
main_form
.
requestSubmit
();
});
this
.
main_form
.
addEventListener
(
"turbo:submit-end"
,
()
=>
{
// this clears the values of file inputs, so they don't get unecessarily
// re-uploaded on future submissions - the file is alreade there on the server
this
.
main_form
.
querySelectorAll
(
"input[type=file]"
)
.
forEach
((
input
:
HTMLInputElement
)
=>
(
input
.
value
=
""
));
});
window
.
addEventListener
(
"load"
,
()
=>
{
this
.
update_width_display
();
});
document
.
addEventListener
(
"turbo:render"
,
()
=>
{
// not calling that to see if that improves performance
// console.log("UWD because of render event");
// this.update_width_display();
});
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const
gutter
=
this
.
gutterTarget
;
gutter
.
addEventListener
(
"mousedown"
,
(
e
)
=>
{
this
.
origin_x
=
e
.
clientX
;
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const
resizable
=
this
.
targets
.
find
(
"preview"
)
as
HTMLSpanElement
;
this
.
origin_width
=
resizable
.
getBoundingClientRect
().
width
;
const
handler
=
(
e
:
MouseEvent
)
=>
this
.
resizeHandler
(
e
);
document
.
addEventListener
(
"mousemove"
,
handler
);
const
remove_move_listener
=
()
=>
{
document
.
removeEventListener
(
"mousemove"
,
handler
);
document
.
removeEventListener
(
"mouseup"
,
remove_move_listener
);
document
.
dispatchEvent
(
new
Event
(
"component-debugger--resize-done"
)
);
};
document
.
addEventListener
(
"mouseup"
,
remove_move_listener
);
e
.
preventDefault
();
});
}
update_width_display
()
{
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
console
.
log
(
"uwd"
);
const
preview
=
this
.
targets
.
find
(
"preview"
)
as
HTMLSpanElement
;
const
component_width
=
preview
.
offsetWidth
;
this
.
sizeSelectTarget
.
querySelectorAll
(
"option"
)
.
forEach
((
e
)
=>
e
.
removeAttribute
(
"selected"
));
let
option
:
HTMLOptionElement
|
null
=
this
.
sizeSelectTarget
.
querySelector
(
"option.dynamic"
);
if
(
!
option
)
{
option
=
document
.
createElement
(
"option"
);
option
.
classList
.
add
(
"dynamic"
);
option
.
setAttribute
(
"selected"
,
""
);
this
.
sizeSelectTarget
.
insertBefore
(
option
,
this
.
sizeSelectTarget
.
childNodes
[
0
]
!
);
}
option
.
setAttribute
(
"selected"
,
""
);
option
.
innerHTML
=
`
${
component_width
}
px`
;
option
.
value
=
String
(
component_width
);
this
.
sizeSelectTarget
.
value
=
String
(
component_width
);
}
resizeHandler
(
e
:
MouseEvent
)
{
const
width_offset
=
this
.
origin_x
-
e
.
clientX
;
const
new_width
=
Math
.
max
(
this
.
origin_width
+
width_offset
,
1
);
this
.
setPreviewWidth
(
new_width
);
this
.
update_width_display
();
document
.
dispatchEvent
(
new
Event
(
"component-debugger--resize"
));
}
setPreviewWidth
(
width
:
number
)
{
document
.
getElementById
(
"component-debugger"
)
?
.
style
.
setProperty
(
"--resizable-column-width"
,
width
.
toString
()
+
"px"
);
this
.
update_width_display
();
}
handleWidthDropdown
()
{
const
value
=
this
.
sizeSelectTarget
.
value
;
this
.
setPreviewWidth
(
parseInt
(
value
));
}
handleBlockHover
(
e
:
MouseEvent
)
{
const
index
=
parseInt
(
(
e
.
target
as
HTMLDivElement
)
.
closest
(
".jdd-editor__component-block"
)
?
.
getAttribute
(
"data-component-index"
)
||
"0"
);
this
.
element
.
querySelector
(
`.component-number-
${
index
}
`
)
?
.
classList
.
add
(
"highlighted"
);
}
handleBlockUnhover
(
e
:
MouseEvent
)
{
const
index
=
parseInt
(
(
e
.
target
as
HTMLDivElement
)
.
closest
(
".jdd-editor__component-block"
)
?
.
getAttribute
(
"data-component-index"
)
||
""
);
this
.
element
.
querySelectorAll
(
`.component-number-
${
index
}
.highlighted`
)
.
forEach
((
e
)
=>
e
.
classList
.
remove
(
"highlighted"
));
}
componentBlockTargetConnected
(
block_element
:
HTMLDivElement
)
{
const
index
=
parseInt
(
block_element
.
getAttribute
(
"data-component-index"
)
||
"0"
);
block_element
.
addEventListener
(
"focusin"
,
()
=>
{
this
.
scrollToComponentPreview
(
index
);
});
const
summary
=
block_element
.
querySelector
(
"summary"
);
if
(
summary
)
{
summary
.
addEventListener
(
"mouseenter"
,
this
.
handleBlockHover
.
bind
(
this
)
);
summary
.
addEventListener
(
"mouseleave"
,
this
.
handleBlockUnhover
.
bind
(
this
)
);
}
}
previewTargetConnected
(
preview_element
:
HTMLDivElement
)
{
preview_element
.
addEventListener
(
"click"
,
({
target
})
=>
{
if
(
!
(
target
instanceof
HTMLElement
))
{
return
;
}
const
closest
=
target
.
closest
(
".jdd-component"
);
if
(
!
closest
)
{
return
;
}
const
index
=
parseInt
(
String
(
Array
.
from
(
closest
.
classList
)
.
find
((
c
)
=>
c
.
startsWith
(
"component-number-"
))
?
.
replace
(
"component-number-"
,
""
)
)
);
if
(
isNaN
(
index
))
{
return
;
}
this
.
focusComponentBlock
(
index
);
});
}
focusComponentBlock
(
index
:
number
)
{
const
block
=
this
.
componentBlockTargets
[
index
];
if
(
!
block
)
{
return
;
}
this
.
checkboxTargets
[
index
]
!
.
checked
=
true
;
this
.
checkboxTargets
[
index
]
!
.
dispatchEvent
(
new
Event
(
"change"
));
// to help with refreshing markdown editor
block
.
scrollIntoView
({
behavior
:
"smooth"
});
(
block
.
querySelector
(
".component-preview-parameters input"
)
as
HTMLInputElement
)
?
.
focus
();
}
getIndex
(
block_element
:
HTMLDivElement
)
{
const
index
=
parseInt
(
String
(
block_element
.
getAttribute
(
"data-component-index"
))
);
return
index
;
}
labelClicked
(
element
:
MouseEvent
)
{
const
block_element
=
(
element
.
target
as
HTMLDivElement
).
closest
(
`[data-component-debugger-target="componentBlock"]`
)
as
HTMLDivElement
;
const
index
=
this
.
getIndex
(
block_element
);
if
(
!
this
.
checkboxTargets
?
.[
index
]
?
.
checked
)
{
this
.
scrollToComponentPreview
(
index
);
}
}
getPreviewElementForComponentIndex
(
index
:
number
)
{
const
element
=
this
.
element
.
querySelector
(
`.component-number-
${
index
}
`
)
as
HTMLDialogElement
;
return
element
;
}
scrollToComponentPreview
(
index
:
number
)
{
const
element
=
this
.
getPreviewElementForComponentIndex
(
index
);
if
(
!
element
)
{
return
;
}
const
preview_element
=
this
.
element
.
querySelector
(
".component-preview"
);
if
(
!
preview_element
)
{
throw
new
Error
(
"Missing preview element!"
);
}
if
(
element
.
clientHeight
>
preview_element
.
clientHeight
)
{
preview_element
.
scrollTop
=
element
.
offsetTop
-
44
;
}
else
{
preview_element
.
scrollTop
=
element
.
offsetTop
-
(
preview_element
.
clientHeight
-
element
.
clientHeight
)
/
2
-
44
;
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Fri, Jul 4, 08:31 (5 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
789339
Default Alt Text
component-debugger.stimulus.ts (7 KB)
Attached To
Mode
rJDDE jdd-editor
Attached
Detach File
Event Timeline
Log In to Comment