Skip to content

Commit

Permalink
Refactor shadow DOM creation, closes #72
Browse files Browse the repository at this point in the history
  • Loading branch information
Vatroslav Vrbanic committed Jun 20, 2022
1 parent c75bf91 commit e56fc3e
Show file tree
Hide file tree
Showing 14 changed files with 1,348 additions and 948 deletions.
157 changes: 95 additions & 62 deletions src/components/AmbientLight.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ AmbientLight cannot be used to cast shadows as it doesn't have a direction. Posi
const self = get_current_component()
const c_name = get_comp_name(self)
const shadow_root: Writable<{ element: HTMLDivElement }> = getContext("shadow_root")
let shadow_root_el: HTMLDivElement
$: shadow_root_el = $shadow_root.element
const verbose: boolean = verbose_mode()
export let log_all: boolean = false
Expand All @@ -74,6 +70,16 @@ AmbientLight cannot be used to cast shadows as it doesn't have a direction. Posi
/** The (three) instance that was shared to this component as it's 'parent'. */
let our_parent: Object3D = undefined
/** Shadow DOM element generated by our parent scene / root scene. Used as fallback if this component has no non-`Scene` component as parent. */
let scene_shadow_dom_el: SvelthreeShadowDOMElement = getContext("scene_shadow_dom_el")
/** Shadow DOM element generated by our parent component (_not `Canvas`_) shared with this component (child) via context.
Fallback is `scene_shadow_dom_el` or `shadow_root_el` in case of the `Scene` component. */
let our_parent_shadow_dom_el: SvelthreeShadowDOMElement = undefined
/** Shadow DOM element generated by this component. Shared by this component (as parent) to it's children via context as "parent_shadow_dom_el". */
let shadow_dom_el: SvelthreeShadowDOMElement = undefined
/** Returns the `light` instance created by the component & allows providing (_injection_) of (_already created / premade_) `THREE.AmbientLight` instances. */
export let light: AmbientLight = undefined
let light_uuid: string = undefined
Expand Down Expand Up @@ -103,11 +109,28 @@ AmbientLight cannot be used to cast shadows as it doesn't have a direction. Posi
// Determining 'parent' on initialization if 'light' instance was provided ('create' is false).
if (!create) {
// get the instance that was shared to us as our 'parent'.
// get the instance that was shared to us as our 'parent' or use fallback.
our_parent = getContext("parent") || scene
// get the shadow DOM element that was shared to us by our parent component or use fallback.
our_parent_shadow_dom_el = getContext("parent_shadow_dom_el") || scene_shadow_dom_el
// share created object (three) instance to all children (slots) as 'parent'.
setContext("parent", light)
// share our own shadow_dom_el as parent_shadow_dom_el
if (shadow_dom_el) {
// recreate shadow_dom_el
remove_shadow_dom_el()
create_shadow_dom_el()
} else {
create_shadow_dom_el()
}
if (shadow_dom_el) {
setContext("parent_shadow_dom_el", shadow_dom_el)
} else {
console.error(`SVELTHREE > ${c_name} > 'shadow_dom_el' not available!`, shadow_dom_el)
}
}
// GENERATOR REMARK: 'reactive_re_creation_logic' not implemented for 'AmbientLight'!
Expand All @@ -129,16 +152,79 @@ AmbientLight cannot be used to cast shadows as it doesn't have a direction. Posi
}
// Determining 'parent' if 'light' instance has to be created first / was not provided on initialization ('create' is true).
$: if (light && create && !our_parent) set_parent()
$: if (light && create && scene && !our_parent) set_parent()
function set_parent() {
// get the instance that was shared to us as our 'parent'.
// get the instance that was shared to us as our 'parent' or use fallback.
our_parent = getContext("parent") || scene
// share created object (three) instance to all children (slots) as 'parent'.
setContext("parent", light)
}
$: if (light && create && !our_parent_shadow_dom_el) set_parent_shadow_dom_el()
function set_parent_shadow_dom_el() {
our_parent_shadow_dom_el = getContext("parent_shadow_dom_el") || scene_shadow_dom_el
// share our own shadow_dom_el as parent_shadow_dom_el
if (shadow_dom_el) {
// recreate shadow_dom_el
remove_shadow_dom_el()
create_shadow_dom_el()
} else {
create_shadow_dom_el()
}
if (shadow_dom_el) {
setContext("parent_shadow_dom_el", shadow_dom_el)
} else {
console.error(`SVELTHREE > ${c_name} : 'shadow_dom_el' not available!`, shadow_dom_el)
}
}
function remove_shadow_dom_el() {
shadow_dom_el.parentNode.removeChild(shadow_dom_el)
}
function create_shadow_dom_el(): void {
shadow_dom_el = document.createElement("div")
shadow_dom_el.dataset.kind = `${c_name}`
if (our_parent_shadow_dom_el) {
our_parent_shadow_dom_el.appendChild(shadow_dom_el)
//console.log(`SVELTHREE > ${c_name} > create_shadow_dom_el > shadow dom appended!:`, our_parent_shadow_dom_el)
} else {
console.error(
`SVELTHREE > ${c_name} > create_shadow_dom_el > could'nt append shadow dom, no 'our_parent_shadow_dom_el'!`,
our_parent_shadow_dom_el
)
}
}
// accessability -> shadow dom focusable
export let tabindex: number = undefined
$: if (shadow_dom_el && tabindex !== undefined) {
shadow_dom_el.tabIndex = tabindex
}
// accessability -> shadow dom wai-aria
export let aria: Partial<ARIAMixin> = undefined
$: if (shadow_dom_el && aria !== undefined) {
for (const key in aria) {
if (key === "ariaLabel") {
// add specified `ariaLabel` as text to generated shadow DOM `<div>` element (for better reader support / indexing (?))
// TODO RECONSIDER needs to be tested more, may be obsolete (?).
shadow_dom_el.innerText += `${aria[key]}`
}
shadow_dom_el[key] = aria[key]
}
}
// this statement is being triggered on creation / recreation
$: if (light && ((light_uuid && light_uuid !== light.uuid) || light.parent !== our_parent)) add_instance_to()
Expand Down Expand Up @@ -191,68 +277,15 @@ AmbientLight cannot be used to cast shadows as it doesn't have a direction. Posi
}
}
// accessability -> shadow dom element
/** Shadow DOM element created by the component, needed for accessability features, event propagation etc. */
export let shadow_dom_el: SvelthreeShadowDOMElement = undefined
$: if (shadow_root_el && light && !shadow_dom_el) create_shadow_dom_target()
async function create_shadow_dom_target() {
if (browser) {
// DUCKTAPE `getContext()` wrong order fix, see [#72](https://github.com/vatro/svelthree/issues/72)
await tick()
shadow_dom_el = document.createElement("div")
shadow_dom_el.dataset.kind = "AmbientLight"
if (name) shadow_dom_el.dataset.name = name
const parent_shadow_dom_target = our_parent?.userData.svelthreeComponent.shadow_dom_el
const shadow_target: SvelthreeShadowDOMElement = parent_shadow_dom_target || shadow_root_el
if (shadow_target) {
shadow_target.appendChild(shadow_dom_el)
} else {
console.error(
"SVELTHREE > AmbientLight > create_shadow_dom_target > Wasn't able to append shadow DOM element, no 'shadow_target'!",
{ shadow_target },
{ parent_shadow_dom_target },
{ our_parent }
)
}
}
}
// accessability -> shadow dom focusable
export let tabindex: number = undefined
$: if (shadow_dom_el && tabindex !== undefined) {
shadow_dom_el.tabIndex = tabindex
}
// accessability -> shadow dom wai-aria
export let aria: Partial<ARIAMixin> = undefined
$: if (shadow_dom_el && aria !== undefined) {
for (const key in aria) {
if (key === "ariaLabel") {
// add specified `ariaLabel` as text to generated shadow DOM `<div>` element (for better reader support / indexing (?))
// TODO RECONSIDER needs to be tested more, may be obsolete (?).
shadow_dom_el.innerText += `${aria[key]}`
}
shadow_dom_el[key] = aria[key]
}
}
/** Override object's `.matrixAutoUpdate` set (*on initialzation*) by scene's `.matrixAutoUpdate` (*default is `true`*). Also: `mau` can be changed on-the-fly.*/
export let mau: boolean = undefined
$: if (light) light.matrixAutoUpdate = scene.matrixAutoUpdate
$: if (light && mau !== undefined) light.matrixAutoUpdate = mau
export let name: string = undefined
$: if (light && name) light.name = name
$: if (shadow_dom_el && name) shadow_dom_el.dataset.name = name
const w_sh = PropUtils.getShortHandAttrWarnings(`SVELTHREE > ${c_name} >`)
Expand Down
Loading

0 comments on commit e56fc3e

Please sign in to comment.