Skip to content

Instantly share code, notes, and snippets.

@hexagon6
Created April 12, 2024 10:19
Show Gist options
  • Save hexagon6/c80a850741ef1f7ecdb9e36c5bb5839f to your computer and use it in GitHub Desktop.
Save hexagon6/c80a850741ef1f7ecdb9e36c5bb5839f to your computer and use it in GitHub Desktop.
visualize tables web component build test
// generated during release, do not modify
const PUBLIC_VERSION = '5'
if (typeof window !== 'undefined')
// @ts-ignore
(window.__svelte ||= { v: new Set() }).v.add(PUBLIC_VERSION)
const DERIVED = 1 << 1
const EFFECT = 1 << 2
const RENDER_EFFECT = 1 << 3
const BLOCK_EFFECT = 1 << 4
const BRANCH_EFFECT = 1 << 5
const ROOT_EFFECT = 1 << 6
const UNOWNED = 1 << 7
const CLEAN = 1 << 8
const DIRTY = 1 << 9
const MAYBE_DIRTY = 1 << 10
const INERT = 1 << 11
const DESTROYED = 1 << 12
const IS_ELSEIF = 1 << 13
const EFFECT_RAN = 1 << 14
const STATE_SYMBOL = Symbol('$state')
// Store the references to globals in case someone tries to monkey patch these, causing the below
// to de-opt (this occurs often when using popular extensions).
var is_array = Array.isArray
var array_from = Array.from
var object_keys = Object.keys
var is_frozen = Object.isFrozen
var define_property = Object.defineProperty
var get_descriptor = Object.getOwnPropertyDescriptor
var get_descriptors = Object.getOwnPropertyDescriptors
var object_prototype = Object.prototype
var array_prototype = Array.prototype
var get_prototype_of = Object.getPrototypeOf
/** @type {import('#client').Equals} */
function equals$1(value) {
return value === this.v
}
/**
* @param {unknown} a
* @param {unknown} b
* @returns {boolean}
*/
function safe_not_equal(a, b) {
// eslint-disable-next-line eqeqeq
return a != a
? // eslint-disable-next-line eqeqeq
b == b
: a !== b ||
(a !== null && typeof a === 'object') ||
typeof a === 'function'
}
/** @type {import('#client').Equals} */
function safe_equals(value) {
return !safe_not_equal(value, this.v)
}
const EACH_ITEM_REACTIVE = 1
const EACH_INDEX_REACTIVE = 1 << 1
const EACH_KEYED = 1 << 2
/** See EachBlock interface metadata.is_controlled for an explanation what this is */
const EACH_IS_CONTROLLED = 1 << 3
const EACH_IS_STRICT_EQUALS = 1 << 6
const PROPS_IS_IMMUTABLE = 1
const PROPS_IS_RUNES = 1 << 1
const PROPS_IS_UPDATED = 1 << 2
const PROPS_IS_LAZY_INITIAL = 1 << 3
const TEMPLATE_FRAGMENT = 1
const TEMPLATE_USE_IMPORT_NODE = 1 << 1
const HYDRATION_START = '['
const HYDRATION_END = ']'
const HYDRATION_END_ELSE = `${HYDRATION_END}!` // used to indicate that an `{:else}...` block was rendered
const UNINITIALIZED = Symbol()
/** List of Element events that will be delegated and are passive */
const PassiveDelegatedEvents = ['touchstart', 'touchmove', 'touchend']
/**
* @template V
* @param {V} value
* @returns {import('#client').Source<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
function source(value) {
/** @type {import('#client').Source<V>} */
const source = {
f: 0, // TODO ideally we could skip this altogether, but it causes type errors
reactions: null,
equals: equals$1,
v: value,
version: 0,
}
return source
}
/**
* @template V
* @param {V} initial_value
* @returns {import('#client').Source<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
function mutable_source(initial_value) {
const s = source(initial_value)
s.equals = safe_equals
// bind the signal to the component context, in case we need to
// track updates to trigger beforeUpdate/afterUpdate callbacks
if (current_component_context) {
;(current_component_context.d ??= []).push(s)
}
return s
}
/**
* @template V
* @param {import('#client').Source<V>} signal
* @param {V} value
* @returns {V}
*/
function set$2(signal, value) {
var initialized = signal.v !== UNINITIALIZED
if (
!current_untracking &&
initialized &&
current_reaction !== null &&
is_runes() &&
(current_reaction.f & DERIVED) !== 0
) {
throw new Error('ERR_SVELTE_UNSAFE_MUTATION' + '')
}
if (!signal.equals(value)) {
signal.v = value
// Increment write version so that unowned signals can properly track dirtiness
signal.version++
// If the current signal is running for the first time, it won't have any
// reactions as we only allocate and assign the reactions after the signal
// has fully executed. So in the case of ensuring it registers the reaction
// properly for itself, we need to ensure the current effect actually gets
// scheduled. i.e:
//
// $effect(() => x++)
//
// We additionally want to skip this logic when initialising store sources
if (
is_runes() &&
initialized &&
current_effect !== null &&
(current_effect.f & CLEAN) !== 0 &&
(current_effect.f & BRANCH_EFFECT) === 0
) {
if (
current_dependencies !== null &&
current_dependencies.includes(signal)
) {
set_signal_status(current_effect, DIRTY)
schedule_effect(current_effect)
} else {
if (current_untracked_writes === null) {
set_current_untracked_writes([signal])
} else {
current_untracked_writes.push(signal)
}
}
}
mark_reactions(signal, DIRTY, true)
}
return value
}
/** @param {string} html */
function create_fragment_from_html(html) {
var elem = document.createElement('template')
elem.innerHTML = html
return elem.content
}
/**
* @param {import('#client').Dom} current
*/
function remove$1(current) {
if (is_array(current)) {
for (var i = 0; i < current.length; i++) {
var node = current[i]
if (node.isConnected) {
node.remove()
}
}
} else if (current.isConnected) {
current.remove()
}
}
/**
* @param {import("#client").Effect} effect
* @param {import("#client").Reaction} parent_effect
*/
function push_effect(effect, parent_effect) {
var parent_last = parent_effect.last
if (parent_last === null) {
parent_effect.last = parent_effect.first = effect
} else {
parent_last.next = effect
effect.prev = parent_last
parent_effect.last = effect
}
}
/**
* @param {number} type
* @param {(() => void | (() => void))} fn
* @param {boolean} sync
* @returns {import('#client').Effect}
*/
function create_effect(type, fn, sync) {
var is_root = (type & ROOT_EFFECT) !== 0
/** @type {import('#client').Effect} */
var effect = {
ctx: current_component_context,
deps: null,
dom: null,
f: type | DIRTY,
first: null,
fn,
last: null,
next: null,
parent: is_root ? null : current_effect,
prev: null,
teardown: null,
transitions: null,
}
if (current_reaction !== null && !is_root) {
push_effect(effect, current_reaction)
}
if (sync) {
var previously_flushing_effect = is_flushing_effect
try {
set_is_flushing_effect(true)
execute_effect(effect)
effect.f |= EFFECT_RAN
} finally {
set_is_flushing_effect(previously_flushing_effect)
}
} else {
schedule_effect(effect)
}
return effect
}
/**
* Internal representation of `$effect.active()`
* @returns {boolean}
*/
function effect_active() {
return current_effect
? (current_effect.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0
: false
}
/**
* Internal representation of `$effect.root(...)`
* @param {() => void | (() => void)} fn
* @returns {() => void}
*/
function effect_root(fn) {
const effect = create_effect(ROOT_EFFECT, fn, true)
return () => {
destroy_effect(effect)
}
}
/**
* @param {() => void | (() => void)} fn
* @returns {import('#client').Effect}
*/
function effect(fn) {
return create_effect(EFFECT, fn, false)
}
/**
* @param {() => void | (() => void)} fn
* @returns {import('#client').Effect}
*/
function render_effect(fn) {
return create_effect(RENDER_EFFECT, fn, true)
}
/** @param {(() => void)} fn */
function block(fn) {
return create_effect(RENDER_EFFECT | BLOCK_EFFECT, fn, true)
}
/** @param {(() => void)} fn */
function branch(fn) {
return create_effect(RENDER_EFFECT | BRANCH_EFFECT, fn, true)
}
/**
* @param {import('#client').Effect} effect
* @returns {void}
*/
function destroy_effect(effect) {
var dom = effect.dom
if (dom !== null) {
remove$1(dom)
}
destroy_effect_children(effect)
remove_reactions(effect, 0)
set_signal_status(effect, DESTROYED)
if (effect.transitions) {
for (const transition of effect.transitions) {
transition.stop()
}
}
effect.teardown?.call(null)
var parent = effect.parent
// If the parent doesn't have any children, then skip this work altogether
if (
parent !== null &&
(effect.f & BRANCH_EFFECT) !== 0 &&
parent.first !== null
) {
var previous = effect.prev
var next = effect.next
if (previous !== null) {
if (next !== null) {
previous.next = next
next.prev = previous
} else {
previous.next = null
parent.last = previous
}
} else if (next !== null) {
next.prev = null
parent.first = next
} else {
parent.first = null
parent.last = null
}
}
// `first` and `child` are nulled out in destroy_effect_children
effect.next =
effect.prev =
effect.teardown =
effect.ctx =
effect.dom =
effect.deps =
effect.parent =
// @ts-expect-error
effect.fn =
null
}
/**
* When a block effect is removed, we don't immediately destroy it or yank it
* out of the DOM, because it might have transitions. Instead, we 'pause' it.
* It stays around (in memory, and in the DOM) until outro transitions have
* completed, and if the state change is reversed then we _resume_ it.
* A paused effect does not update, and the DOM subtree becomes inert.
* @param {import('#client').Effect} effect
* @param {() => void} [callback]
*/
function pause_effect(effect, callback) {
/** @type {import('#client').TransitionManager[]} */
var transitions = []
pause_children(effect, transitions, true)
run_out_transitions(transitions, () => {
destroy_effect(effect)
if (callback) callback()
})
}
/**
* @param {import('#client').TransitionManager[]} transitions
* @param {() => void} fn
*/
function run_out_transitions(transitions, fn) {
var remaining = transitions.length
if (remaining > 0) {
var check = () => --remaining || fn()
for (var transition of transitions) {
transition.out(check)
}
} else {
fn()
}
}
/**
* @param {import('#client').Effect} effect
* @param {import('#client').TransitionManager[]} transitions
* @param {boolean} local
*/
function pause_children(effect, transitions, local) {
if ((effect.f & INERT) !== 0) return
effect.f ^= INERT
if (effect.transitions !== null) {
for (const transition of effect.transitions) {
if (transition.is_global || local) {
transitions.push(transition)
}
}
}
var child = effect.first
while (child !== null) {
var sibling = child.next
var transparent =
(child.f & IS_ELSEIF) !== 0 || (child.f & BRANCH_EFFECT) !== 0
// TODO we don't need to call pause_children recursively with a linked list in place
// it's slightly more involved though as we have to account for `transparent` changing
// through the tree.
pause_children(child, transitions, transparent ? local : false)
child = sibling
}
}
/**
* The opposite of `pause_effect`. We call this if (for example)
* `x` becomes falsy then truthy: `{#if x}...{/if}`
* @param {import('#client').Effect} effect
*/
function resume_effect(effect) {
resume_children(effect, true)
}
/**
* @param {import('#client').Effect} effect
* @param {boolean} local
*/
function resume_children(effect, local) {
if ((effect.f & INERT) === 0) return
effect.f ^= INERT
// If a dependency of this effect changed while it was paused,
// apply the change now
if (check_dirtiness(effect)) {
execute_effect(effect)
}
var child = effect.first
while (child !== null) {
var sibling = child.next
var transparent =
(child.f & IS_ELSEIF) !== 0 || (child.f & BRANCH_EFFECT) !== 0
// TODO we don't need to call resume_children recursively with a linked list in place
// it's slightly more involved though as we have to account for `transparent` changing
// through the tree.
resume_children(child, transparent ? local : false)
child = sibling
}
if (effect.transitions !== null) {
for (const transition of effect.transitions) {
if (transition.is_global || local) {
transition.in()
}
}
}
}
let updating_derived = false
/**
* @template V
* @param {() => V} fn
* @returns {import('#client').Derived<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
function derived(fn) {
let flags = DERIVED | DIRTY
if (current_effect === null) flags |= UNOWNED
/** @type {import('#client').Derived<V>} */
const signal = {
deps: null,
deriveds: null,
equals: equals$1,
f: flags,
first: null,
fn,
last: null,
reactions: null,
v: /** @type {V} */ (null),
version: 0,
}
if (current_reaction !== null && (current_reaction.f & DERIVED) !== 0) {
var current_derived = /** @type {import('#client').Derived<V>} */ (
current_reaction
)
if (current_derived.deriveds === null) {
current_derived.deriveds = [signal]
} else {
current_derived.deriveds.push(signal)
}
}
return signal
}
/**
* @param {import('./types.js').Derived} signal
* @returns {void}
*/
function destroy_derived_children(signal) {
destroy_effect_children(signal)
var deriveds = signal.deriveds
if (deriveds !== null) {
signal.deriveds = null
for (var i = 0; i < deriveds.length; i += 1) {
destroy_derived(deriveds[i])
}
}
}
/**
* @param {import('#client').Derived} derived
* @param {boolean} force_schedule
* @returns {void}
*/
function update_derived(derived, force_schedule) {
var previous_updating_derived = updating_derived
updating_derived = true
destroy_derived_children(derived)
var value = execute_reaction_fn(derived)
updating_derived = previous_updating_derived
var status =
(current_skip_reaction || (derived.f & UNOWNED) !== 0) &&
derived.deps !== null
? MAYBE_DIRTY
: CLEAN
set_signal_status(derived, status)
if (!derived.equals(value)) {
derived.v = value
mark_reactions(derived, DIRTY, force_schedule)
}
}
/**
* @param {import('#client').Derived} signal
* @returns {void}
*/
function destroy_derived(signal) {
destroy_derived_children(signal)
remove_reactions(signal, 0)
set_signal_status(signal, DESTROYED)
// TODO we need to ensure we remove the derived from any parent derives
signal.first =
signal.last =
signal.deps =
signal.reactions =
// @ts-expect-error `signal.fn` cannot be `null` while the signal is alive
signal.fn =
null
}
/**
* @template T
* @param {T} value
* @param {boolean} [immutable]
* @param {Set<Function> | null} [owners]
* @returns {import('#client').ProxyStateObject<T> | T}
*/
function proxy(value, immutable = true, owners) {
if (typeof value === 'object' && value != null && !is_frozen(value)) {
// If we have an existing proxy, return it...
if (STATE_SYMBOL in value) {
const metadata = /** @type {import('#client').ProxyMetadata<T>} */ (
value[STATE_SYMBOL]
)
// ...unless the proxy belonged to a different object, because
// someone copied the state symbol using `Reflect.ownKeys(...)`
if (metadata.t === value || metadata.p === value) {
return metadata.p
}
}
const prototype = get_prototype_of(value)
if (prototype === object_prototype || prototype === array_prototype) {
const proxy = new Proxy(value, state_proxy_handler)
define_property(value, STATE_SYMBOL, {
value: /** @type {import('#client').ProxyMetadata} */ ({
s: new Map(),
v: source(0),
a: is_array(value),
i: immutable,
p: proxy,
t: value,
}),
writable: true,
enumerable: false,
})
return proxy
}
}
return value
}
/**
* @param {import('#client').Source<number>} signal
* @param {1 | -1} [d]
*/
function update_version(signal, d = 1) {
set$2(signal, signal.v + d)
}
/** @type {ProxyHandler<import('#client').ProxyStateObject<any>>} */
const state_proxy_handler = {
defineProperty(target, prop, descriptor) {
if (descriptor.value) {
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
const s = metadata.s.get(prop)
if (s !== undefined)
set$2(s, proxy(descriptor.value, metadata.i, metadata.o))
}
return Reflect.defineProperty(target, prop, descriptor)
},
deleteProperty(target, prop) {
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
const s = metadata.s.get(prop)
const is_array = metadata.a
const boolean = delete target[prop]
// If we have mutated an array directly, and the deletion
// was successful we will also need to update the length
// before updating the field or the version. This is to
// ensure any effects observing length can execute before
// effects that listen to the fields – otherwise they will
// operate an an index that no longer exists.
if (is_array && boolean) {
const ls = metadata.s.get('length')
const length = target.length - 1
if (ls !== undefined && ls.v !== length) {
set$2(ls, length)
}
}
if (s !== undefined) set$2(s, UNINITIALIZED)
if (boolean) {
update_version(metadata.v)
}
return boolean
},
get(target, prop, receiver) {
if (prop === STATE_SYMBOL) {
return Reflect.get(target, STATE_SYMBOL)
}
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
let s = metadata.s.get(prop)
// if we're reading a property in a reactive context, create a source,
// but only if it's an own property and not a prototype property
if (
s === undefined &&
(effect_active() || updating_derived) &&
(!(prop in target) || get_descriptor(target, prop)?.writable)
) {
s = (metadata.i ? source : mutable_source)(
proxy(target[prop], metadata.i, metadata.o),
)
metadata.s.set(prop, s)
}
if (s !== undefined) {
const value = get$2(s)
return value === UNINITIALIZED ? undefined : value
}
return Reflect.get(target, prop, receiver)
},
getOwnPropertyDescriptor(target, prop) {
const descriptor = Reflect.getOwnPropertyDescriptor(target, prop)
if (descriptor && 'value' in descriptor) {
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
const s = metadata.s.get(prop)
if (s) {
descriptor.value = get$2(s)
}
}
return descriptor
},
has(target, prop) {
if (prop === STATE_SYMBOL) {
return true
}
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
const has = Reflect.has(target, prop)
let s = metadata.s.get(prop)
if (
s !== undefined ||
(effect_active() && (!has || get_descriptor(target, prop)?.writable))
) {
if (s === undefined) {
s = (metadata.i ? source : mutable_source)(
has ? proxy(target[prop], metadata.i, metadata.o) : UNINITIALIZED,
)
metadata.s.set(prop, s)
}
const value = get$2(s)
if (value === UNINITIALIZED) {
return false
}
}
return has
},
set(target, prop, value, receiver) {
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
let s = metadata.s.get(prop)
// If we haven't yet created a source for this property, we need to ensure
// we do so otherwise if we read it later, then the write won't be tracked and
// the heuristics of effects will be different vs if we had read the proxied
// object property before writing to that property.
if (s === undefined && effect_active()) {
// the read creates a signal
untrack(() => receiver[prop])
s = metadata.s.get(prop)
}
if (s !== undefined) {
set$2(s, proxy(value, metadata.i, metadata.o))
}
const is_array = metadata.a
const not_has = !(prop in target)
// variable.length = value -> clear all signals with index >= value
if (is_array && prop === 'length') {
for (let i = value; i < target.length; i += 1) {
const s = metadata.s.get(i + '')
if (s !== undefined) set$2(s, UNINITIALIZED)
}
}
// Set the new value before updating any signals so that any listeners get the new value
// @ts-ignore
target[prop] = value
if (not_has) {
// If we have mutated an array directly, we might need to
// signal that length has also changed. Do it before updating metadata
// to ensure that iterating over the array as a result of a metadata update
// will not cause the length to be out of sync.
if (is_array) {
const ls = metadata.s.get('length')
const length = target.length
if (ls !== undefined && ls.v !== length) {
set$2(ls, length)
}
}
update_version(metadata.v)
}
return true
},
ownKeys(target) {
/** @type {import('#client').ProxyMetadata} */
const metadata = target[STATE_SYMBOL]
get$2(metadata.v)
return Reflect.ownKeys(target)
},
}
/**
* Synchronously run any queued tasks.
*/
function flush_tasks() {}
const FLUSH_MICROTASK = 0
const FLUSH_SYNC = 1
// Used for controlling the flush of effects.
let current_scheduler_mode = FLUSH_MICROTASK
// Used for handling scheduling
let is_micro_task_queued = false
let is_flushing_effect = false
/** @param {boolean} value */
function set_is_flushing_effect(value) {
is_flushing_effect = value
}
// Handle effect queues
/** @type {import('./types.js').Effect[]} */
let current_queued_root_effects = []
let flush_count = 0
// Handle signal reactivity tree dependencies and reactions
/** @type {null | import('./types.js').Reaction} */
let current_reaction = null
/** @type {null | import('./types.js').Effect} */
let current_effect = null
/** @type {null | import('./types.js').Value[]} */
let current_dependencies = null
let current_dependencies_index = 0
/**
* Tracks writes that the effect it's executed in doesn't listen to yet,
* so that the dependency can be added to the effect later on if it then reads it
* @type {null | import('./types.js').Source[]}
*/
let current_untracked_writes = null
/** @param {null | import('./types.js').Source[]} value */
function set_current_untracked_writes(value) {
current_untracked_writes = value
}
/** If `true`, `get`ting the signal should not register it as a dependency */
let current_untracking = false
// If we are working with a get() chain that has no active container,
// to prevent memory leaks, we skip adding the reaction.
let current_skip_reaction = false
// Handling runtime component context
/** @type {import('./types.js').ComponentContext | null} */
let current_component_context = null
/** @returns {boolean} */
function is_runes() {
return current_component_context !== null && current_component_context.r
}
/**
* Determines whether a derived or effect is dirty.
* If it is MAYBE_DIRTY, will set the status to CLEAN
* @param {import('./types.js').Reaction} reaction
* @returns {boolean}
*/
function check_dirtiness(reaction) {
var flags = reaction.f
if ((flags & DIRTY) !== 0) {
return true
}
if ((flags & MAYBE_DIRTY) !== 0) {
var dependencies = reaction.deps
var is_unowned = (flags & UNOWNED) !== 0
if (dependencies !== null) {
var length = dependencies.length
for (var i = 0; i < length; i++) {
var dependency = dependencies[i]
if (
check_dirtiness(/** @type {import('#client').Derived} */ (dependency))
) {
update_derived(
/** @type {import('#client').Derived} **/ (dependency),
true,
)
// `signal` might now be dirty, as a result of calling `update_derived`
if ((reaction.f & DIRTY) !== 0) {
return true
}
}
// If we're working with an unowned derived signal, then we need to check
// if our dependency write version is higher. If it is then we can assume
// that state has changed to a newer version and thus this unowned signal
// is also dirty.
var version = dependency.version
if (
is_unowned &&
version > /** @type {import('#client').Derived} */ (reaction).version
) {
/** @type {import('#client').Derived} */ ;(reaction).version = version
return true
}
}
}
// Unowned signals are always maybe dirty, as we instead check their dependency versions.
if (!is_unowned) {
set_signal_status(reaction, CLEAN)
}
}
return false
}
/**
* @template V
* @param {import('./types.js').Reaction} signal
* @returns {V}
*/
function execute_reaction_fn(signal) {
const previous_dependencies = current_dependencies
const previous_dependencies_index = current_dependencies_index
const previous_untracked_writes = current_untracked_writes
const previous_reaction = current_reaction
const previous_skip_reaction = current_skip_reaction
const previous_untracking = current_untracking
current_dependencies = /** @type {null | import('./types.js').Value[]} */ (
null
)
current_dependencies_index = 0
current_untracked_writes = null
current_reaction = signal
current_skip_reaction = !is_flushing_effect && (signal.f & UNOWNED) !== 0
current_untracking = false
try {
let res = signal.fn()
let dependencies = /** @type {import('./types.js').Value<unknown>[]} **/ (
signal.deps
)
if (current_dependencies !== null) {
let i
if (dependencies !== null) {
const deps_length = dependencies.length
// Include any dependencies up until the current_dependencies_index.
const full_current_dependencies =
current_dependencies_index === 0
? current_dependencies
: dependencies
.slice(0, current_dependencies_index)
.concat(current_dependencies)
const current_dep_length = full_current_dependencies.length
// If we have more than 16 elements in the array then use a Set for faster performance
// TODO: evaluate if we should always just use a Set or not here?
const full_current_dependencies_set =
current_dep_length > 16 &&
deps_length - current_dependencies_index > 1
? new Set(full_current_dependencies)
: null
for (i = current_dependencies_index; i < deps_length; i++) {
const dependency = dependencies[i]
if (
full_current_dependencies_set !== null
? !full_current_dependencies_set.has(dependency)
: !full_current_dependencies.includes(dependency)
) {
remove_reaction(signal, dependency)
}
}
}
if (dependencies !== null && current_dependencies_index > 0) {
dependencies.length =
current_dependencies_index + current_dependencies.length
for (i = 0; i < current_dependencies.length; i++) {
dependencies[current_dependencies_index + i] = current_dependencies[i]
}
} else {
signal.deps = /** @type {import('./types.js').Value<V>[]} **/ (
dependencies = current_dependencies
)
}
if (!current_skip_reaction) {
for (i = current_dependencies_index; i < dependencies.length; i++) {
const dependency = dependencies[i]
const reactions = dependency.reactions
if (reactions === null) {
dependency.reactions = [signal]
} else if (reactions[reactions.length - 1] !== signal) {
// TODO: should this be:
//
// } else if (!reactions.includes(signal)) {
//
reactions.push(signal)
}
}
}
} else if (
dependencies !== null &&
current_dependencies_index < dependencies.length
) {
remove_reactions(signal, current_dependencies_index)
dependencies.length = current_dependencies_index
}
return res
} finally {
current_dependencies = previous_dependencies
current_dependencies_index = previous_dependencies_index
current_untracked_writes = previous_untracked_writes
current_reaction = previous_reaction
current_skip_reaction = previous_skip_reaction
current_untracking = previous_untracking
}
}
/**
* @template V
* @param {import('./types.js').Reaction} signal
* @param {import('./types.js').Value<V>} dependency
* @returns {void}
*/
function remove_reaction(signal, dependency) {
const reactions = dependency.reactions
let reactions_length = 0
if (reactions !== null) {
reactions_length = reactions.length - 1
const index = reactions.indexOf(signal)
if (index !== -1) {
if (reactions_length === 0) {
dependency.reactions = null
} else {
// Swap with last element and then remove.
reactions[index] = reactions[reactions_length]
reactions.pop()
}
}
}
if (reactions_length === 0 && (dependency.f & UNOWNED) !== 0) {
// If the signal is unowned then we need to make sure to change it to dirty.
set_signal_status(dependency, DIRTY)
remove_reactions(
/** @type {import('./types.js').Derived} **/ (dependency),
0,
)
}
}
/**
* @param {import('./types.js').Reaction} signal
* @param {number} start_index
* @returns {void}
*/
function remove_reactions(signal, start_index) {
const dependencies = signal.deps
if (dependencies !== null) {
const active_dependencies =
start_index === 0 ? null : dependencies.slice(0, start_index)
let i
for (i = start_index; i < dependencies.length; i++) {
const dependency = dependencies[i]
// Avoid removing a reaction if we know that it is active (start_index will not be 0)
if (
active_dependencies === null ||
!active_dependencies.includes(dependency)
) {
remove_reaction(signal, dependency)
}
}
}
}
/**
* @param {import('./types.js').Reaction} signal
* @returns {void}
*/
function destroy_effect_children(signal) {
let effect = signal.first
signal.first = null
signal.last = null
var sibling
while (effect !== null) {
sibling = effect.next
destroy_effect(effect)
effect = sibling
}
}
/**
* @param {import('./types.js').Effect} effect
* @returns {void}
*/
function execute_effect(effect) {
var flags = effect.f
if ((flags & DESTROYED) !== 0) {
return
}
set_signal_status(effect, CLEAN)
var component_context = effect.ctx
var previous_effect = current_effect
var previous_component_context = current_component_context
current_effect = effect
current_component_context = component_context
try {
if ((flags & BLOCK_EFFECT) === 0) {
destroy_effect_children(effect)
}
effect.teardown?.call(null)
var teardown = execute_reaction_fn(effect)
effect.teardown = typeof teardown === 'function' ? teardown : null
} finally {
current_effect = previous_effect
current_component_context = previous_component_context
}
}
function infinite_loop_guard() {
if (flush_count > 1000) {
flush_count = 0
throw new Error('ERR_SVELTE_TOO_MANY_UPDATES' + '')
}
flush_count++
}
/**
* @param {Array<import('./types.js').Effect>} root_effects
* @returns {void}
*/
function flush_queued_root_effects(root_effects) {
for (var i = 0; i < root_effects.length; i++) {
var signal = root_effects[i]
flush_nested_effects(signal, RENDER_EFFECT | EFFECT)
}
}
/**
* @param {Array<import('./types.js').Effect>} effects
* @returns {void}
*/
function flush_queued_effects(effects) {
var length = effects.length
if (length === 0) return
infinite_loop_guard()
for (var i = 0; i < length; i++) {
var effect = effects[i]
if ((effect.f & (DESTROYED | INERT)) === 0 && check_dirtiness(effect)) {
execute_effect(effect)
}
}
}
function process_microtask() {
is_micro_task_queued = false
if (flush_count > 101) {
return
}
const previous_queued_root_effects = current_queued_root_effects
current_queued_root_effects = []
flush_queued_root_effects(previous_queued_root_effects)
if (!is_micro_task_queued) {
flush_count = 0
}
}
/**
* @param {import('./types.js').Effect} signal
* @returns {void}
*/
function schedule_effect(signal) {
if (current_scheduler_mode === FLUSH_MICROTASK) {
if (!is_micro_task_queued) {
is_micro_task_queued = true
queueMicrotask(process_microtask)
}
}
var effect = signal
while (effect.parent !== null) {
effect = effect.parent
var flags = effect.f
if ((flags & BRANCH_EFFECT) !== 0) {
if ((flags & CLEAN) === 0) return
set_signal_status(effect, MAYBE_DIRTY)
}
}
current_queued_root_effects.push(effect)
}
/**
*
* This function both runs render effects and collects user effects in topological order
* from the starting effect passed in. Effects will be collected when they match the filtered
* bitwise flag passed in only. The collected effects array will be populated with all the user
* effects to be flushed.
*
* @param {import('./types.js').Effect} effect
* @param {number} filter_flags
* @param {boolean} shallow
* @param {import('./types.js').Effect[]} collected_effects
* @returns {void}
*/
function process_effects(effect, filter_flags, shallow, collected_effects) {
var current_effect = effect.first
var effects = []
main_loop: while (current_effect !== null) {
var flags = current_effect.f
// TODO: we probably don't need to check for destroyed as it shouldn't be encountered?
var is_active = (flags & (DESTROYED | INERT)) === 0
var is_branch = flags & BRANCH_EFFECT
var is_clean = (flags & CLEAN) !== 0
var child = current_effect.first
// Skip this branch if it's clean
if (is_active && (!is_branch || !is_clean)) {
if (is_branch) {
set_signal_status(current_effect, CLEAN)
}
if ((flags & RENDER_EFFECT) !== 0) {
if (is_branch) {
if (!shallow && child !== null) {
current_effect = child
continue
}
} else {
if (check_dirtiness(current_effect)) {
execute_effect(current_effect)
// Child might have been mutated since running the effect
child = current_effect.first
}
if (!shallow && child !== null) {
current_effect = child
continue
}
}
} else if ((flags & EFFECT) !== 0) {
if (is_branch || is_clean) {
if (!shallow && child !== null) {
current_effect = child
continue
}
} else {
effects.push(current_effect)
}
}
}
var sibling = current_effect.next
if (sibling === null) {
let parent = current_effect.parent
while (parent !== null) {
if (effect === parent) {
break main_loop
}
var parent_sibling = parent.next
if (parent_sibling !== null) {
current_effect = parent_sibling
continue main_loop
}
parent = parent.parent
}
}
current_effect = sibling
}
if (effects.length > 0) {
if ((filter_flags & EFFECT) !== 0) {
collected_effects.push(...effects)
}
if (!shallow) {
for (var i = 0; i < effects.length; i++) {
process_effects(effects[i], filter_flags, false, collected_effects)
}
}
}
}
/**
*
* This function recursively collects effects in topological order from the starting effect passed in.
* Effects will be collected when they match the filtered bitwise flag passed in only. The collected
* array will be populated with all the effects.
*
* @param {import('./types.js').Effect} effect
* @param {number} filter_flags
* @param {boolean} [shallow]
* @returns {void}
*/
function flush_nested_effects(effect, filter_flags, shallow = false) {
/** @type {import('#client').Effect[]} */
var collected_effects = []
var previously_flushing_effect = is_flushing_effect
is_flushing_effect = true
try {
// When working with custom elements, the root effects might not have a root
if (effect.first === null && (effect.f & BRANCH_EFFECT) === 0) {
flush_queued_effects([effect])
} else {
process_effects(effect, filter_flags, shallow, collected_effects)
flush_queued_effects(collected_effects)
}
} finally {
is_flushing_effect = previously_flushing_effect
}
}
/**
* Internal version of `flushSync` with the option to not flush previous effects.
* Returns the result of the passed function, if given.
* @param {() => any} [fn]
* @param {boolean} [flush_previous]
* @returns {any}
*/
function flush_sync(fn, flush_previous = true) {
var previous_scheduler_mode = current_scheduler_mode
var previous_queued_root_effects = current_queued_root_effects
try {
infinite_loop_guard()
/** @type {import('./types.js').Effect[]} */
const root_effects = []
current_scheduler_mode = FLUSH_SYNC
current_queued_root_effects = root_effects
if (flush_previous) {
flush_queued_root_effects(previous_queued_root_effects)
}
var result = fn?.()
if (current_queued_root_effects.length > 0 || root_effects.length > 0) {
flush_sync()
}
flush_tasks()
flush_count = 0
return result
} finally {
current_scheduler_mode = previous_scheduler_mode
current_queued_root_effects = previous_queued_root_effects
}
}
/**
* @template V
* @param {import('./types.js').Value<V>} signal
* @returns {V}
*/
function get$2(signal) {
const flags = signal.f
if ((flags & DESTROYED) !== 0) {
return signal.v
}
// Register the dependency on the current reaction signal.
if (
current_reaction !== null &&
(current_reaction.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 &&
!current_untracking
) {
const unowned = (current_reaction.f & UNOWNED) !== 0
const dependencies = current_reaction.deps
if (
current_dependencies === null &&
dependencies !== null &&
dependencies[current_dependencies_index] === signal &&
!(unowned && current_effect !== null)
) {
current_dependencies_index++
} else if (
dependencies === null ||
current_dependencies_index === 0 ||
dependencies[current_dependencies_index - 1] !== signal
) {
if (current_dependencies === null) {
current_dependencies = [signal]
} else {
current_dependencies.push(signal)
}
}
if (
current_untracked_writes !== null &&
current_effect !== null &&
(current_effect.f & CLEAN) !== 0 &&
(current_effect.f & BRANCH_EFFECT) === 0 &&
current_untracked_writes.includes(signal)
) {
set_signal_status(current_effect, DIRTY)
schedule_effect(current_effect)
}
}
if (
(flags & DERIVED) !== 0 &&
check_dirtiness(/** @type {import('#client').Derived} */ (signal))
) {
{
update_derived(
/** @type {import('./types.js').Derived} **/ (signal),
false,
)
}
}
return signal.v
}
/**
* @param {import('#client').Value} signal
* @param {number} to_status
* @param {boolean} force_schedule
* @returns {void}
*/
function mark_reactions(signal, to_status, force_schedule) {
var reactions = signal.reactions
if (reactions === null) return
var runes = is_runes()
var length = reactions.length
for (var i = 0; i < length; i++) {
var reaction = reactions[i]
// We skip any effects that are already dirty (but not unowned). Additionally, we also
// skip if the reaction is the same as the current effect (except if we're not in runes or we
// are in force schedule mode).
if ((!force_schedule || !runes) && reaction === current_effect) {
continue
}
var flags = reaction.f
set_signal_status(reaction, to_status)
// If the signal is not clean, then skip over it – with the exception of unowned signals that
// are already maybe dirty. Unowned signals might be dirty because they are not captured as part of an
// effect.
var maybe_dirty = (flags & MAYBE_DIRTY) !== 0
var unowned = (flags & UNOWNED) !== 0
if ((flags & CLEAN) !== 0 || (maybe_dirty && unowned)) {
if ((reaction.f & DERIVED) !== 0) {
mark_reactions(
/** @type {import('#client').Derived} */ (reaction),
MAYBE_DIRTY,
force_schedule,
)
} else {
schedule_effect(/** @type {import('#client').Effect} */ (reaction))
}
}
}
}
/**
* Use `untrack` to prevent something from being treated as an `$effect`/`$derived` dependency.
*
* https://svelte-5-preview.vercel.app/docs/functions#untrack
* @template T
* @param {() => T} fn
* @returns {T}
*/
function untrack(fn) {
const previous_untracking = current_untracking
try {
current_untracking = true
return fn()
} finally {
current_untracking = previous_untracking
}
}
const STATUS_MASK = ~(DIRTY | MAYBE_DIRTY | CLEAN)
/**
* @param {import('./types.js').Signal} signal
* @param {number} status
* @returns {void}
*/
function set_signal_status(signal, status) {
signal.f = (signal.f & STATUS_MASK) | status
}
/**
* @template V
* @param {V | import('./types.js').Value<V>} val
* @returns {val is import('./types.js').Value<V>}
*/
function is_signal(val) {
return (
typeof val === 'object' &&
val !== null &&
typeof (/** @type {import('./types.js').Value<V>} */ (val).f) === 'number'
)
}
/**
* @param {Record<string, unknown>} props
* @param {any} runes
* @param {Function} [fn]
* @returns {void}
*/
function push(props, runes = false, fn) {
current_component_context = {
// exports (and props, if `accessors: true`)
x: null,
// context
c: null,
// effects
e: null,
// mounted
m: false,
// parent
p: current_component_context,
// signals
d: null,
// props
s: props,
// runes
r: runes,
// legacy $:
l1: [],
l2: source(false),
// update_callbacks
u: null,
}
}
/**
* @template {Record<string, any>} T
* @param {T} [component]
* @returns {T}
*/
function pop(component) {
const context_stack_item = current_component_context
if (context_stack_item !== null) {
if (component !== undefined) {
context_stack_item.x = component
}
const effects = context_stack_item.e
if (effects !== null) {
context_stack_item.e = null
for (let i = 0; i < effects.length; i++) {
effect(effects[i])
}
}
current_component_context = context_stack_item.p
context_stack_item.m = true
}
// Micro-optimization: Don't set .a above to the empty object
// so it can be garbage-collected when the return here is unused
return component || /** @type {T} */ ({})
}
/**
* Possibly traverse an object and read all its properties so that they're all reactive in case this is `$state`.
* Does only check first level of an object for performance reasons (heuristic should be good for 99% of all cases).
* @param {any} value
* @returns {void}
*/
function deep_read_state(value) {
if (typeof value !== 'object' || !value || value instanceof EventTarget) {
return
}
if (STATE_SYMBOL in value) {
deep_read(value)
} else if (!Array.isArray(value)) {
for (let key in value) {
const prop = value[key]
if (typeof prop === 'object' && prop && STATE_SYMBOL in prop) {
deep_read(prop)
}
}
}
}
/**
* Deeply traverse an object and read all its properties
* so that they're all reactive in case this is `$state`
* @param {any} value
* @param {Set<any>} visited
* @returns {void}
*/
function deep_read(value, visited = new Set()) {
if (
typeof value === 'object' &&
value !== null &&
// We don't want to traverse DOM elements
!(value instanceof EventTarget) &&
!visited.has(value)
) {
visited.add(value)
for (let key in value) {
try {
deep_read(value[key], visited)
} catch (e) {
// continue
}
}
const proto = Object.getPrototypeOf(value)
if (
proto !== Object.prototype &&
proto !== Array.prototype &&
proto !== Map.prototype &&
proto !== Set.prototype &&
proto !== Date.prototype
) {
const descriptors = get_descriptors(proto)
for (let key in descriptors) {
const get = descriptors[key].get
if (get) {
try {
get.call(value)
} catch (e) {
// continue
}
}
}
}
}
}
/**
* @template V
* @param {V | import('#client').Value<V>} value
* @returns {V}
*/
function unwrap(value) {
if (is_signal(value)) {
// @ts-ignore
return get$2(value)
}
// @ts-ignore
return value
}
/**
* Use this variable to guard everything related to hydration code so it can be treeshaken out
* if the user doesn't use the `hydrate` method and these code paths are therefore not needed.
*/
let hydrating = false
/** @param {boolean} value */
function set_hydrating(value) {
hydrating = value
}
/**
* Array of nodes to traverse for hydration. This will be null if we're not hydrating, but for
* the sake of simplicity we're not going to use `null` checks everywhere and instead rely on
* the `hydrating` flag to tell whether or not we're in hydration mode at which point this is set.
* @type {import('#client').TemplateNode[]}
*/
let hydrate_nodes = /** @type {any} */ (null)
/** @param {import('#client').TemplateNode[]} nodes */
function set_hydrate_nodes(nodes) {
hydrate_nodes = nodes
}
/**
* This function is only called when `hydrating` is true. If passed a `<!--[-->` opening
* hydration marker, it finds the corresponding closing marker and sets `hydrate_nodes`
* to everything between the markers, before returning the closing marker.
* @param {Node} node
* @returns {Node}
*/
function hydrate_anchor(node) {
if (node.nodeType !== 8) {
return node
}
var current = /** @type {Node | null} */ (node)
// TODO this could have false positives, if a user comment consisted of `[`. need to tighten that up
if (/** @type {Comment} */ (current)?.data !== HYDRATION_START) {
return node
}
/** @type {Node[]} */
var nodes = []
var depth = 0
while ((current = /** @type {Node} */ (current).nextSibling) !== null) {
if (current.nodeType === 8) {
var data = /** @type {Comment} */ (current).data
if (data === HYDRATION_START) {
depth += 1
} else if (data[0] === HYDRATION_END) {
if (depth === 0) {
hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (
nodes
)
return current
}
depth -= 1
}
}
nodes.push(current)
}
throw new Error('Expected a closing hydration marker')
}
/**
* @param {Comment} anchor
* @param {() => boolean} get_condition
* @param {(anchor: Node) => import('#client').Dom} consequent_fn
* @param {null | ((anchor: Node) => import('#client').Dom)} [alternate_fn]
* @param {boolean} [elseif] True if this is an `{:else if ...}` block rather than an `{#if ...}`, as that affects which transitions are considered 'local'
* @returns {void}
*/
function if_block(
anchor,
get_condition,
consequent_fn,
alternate_fn = null,
elseif = false,
) {
/** @type {import('#client').Effect | null} */
let consequent_effect = null
/** @type {import('#client').Effect | null} */
let alternate_effect = null
/** @type {boolean | null} */
let condition = null
const effect = block(() => {
if (condition === (condition = !!get_condition())) return
/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false
if (hydrating) {
const is_else = anchor.data === HYDRATION_END_ELSE
if (condition === is_else) {
// Hydration mismatch: remove everything inside the anchor and start fresh.
// This could happen with `{#if browser}...{/if}`, for example
remove$1(hydrate_nodes)
set_hydrating(false)
mismatch = true
}
}
if (condition) {
if (consequent_effect) {
resume_effect(consequent_effect)
} else {
consequent_effect = branch(() => consequent_fn(anchor))
}
if (alternate_effect) {
pause_effect(alternate_effect, () => {
alternate_effect = null
})
}
} else {
if (alternate_effect) {
resume_effect(alternate_effect)
} else if (alternate_fn) {
alternate_effect = branch(() => alternate_fn(anchor))
}
if (consequent_effect) {
pause_effect(consequent_effect, () => {
consequent_effect = null
})
}
}
if (mismatch) {
// continue in hydration mode
set_hydrating(true)
}
})
if (elseif) {
effect.f |= IS_ELSEIF
}
}
// We cache the Node and Element prototype methods, so that we can avoid doing
// expensive prototype chain lookups.
/** @type {Node} */
var node_prototype
/** @type {Element} */
var element_prototype
/** @type {Text} */
var text_prototype
/** @type {typeof Node.prototype.cloneNode} */
var clone_node_method
/** @type {(this: Node) => ChildNode | null} */
var first_child_get
/** @type {(this: Node) => ChildNode | null} */
var next_sibling_get
/** @type {(this: Node, text: string ) => void} */
var text_content_set
/**
* Initialize these lazily to avoid issues when using the runtime in a server context
* where these globals are not available while avoiding a separate server entry point
*/
function init_operations() {
if (node_prototype !== undefined) {
return
}
node_prototype = Node.prototype
element_prototype = Element.prototype
text_prototype = Text.prototype
node_prototype.appendChild
clone_node_method = node_prototype.cloneNode
// the following assignments improve perf of lookups on DOM nodes
// @ts-expect-error
element_prototype.__click = undefined
// @ts-expect-error
text_prototype.__nodeValue = ' '
// @ts-expect-error
element_prototype.__className = ''
// @ts-expect-error
element_prototype.__attributes = null
first_child_get = /** @type {(this: Node) => ChildNode | null} */ (
// @ts-ignore
get_descriptor(node_prototype, 'firstChild').get
)
next_sibling_get = /** @type {(this: Node) => ChildNode | null} */ (
// @ts-ignore
get_descriptor(node_prototype, 'nextSibling').get
)
text_content_set = /** @type {(this: Node, text: string ) => void} */ (
// @ts-ignore
get_descriptor(node_prototype, 'textContent').set
)
/** @type {(this: Element, class_name: string) => void} */ ;(
// @ts-ignore
get_descriptor(element_prototype, 'className').set
)
}
/**
* @template {Node} N
* @param {N} node
* @param {boolean} deep
* @returns {N}
*/
/*#__NO_SIDE_EFFECTS__*/
function clone_node(node, deep) {
return /** @type {N} */ (clone_node_method.call(node, deep))
}
/** @returns {Text} */
function empty$1() {
return document.createTextNode('')
}
/**
* @template {Node} N
* @param {N} node
* @returns {Node | null}
*/
/*#__NO_SIDE_EFFECTS__*/
function child(node) {
const child = first_child_get.call(node)
if (!hydrating) return child
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty
if (child === null) {
return node.appendChild(empty$1())
}
return hydrate_anchor(child)
}
/**
* @param {DocumentFragment | import('#client').TemplateNode[]} fragment
* @param {boolean} is_text
* @returns {Node | null}
*/
/*#__NO_SIDE_EFFECTS__*/
function first_child(fragment, is_text) {
if (!hydrating) {
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
return first_child_get.call(/** @type {DocumentFragment} */ (fragment))
}
// when we _are_ hydrating, `fragment` is an array of nodes
const first_node = /** @type {import('#client').TemplateNode[]} */ (
fragment
)[0]
// if an {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one
if (is_text && first_node?.nodeType !== 3) {
const text = empty$1()
hydrate_nodes.unshift(text)
first_node?.before(text)
return text
}
return hydrate_anchor(first_node)
}
/**
* @template {Node} N
* @param {N} node
* @param {boolean} is_text
* @returns {Node | null}
*/
/*#__NO_SIDE_EFFECTS__*/
function sibling(node, is_text = false) {
const next_sibling = next_sibling_get.call(node)
if (!hydrating) {
return next_sibling
}
// if a sibling {expression} is empty during SSR, there might be no
// text node to hydrate — we must therefore create one
if (is_text && next_sibling?.nodeType !== 3) {
const text = empty$1()
if (next_sibling) {
const index = hydrate_nodes.indexOf(
/** @type {Text | Comment | Element} */ (next_sibling),
)
hydrate_nodes.splice(index, 0, text)
next_sibling.before(text)
} else {
hydrate_nodes.push(text)
}
return text
}
return hydrate_anchor(/** @type {Node} */ (next_sibling))
}
/**
* @template {Node} N
* @param {N} node
* @returns {void}
*/
function clear_text_content(node) {
text_content_set.call(node, '')
}
/**
* The row of a keyed each block that is currently updating. We track this
* so that `animate:` directives have something to attach themselves to
* @type {import('#client').EachItem | null}
*/
let current_each_item = null
/**
* Pause multiple effects simultaneously, and coordinate their
* subsequent destruction. Used in each blocks
* @param {import('#client').Effect[]} effects
* @param {null | Node} controlled_anchor
* @param {() => void} [callback]
*/
function pause_effects(effects, controlled_anchor, callback) {
/** @type {import('#client').TransitionManager[]} */
var transitions = []
var length = effects.length
for (var i = 0; i < length; i++) {
pause_children(effects[i], transitions, true)
}
// If we have a controlled anchor, it means that the each block is inside a single
// DOM element, so we can apply a fast-path for clearing the contents of the element.
if (
effects.length > 0 &&
transitions.length === 0 &&
controlled_anchor !== null
) {
var parent_node = /** @type {Element} */ (controlled_anchor.parentNode)
parent_node.textContent = ''
parent_node.append(controlled_anchor)
}
run_out_transitions(transitions, () => {
for (var i = 0; i < length; i++) {
destroy_effect(effects[i])
}
if (callback !== undefined) callback()
})
}
/**
* @template V
* @param {Element | Comment} anchor The next sibling node, or the parent node if this is a 'controlled' block
* @param {number} flags
* @param {() => V[]} get_collection
* @param {null | ((item: V) => string)} get_key
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn
* @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn
* @returns {void}
*/
function each(
anchor,
flags,
get_collection,
get_key,
render_fn,
fallback_fn,
reconcile_fn,
) {
/** @type {import('#client').EachState} */
var state = { flags, items: [] }
var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0
if (is_controlled) {
var parent_node = /** @type {Element} */ (anchor)
anchor = hydrating
? /** @type {Comment | Text} */ (
hydrate_anchor(/** @type {Comment | Text} */ (parent_node.firstChild))
)
: parent_node.appendChild(empty$1())
}
/** @type {import('#client').Effect | null} */
var fallback = null
block(() => {
var collection = get_collection()
var array = is_array(collection)
? collection
: collection == null
? []
: Array.from(collection)
var keys = get_key === null ? array : array.map(get_key)
var length = array.length
// If we are working with an array that isn't proxied or frozen, then remove strict equality and ensure the items
// are treated as reactive, so they get wrapped in a signal.
var flags = state.flags
if (
(flags & EACH_IS_STRICT_EQUALS) !== 0 &&
!is_frozen(array) &&
!(STATE_SYMBOL in array)
) {
flags ^= EACH_IS_STRICT_EQUALS
// Additionally if we're in an keyed each block, we'll need ensure the items are all wrapped in signals.
if ((flags & EACH_KEYED) !== 0 && (flags & EACH_ITEM_REACTIVE) === 0) {
flags ^= EACH_ITEM_REACTIVE
}
}
/** `true` if there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false
if (hydrating) {
var is_else = /** @type {Comment} */ (anchor).data === HYDRATION_END_ELSE
if (is_else !== (length === 0)) {
// hydration mismatch — remove the server-rendered DOM and start over
remove$1(hydrate_nodes)
set_hydrating(false)
mismatch = true
}
}
// this is separate to the previous block because `hydrating` might change
if (hydrating) {
var b_items = []
/** @type {Node} */
var child_anchor = hydrate_nodes[0]
for (var i = 0; i < length; i++) {
if (
child_anchor.nodeType !== 8 ||
/** @type {Comment} */ (child_anchor).data !== HYDRATION_START
) {
// If `nodes` is null, then that means that the server rendered fewer items than what
// expected, so break out and continue appending non-hydrated items
mismatch = true
set_hydrating(false)
break
}
child_anchor = hydrate_anchor(child_anchor)
b_items[i] = create_item(
child_anchor,
array[i],
keys?.[i],
i,
render_fn,
flags,
)
child_anchor = /** @type {Comment} */ (child_anchor.nextSibling)
}
// remove excess nodes
if (length > 0) {
while (child_anchor !== anchor) {
var next = /** @type {import('#client').TemplateNode} */ (
child_anchor.nextSibling
)
/** @type {import('#client').TemplateNode} */ ;(child_anchor).remove()
child_anchor = next
}
}
state.items = b_items
}
if (!hydrating) {
reconcile_fn(array, state, anchor, render_fn, flags, keys)
}
if (fallback_fn !== null) {
if (length === 0) {
if (fallback) {
resume_effect(fallback)
} else {
fallback = branch(() => fallback_fn(anchor))
}
} else if (fallback !== null) {
pause_effect(fallback, () => {
fallback = null
})
}
}
if (mismatch) {
// continue in hydration mode
set_hydrating(true)
}
})
}
/**
* @template V
* @param {Element | Comment} anchor
* @param {number} flags
* @param {() => V[]} get_collection
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} [fallback_fn]
* @returns {void}
*/
function each_indexed(
anchor,
flags,
get_collection,
render_fn,
fallback_fn = null,
) {
each(
anchor,
flags,
get_collection,
null,
render_fn,
fallback_fn,
reconcile_indexed_array,
)
}
/**
* @template V
* @param {Array<V>} array
* @param {import('#client').EachState} state
* @param {Element | Comment | Text} anchor
* @param {(anchor: Node, item: import('#client').MaybeSource<V>, index: number | import('#client').Source<number>) => void} render_fn
* @param {number} flags
* @returns {void}
*/
function reconcile_indexed_array(array, state, anchor, render_fn, flags) {
var a_items = state.items
var a = a_items.length
var b = array.length
var min = Math.min(a, b)
/** @type {typeof a_items} */
var b_items = Array(b)
var item
var value
// update items
for (var i = 0; i < min; i += 1) {
value = array[i]
item = a_items[i]
b_items[i] = item
update_item(item, value, i, flags)
resume_effect(item.e)
}
if (b > a) {
// add items
for (; i < b; i += 1) {
value = array[i]
item = create_item(anchor, value, null, i, render_fn, flags)
b_items[i] = item
}
state.items = b_items
} else if (a > b) {
// remove items
var effects = []
for (i = b; i < a; i += 1) {
effects.push(a_items[i].e)
}
var controlled_anchor =
(flags & EACH_IS_CONTROLLED) !== 0 && b === 0 ? anchor : null
pause_effects(effects, controlled_anchor, () => {
state.items.length = b
})
}
}
/**
* @param {import('#client').EachItem} item
* @param {any} value
* @param {number} index
* @param {number} type
* @returns {void}
*/
function update_item(item, value, index, type) {
if ((type & EACH_ITEM_REACTIVE) !== 0) {
set$2(item.v, value)
}
if ((type & EACH_INDEX_REACTIVE) !== 0) {
set$2(/** @type {import('#client').Value<number>} */ (item.i), index)
} else {
item.i = index
}
}
/**
* @template V
* @param {Node} anchor
* @param {V} value
* @param {unknown} key
* @param {number} index
* @param {(anchor: Node, item: V | import('#client').Source<V>, index: number | import('#client').Value<number>) => void} render_fn
* @param {number} flags
* @returns {import('#client').EachItem}
*/
function create_item(anchor, value, key, index, render_fn, flags) {
var previous_each_item = current_each_item
try {
var reactive = (flags & EACH_ITEM_REACTIVE) !== 0
var mutable = (flags & EACH_IS_STRICT_EQUALS) === 0
var v = reactive ? (mutable ? mutable_source(value) : source(value)) : value
var i = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index)
/** @type {import('#client').EachItem} */
var item = {
i,
v,
k: key,
a: null,
// @ts-expect-error
e: null,
}
current_each_item = item
item.e = branch(() => render_fn(anchor, v, i))
return item
} finally {
current_each_item = previous_each_item
}
}
/**
* @param {Node} handler_element
* @param {Event} event
* @returns {void}
*/
function handle_event_propagation(handler_element, event) {
var owner_document = handler_element.ownerDocument
var event_name = event.type
var path = event.composedPath?.() || []
var current_target = /** @type {null | Element} */ (path[0] || event.target)
if (event.target !== current_target) {
define_property(event, 'target', {
configurable: true,
value: current_target,
})
}
// composedPath contains list of nodes the event has propagated through.
// We check __root to skip all nodes below it in case this is a
// parent of the __root node, which indicates that there's nested
// mounted apps. In this case we don't want to trigger events multiple times.
var path_idx = 0
// @ts-expect-error is added below
var handled_at = event.__root
if (handled_at) {
var at_idx = path.indexOf(handled_at)
if (
at_idx !== -1 &&
(handler_element === document ||
handler_element === /** @type {any} */ (window))
) {
// This is the fallback document listener or a window listener, but the event was already handled
// -> ignore, but set handle_at to document/window so that we're resetting the event
// chain in case someone manually dispatches the same event object again.
// @ts-expect-error
event.__root = handler_element
return
}
// We're deliberately not skipping if the index is higher, because
// someone could create an event programmatically and emit it multiple times,
// in which case we want to handle the whole propagation chain properly each time.
// (this will only be a false negative if the event is dispatched multiple times and
// the fallback document listener isn't reached in between, but that's super rare)
var handler_idx = path.indexOf(handler_element)
if (handler_idx === -1) {
// handle_idx can theoretically be -1 (happened in some JSDOM testing scenarios with an event listener on the window object)
// so guard against that, too, and assume that everything was handled at this point.
return
}
if (at_idx <= handler_idx) {
// +1 because at_idx is the element which was already handled, and there can only be one delegated event per element.
// Avoids on:click and onclick on the same event resulting in onclick being fired twice.
path_idx = at_idx + 1
}
}
current_target = /** @type {Element} */ (path[path_idx] || event.target)
// Proxy currentTarget to correct target
define_property(event, 'currentTarget', {
configurable: true,
get() {
return current_target || owner_document
},
})
while (current_target !== null) {
/** @type {null | Element} */
var parent_element =
current_target.parentNode ||
/** @type {any} */ (current_target).host ||
null
var internal_prop_name = '__' + event_name
// @ts-ignore
var delegated = current_target[internal_prop_name]
if (
delegated !== undefined &&
!(/** @type {any} */ (current_target).disabled)
) {
if (is_array(delegated)) {
var [fn, ...data] = delegated
fn.apply(current_target, [event, ...data])
} else {
delegated.call(current_target, event)
}
}
if (
event.cancelBubble ||
parent_element === handler_element ||
current_target === handler_element
) {
break
}
current_target = parent_element
}
// @ts-expect-error is used above
event.__root = handler_element
// @ts-expect-error is used above
current_target = handler_element
}
/** @type {Set<string>} */
const all_registered_events = new Set()
/** @type {Set<(events: Array<string>) => void>} */
const root_event_handles = new Set()
/**
* @param {Element} dom
* @param {string} value
* @returns {void}
*/
function set_text(dom, value) {
// @ts-expect-error need to add __value to patched prototype
const prev_node_value = dom.__nodeValue
const next_node_value = stringify(value)
if (hydrating && dom.nodeValue === next_node_value) {
// In case of hydration don't reset the nodeValue as it's already correct.
// @ts-expect-error need to add __nodeValue to patched prototype
dom.__nodeValue = next_node_value
} else if (prev_node_value !== next_node_value) {
dom.nodeValue = next_node_value
// @ts-expect-error need to add __className to patched prototype
dom.__nodeValue = next_node_value
}
}
/**
* @param {unknown} value
* @returns {string}
*/
function stringify(value) {
return typeof value === 'string' ? value : value == null ? '' : value + ''
}
/**
* Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component
*
* @template {Record<string, any>} Props
* @template {Record<string, any>} Exports
* @template {Record<string, any>} Events
* @param {import('../../index.js').ComponentType<import('../../index.js').SvelteComponent<Props, Events>>} component
* @param {{
* target: Document | Element | ShadowRoot;
* anchor?: Node;
* props?: Props;
* events?: { [Property in keyof Events]: (e: Events[Property]) => any };
* context?: Map<any, any>;
* intro?: boolean;
* }} options
* @returns {Exports}
*/
function mount(component, options) {
const anchor = options.anchor ?? options.target.appendChild(empty$1())
// Don't flush previous effects to ensure order of outer effects stays consistent
return flush_sync(() => _mount(component, { ...options, anchor }), false)
}
/**
* Hydrates a component on the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component
*
* @template {Record<string, any>} Props
* @template {Record<string, any>} Exports
* @template {Record<string, any>} Events
* @param {import('../../index.js').ComponentType<import('../../index.js').SvelteComponent<Props, Events>>} component
* @param {{
* target: Document | Element | ShadowRoot;
* props?: Props;
* events?: { [Property in keyof Events]: (e: Events[Property]) => any };
* context?: Map<any, any>;
* intro?: boolean;
* recover?: false;
* }} options
* @returns {Exports}
*/
function hydrate(component, options) {
const target = options.target
const previous_hydrate_nodes = hydrate_nodes
let hydrated = false
try {
// Don't flush previous effects to ensure order of outer effects stays consistent
return flush_sync(() => {
set_hydrating(true)
var node = target.firstChild
while (
node &&
(node.nodeType !== 8 ||
/** @type {Comment} */ (node).data !== HYDRATION_START)
) {
node = node.nextSibling
}
if (!node) {
throw new Error('Missing hydration marker')
}
const anchor = hydrate_anchor(node)
const instance = _mount(component, { ...options, anchor })
// flush_sync will run this callback and then synchronously run any pending effects,
// which don't belong to the hydration phase anymore - therefore reset it here
set_hydrating(false)
hydrated = true
return instance
}, false)
} catch (error) {
if (!hydrated && options.recover !== false) {
// eslint-disable-next-line no-console
console.error('ERR_SVELTE_HYDRATION_MISMATCH' + '', error)
clear_text_content(target)
set_hydrating(false)
return mount(component, options)
} else {
throw error
}
} finally {
set_hydrating(!!previous_hydrate_nodes)
set_hydrate_nodes(previous_hydrate_nodes)
}
}
/**
* @template {Record<string, any>} Props
* @template {Record<string, any>} Exports
* @template {Record<string, any>} Events
* @param {import('../../index.js').ComponentType<import('../../index.js').SvelteComponent<Props, Events>>} Component
* @param {{
* target: Document | Element | ShadowRoot;
* anchor: Node;
* props?: Props;
* events?: { [Property in keyof Events]: (e: Events[Property]) => any };
* context?: Map<any, any>;
* intro?: boolean;
* }} options
* @returns {Exports}
*/
function _mount(
Component,
{
target,
anchor,
props = /** @type {Props} */ ({}),
events,
context,
intro = false,
},
) {
init_operations()
const registered_events = new Set()
const bound_event_listener = handle_event_propagation.bind(null, target)
const bound_document_event_listener = handle_event_propagation.bind(
null,
document,
)
/** @param {Array<string>} events */
const event_handle = (events) => {
for (let i = 0; i < events.length; i++) {
const event_name = events[i]
if (!registered_events.has(event_name)) {
registered_events.add(event_name)
// Add the event listener to both the container and the document.
// The container listener ensures we catch events from within in case
// the outer content stops propagation of the event.
target.addEventListener(
event_name,
bound_event_listener,
PassiveDelegatedEvents.includes(event_name)
? {
passive: true,
}
: undefined,
)
// The document listener ensures we catch events that originate from elements that were
// manually moved outside of the container (e.g. via manual portals).
document.addEventListener(
event_name,
bound_document_event_listener,
PassiveDelegatedEvents.includes(event_name)
? {
passive: true,
}
: undefined,
)
}
}
}
event_handle(array_from(all_registered_events))
root_event_handles.add(event_handle)
/** @type {Exports} */
// @ts-expect-error will be defined because the render effect runs synchronously
let component = undefined
const unmount = effect_root(() => {
branch(() => {
if (context) {
push({})
var ctx = /** @type {import('#client').ComponentContext} */ (
current_component_context
)
ctx.c = context
}
if (events) {
// We can't spread the object or else we'd lose the state proxy stuff, if it is one
/** @type {any} */ ;(props).$$events = events
}
// @ts-expect-error the public typings are not what the actual function looks like
component = Component(anchor, props) || {}
if (context) {
pop()
}
})
return () => {
for (const event_name of registered_events) {
target.removeEventListener(event_name, bound_event_listener)
}
root_event_handles.delete(event_handle)
}
})
mounted_components.set(component, unmount)
return component
}
/**
* References of the components that were mounted or hydrated.
* Uses a `WeakMap` to avoid memory leaks.
*/
let mounted_components = new WeakMap()
/**
* Unmounts a component that was previously mounted using `mount` or `hydrate`.
* @param {Record<string, any>} component
*/
function unmount(component) {
const fn = mounted_components.get(component)
fn?.()
}
/**
* @template P
* @param {Element} dom
* @param {(dom: Element, value?: P) => import('#client').ActionPayload<P>} action
* @param {() => P} [get_value]
* @returns {void}
*/
function action(dom, action, get_value) {
effect(() => {
var payload = untrack(() => action(dom, get_value?.()) || {})
if (get_value && payload?.update) {
var inited = false
render_effect(() => {
var value = get_value()
// Action's update method is coarse-grained, i.e. when anything in the passed value changes, update.
// This works in legacy mode because of mutable_source being updated as a whole, but when using $state
// together with actions and mutation, it wouldn't notice the change without a deep read.
deep_read_state(value)
if (inited) {
/** @type {Function} */ ;(payload.update)(value)
}
})
inited = true
}
if (payload?.destroy) {
return () => /** @type {Function} */ (payload.destroy)()
}
})
}
/**
* @param {Element} element
* @param {string} attribute
* @param {string | null} value
*/
function set_attribute(element, attribute, value) {
value = value == null ? null : value + ''
// @ts-expect-error
var attributes = (element.__attributes ??= {})
if (hydrating) {
attributes[attribute] = element.getAttribute(attribute)
if (attribute === 'src' || attribute === 'href' || attribute === 'srcset') {
// If we reset these attributes, they would result in another network request, which we want to avoid.
// We assume they are the same between client and server as checking if they are equal is expensive
// (we can't just compare the strings as they can be different between client and server but result in the
// same url, so we would need to create hidden anchor elements to compare them)
return
}
}
if (attributes[attribute] === (attributes[attribute] = value)) return
if (value === null) {
element.removeAttribute(attribute)
} else {
element.setAttribute(attribute, value)
}
}
/**
* @param {string} content
* @param {number} flags
* @returns {() => Node | Node[]}
*/
/*#__NO_SIDE_EFFECTS__*/
function template(content, flags) {
var is_fragment = (flags & TEMPLATE_FRAGMENT) !== 0
var use_import_node = (flags & TEMPLATE_USE_IMPORT_NODE) !== 0
/** @type {Node} */
var node
return () => {
if (hydrating) {
return is_fragment
? hydrate_nodes
: /** @type {Node} */ (hydrate_nodes[0])
}
if (!node) {
node = create_fragment_from_html(content)
if (!is_fragment) node = /** @type {Node} */ (node.firstChild)
}
return use_import_node
? document.importNode(node, true)
: clone_node(node, true)
}
}
/**
* @param {string} content
* @param {number} flags
* @returns {() => Node | Node[]}
*/
/*#__NO_SIDE_EFFECTS__*/
function svg_template(content, flags) {
var is_fragment = (flags & TEMPLATE_FRAGMENT) !== 0
var fn = template(`<svg>${content}</svg>`, 0) // we don't need to worry about using importNode for SVGs
/** @type {Element | DocumentFragment} */
var node
return () => {
if (hydrating) {
return is_fragment
? hydrate_nodes
: /** @type {Node} */ (hydrate_nodes[0])
}
if (!node) {
var svg = /** @type {Element} */ (fn())
if ((flags & TEMPLATE_FRAGMENT) === 0) {
node = /** @type {Element} */ (svg.firstChild)
} else {
node = document.createDocumentFragment()
while (svg.firstChild) {
node.appendChild(svg.firstChild)
}
}
}
return clone_node(node, true)
}
}
const comment = template('<!>', TEMPLATE_FRAGMENT)
/**
* Assign the created (or in hydration mode, traversed) dom elements to the current block
* and insert the elements into the dom (in client mode).
* @param {Text | Comment | Element} anchor
* @param {import('#client').Dom} dom
*/
function append(anchor, dom) {
var current = dom
if (!hydrating) {
var node = /** @type {Node} */ (dom)
if (node.nodeType === 11) {
// if hydrating, `dom` is already an array of nodes, but if not then
// we need to create an array to store it on the current effect
current = /** @type {import('#client').Dom} */ ([...node.childNodes])
}
anchor.before(node)
}
/** @type {import('#client').Effect} */ ;(current_effect).dom = current
}
/**
* This function is responsible for synchronizing a possibly bound prop with the inner component state.
* It is used whenever the compiler sees that the component writes to the prop, or when it has a default prop_value.
* @template V
* @param {Record<string, unknown>} props
* @param {string} key
* @param {number} flags
* @param {V | (() => V)} [fallback]
* @returns {(() => V | ((arg: V) => V) | ((arg: V, mutation: boolean) => V))}
*/
function prop(props, key, flags, fallback) {
var immutable = (flags & PROPS_IS_IMMUTABLE) !== 0
var runes = (flags & PROPS_IS_RUNES) !== 0
var lazy = (flags & PROPS_IS_LAZY_INITIAL) !== 0
var prop_value = /** @type {V} */ (props[key])
var setter = get_descriptor(props, key)?.set
var fallback_value = /** @type {V} */ (fallback)
var fallback_dirty = true
var get_fallback = () => {
if (lazy && fallback_dirty) {
fallback_dirty = false
fallback_value = untrack(/** @type {() => V} */ (fallback))
}
return fallback_value
}
if (prop_value === undefined && fallback !== undefined) {
if (setter && runes) {
// TODO consolidate all these random runtime errors
throw new Error('ERR_SVELTE_BINDING_FALLBACK' + '')
}
prop_value = get_fallback()
if (setter) setter(prop_value)
}
var getter = runes
? () => {
var value = /** @type {V} */ (props[key])
if (value === undefined) return get_fallback()
fallback_dirty = true
return value
}
: () => {
var value = /** @type {V} */ (props[key])
if (value !== undefined) fallback_value = /** @type {V} */ (undefined)
return value === undefined ? fallback_value : value
}
// easy mode — prop is never written to
if ((flags & PROPS_IS_UPDATED) === 0) {
return getter
}
// intermediate mode — prop is written to, but the parent component had
// `bind:foo` which means we can just call `$$props.foo = value` directly
if (setter) {
return function (/** @type {V} */ value) {
if (arguments.length === 1) {
/** @type {Function} */ ;(setter)(value)
return value
} else {
return getter()
}
}
}
// hard mode. this is where it gets ugly — the value in the child should
// synchronize with the parent, but it should also be possible to temporarily
// set the value to something else locally.
var from_child = false
// The derived returns the current value. The underlying mutable
// source is written to from various places to persist this value.
var inner_current_value = mutable_source(prop_value)
var current_value = derived(() => {
var parent_value = getter()
var child_value = get$2(inner_current_value)
if (from_child) {
from_child = false
return child_value
}
return (inner_current_value.v = parent_value)
})
if (!immutable) current_value.equals = safe_equals
return function (/** @type {V} */ value) {
var current = get$2(current_value)
if (arguments.length > 0) {
if (!current_value.equals(value)) {
from_child = true
set$2(inner_current_value, value)
get$2(current_value) // force a synchronisation immediately
}
return value
}
return current
}
}
/**
* Takes the same options as a Svelte 4 component and the component function and returns a Svelte 4 compatible component.
*
* @deprecated Use this only as a temporary solution to migrate your imperative component code to Svelte 5.
*
* @template {Record<string, any>} Props
* @template {Record<string, any>} Exports
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
*
* @param {import('svelte').ComponentConstructorOptions<Props> & {
* component: import('svelte').ComponentType<import('svelte').SvelteComponent<Props, Events, Slots>>;
* immutable?: boolean;
* hydrate?: boolean;
* recover?: boolean;
* }} options
* @returns {import('svelte').SvelteComponent<Props, Events, Slots> & Exports}
*/
function createClassComponent(options) {
// @ts-expect-error $$prop_def etc are not actually defined
return new Svelte4Component(options)
}
class Svelte4Component {
/** @type {any} */
#events = {}
/** @type {Record<string, any>} */
#instance
/**
* @param {import('svelte').ComponentConstructorOptions & {
* component: any;
* immutable?: boolean;
* hydrate?: boolean;
* recover?: false;
* }} options
*/
constructor(options) {
// Using proxy state here isn't completely mirroring the Svelte 4 behavior, because mutations to a property
// cause fine-grained updates to only the places where that property is used, and not the entire property.
// Reactive statements and actions (the things where this matters) are handling this properly regardless, so it should be fine in practise.
const props = proxy(
{ ...(options.props || {}), $$events: this.#events },
false,
)
this.#instance = (options.hydrate ? hydrate : mount)(options.component, {
target: options.target,
props,
context: options.context,
intro: options.intro,
recover: options.recover,
})
for (const key of Object.keys(this.#instance)) {
if (key === '$set' || key === '$destroy' || key === '$on') continue
define_property(this, key, {
get() {
return this.#instance[key]
},
/** @param {any} value */
set(value) {
this.#instance[key] = value
},
enumerable: true,
})
}
this.#instance.$set = /** @param {Record<string, any>} next */ (next) => {
Object.assign(props, next)
}
this.#instance.$destroy = () => {
unmount(this.#instance)
}
}
/** @param {Record<string, any>} props */
$set(props) {
this.#instance.$set(props)
}
/**
* @param {string} event
* @param {(...args: any[]) => any} callback
* @returns {any}
*/
$on(event, callback) {
this.#events[event] = this.#events[event] || []
/** @param {any[]} args */
const cb = (...args) => callback.call(this, ...args)
this.#events[event].push(cb)
return () => {
this.#events[event] = this.#events[event].filter(
/** @param {any} fn */ (fn) => fn !== cb,
)
}
}
$destroy() {
this.#instance.$destroy()
}
}
/**
* @typedef {Object} CustomElementPropDefinition
* @property {string} [attribute]
* @property {boolean} [reflect]
* @property {'String'|'Boolean'|'Number'|'Array'|'Object'} [type]
*/
/** @type {any} */
let SvelteElement
if (typeof HTMLElement === 'function') {
SvelteElement = class extends HTMLElement {
/** The Svelte component constructor */
$$ctor
/** Slots */
$$s
/** @type {any} The Svelte component instance */
$$c
/** Whether or not the custom element is connected */
$$cn = false
/** @type {Record<string, any>} Component props data */
$$d = {}
/** `true` if currently in the process of reflecting component props back to attributes */
$$r = false
/** @type {Record<string, CustomElementPropDefinition>} Props definition (name, reflected, type etc) */
$$p_d = {}
/** @type {Record<string, EventListenerOrEventListenerObject[]>} Event listeners */
$$l = {}
/** @type {Map<EventListenerOrEventListenerObject, Function>} Event listener unsubscribe functions */
$$l_u = new Map()
/** @type {any} The managed render effect for reflecting attributes */
$$me
/**
* @param {*} $$componentCtor
* @param {*} $$slots
* @param {*} use_shadow_dom
*/
constructor($$componentCtor, $$slots, use_shadow_dom) {
super()
this.$$ctor = $$componentCtor
this.$$s = $$slots
if (use_shadow_dom) {
this.attachShadow({ mode: 'open' })
}
}
/**
* @param {string} type
* @param {EventListenerOrEventListenerObject} listener
* @param {boolean | AddEventListenerOptions} [options]
*/
addEventListener(type, listener, options) {
// We can't determine upfront if the event is a custom event or not, so we have to
// listen to both. If someone uses a custom event with the same name as a regular
// browser event, this fires twice - we can't avoid that.
this.$$l[type] = this.$$l[type] || []
this.$$l[type].push(listener)
if (this.$$c) {
const unsub = this.$$c.$on(type, listener)
this.$$l_u.set(listener, unsub)
}
super.addEventListener(type, listener, options)
}
/**
* @param {string} type
* @param {EventListenerOrEventListenerObject} listener
* @param {boolean | AddEventListenerOptions} [options]
*/
removeEventListener(type, listener, options) {
super.removeEventListener(type, listener, options)
if (this.$$c) {
const unsub = this.$$l_u.get(listener)
if (unsub) {
unsub()
this.$$l_u.delete(listener)
}
}
}
async connectedCallback() {
this.$$cn = true
if (!this.$$c) {
// We wait one tick to let possible child slot elements be created/mounted
await Promise.resolve()
if (!this.$$cn || this.$$c) {
return
}
/** @param {string} name */
function create_slot(name) {
/**
* @param {Element} anchor
*/
return (anchor) => {
const slot = document.createElement('slot')
if (name !== 'default') slot.name = name
append(anchor, slot)
}
}
/** @type {Record<string, any>} */
const $$slots = {}
const existing_slots = get_custom_elements_slots(this)
for (const name of this.$$s) {
if (name in existing_slots) {
if (name === 'default') {
this.$$d.children = create_slot(name)
} else {
$$slots[name] = create_slot(name)
}
}
}
for (const attribute of this.attributes) {
// this.$$data takes precedence over this.attributes
const name = this.$$g_p(attribute.name)
if (!(name in this.$$d)) {
this.$$d[name] = get_custom_element_value(
name,
attribute.value,
this.$$p_d,
'toProp',
)
}
}
// Port over props that were set programmatically before ce was initialized
for (const key in this.$$p_d) {
// @ts-expect-error
if (!(key in this.$$d) && this[key] !== undefined) {
// @ts-expect-error
this.$$d[key] = this[key] // don't transform, these were set through JavaScript
// @ts-expect-error
delete this[key] // remove the property that shadows the getter/setter
}
}
this.$$c = createClassComponent({
component: this.$$ctor,
target: this.shadowRoot || this,
props: {
...this.$$d,
$$slots,
},
})
// Reflect component props as attributes
this.$$me = render_effect(() => {
this.$$r = true
for (const key of object_keys(this.$$c)) {
if (!this.$$p_d[key]?.reflect) continue
this.$$d[key] = this.$$c[key]
const attribute_value = get_custom_element_value(
key,
this.$$d[key],
this.$$p_d,
'toAttribute',
)
if (attribute_value == null) {
this.removeAttribute(this.$$p_d[key].attribute || key)
} else {
this.setAttribute(
this.$$p_d[key].attribute || key,
attribute_value,
)
}
}
this.$$r = false
})
for (const type in this.$$l) {
for (const listener of this.$$l[type]) {
const unsub = this.$$c.$on(type, listener)
this.$$l_u.set(listener, unsub)
}
}
this.$$l = {}
}
}
// We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte
// and setting attributes through setAttribute etc, this is helpful
/**
* @param {string} attr
* @param {string} _oldValue
* @param {string} newValue
*/
attributeChangedCallback(attr, _oldValue, newValue) {
if (this.$$r) return
attr = this.$$g_p(attr)
this.$$d[attr] = get_custom_element_value(
attr,
newValue,
this.$$p_d,
'toProp',
)
this.$$c?.$set({ [attr]: this.$$d[attr] })
}
disconnectedCallback() {
this.$$cn = false
// In a microtask, because this could be a move within the DOM
Promise.resolve().then(() => {
if (!this.$$cn) {
this.$$c.$destroy()
destroy_effect(this.$$me)
this.$$c = undefined
}
})
}
/**
* @param {string} attribute_name
*/
$$g_p(attribute_name) {
return (
object_keys(this.$$p_d).find(
(key) =>
this.$$p_d[key].attribute === attribute_name ||
(!this.$$p_d[key].attribute &&
key.toLowerCase() === attribute_name),
) || attribute_name
)
}
}
}
/**
* @param {string} prop
* @param {any} value
* @param {Record<string, CustomElementPropDefinition>} props_definition
* @param {'toAttribute' | 'toProp'} [transform]
*/
function get_custom_element_value(prop, value, props_definition, transform) {
const type = props_definition[prop]?.type
value =
type === 'Boolean' && typeof value !== 'boolean' ? value != null : value
if (!transform || !props_definition[prop]) {
return value
} else if (transform === 'toAttribute') {
switch (type) {
case 'Object':
case 'Array':
return value == null ? null : JSON.stringify(value)
case 'Boolean':
return value ? '' : null
case 'Number':
return value == null ? null : value
default:
return value
}
} else {
switch (type) {
case 'Object':
case 'Array':
return value && JSON.parse(value)
case 'Boolean':
return value // conversion already handled above
case 'Number':
return value != null ? +value : value
default:
return value
}
}
}
/**
* @param {HTMLElement} element
*/
function get_custom_elements_slots(element) {
/** @type {Record<string, true>} */
const result = {}
element.childNodes.forEach((node) => {
result[/** @type {Element} node */ (node).slot || 'default'] = true
})
return result
}
/**
* @internal
*
* Turn a Svelte component into a custom element.
* @param {any} Component A Svelte component function
* @param {Record<string, CustomElementPropDefinition>} props_definition The props to observe
* @param {string[]} slots The slots to create
* @param {string[]} exports Explicitly exported values, other than props
* @param {boolean} use_shadow_dom Whether to use shadow DOM
* @param {(ce: new () => HTMLElement) => new () => HTMLElement} [extend]
*/
function create_custom_element(
Component,
props_definition,
slots,
exports,
use_shadow_dom,
extend,
) {
let Class = class extends SvelteElement {
constructor() {
super(Component, slots, use_shadow_dom)
this.$$p_d = props_definition
}
static get observedAttributes() {
return object_keys(props_definition).map((key) =>
(props_definition[key].attribute || key).toLowerCase(),
)
}
}
object_keys(props_definition).forEach((prop) => {
define_property(Class.prototype, prop, {
get() {
return this.$$c && prop in this.$$c ? this.$$c[prop] : this.$$d[prop]
},
set(value) {
value = get_custom_element_value(prop, value, props_definition)
this.$$d[prop] = value
this.$$c?.$set({ [prop]: value })
},
})
})
exports.forEach((property) => {
define_property(Class.prototype, property, {
get() {
return this.$$c?.[property]
},
})
})
if (extend) {
// @ts-expect-error - assigning here is fine
Class = extend(Class)
}
Component.element = /** @type {any} */ Class
return Class
}
class InternMap extends Map {
constructor(entries, key = keyof) {
super()
Object.defineProperties(this, {
_intern: { value: new Map() },
_key: { value: key },
})
if (entries != null)
for (const [key, value] of entries) this.set(key, value)
}
get(key) {
return super.get(intern_get(this, key))
}
has(key) {
return super.has(intern_get(this, key))
}
set(key, value) {
return super.set(intern_set(this, key), value)
}
delete(key) {
return super.delete(intern_delete(this, key))
}
}
function intern_get({ _intern, _key }, value) {
const key = _key(value)
return _intern.has(key) ? _intern.get(key) : value
}
function intern_set({ _intern, _key }, value) {
const key = _key(value)
if (_intern.has(key)) return _intern.get(key)
_intern.set(key, value)
return value
}
function intern_delete({ _intern, _key }, value) {
const key = _key(value)
if (_intern.has(key)) {
value = _intern.get(key)
_intern.delete(key)
}
return value
}
function keyof(value) {
return value !== null && typeof value === 'object' ? value.valueOf() : value
}
var noop = { value: () => {} }
function dispatch() {
for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
if (!(t = arguments[i] + '') || t in _ || /[\s.]/.test(t))
throw new Error('illegal type: ' + t)
_[t] = []
}
return new Dispatch(_)
}
function Dispatch(_) {
this._ = _
}
function parseTypenames$1(typenames, types) {
return typenames
.trim()
.split(/^|\s+/)
.map(function (t) {
var name = '',
i = t.indexOf('.')
if (i >= 0) (name = t.slice(i + 1)), (t = t.slice(0, i))
if (t && !types.hasOwnProperty(t)) throw new Error('unknown type: ' + t)
return { type: t, name: name }
})
}
Dispatch.prototype = dispatch.prototype = {
constructor: Dispatch,
on: function (typename, callback) {
var _ = this._,
T = parseTypenames$1(typename + '', _),
t,
i = -1,
n = T.length
// If no callback was specified, return the callback of the given type and name.
if (arguments.length < 2) {
while (++i < n)
if ((t = (typename = T[i]).type) && (t = get$1(_[t], typename.name)))
return t
return
}
// If a type was specified, set the callback for the given type and name.
// Otherwise, if a null callback was specified, remove callbacks of the given name.
if (callback != null && typeof callback !== 'function')
throw new Error('invalid callback: ' + callback)
while (++i < n) {
if ((t = (typename = T[i]).type))
_[t] = set$1(_[t], typename.name, callback)
else if (callback == null)
for (t in _) _[t] = set$1(_[t], typename.name, null)
}
return this
},
copy: function () {
var copy = {},
_ = this._
for (var t in _) copy[t] = _[t].slice()
return new Dispatch(copy)
},
call: function (type, that) {
if ((n = arguments.length - 2) > 0)
for (var args = new Array(n), i = 0, n, t; i < n; ++i)
args[i] = arguments[i + 2]
if (!this._.hasOwnProperty(type)) throw new Error('unknown type: ' + type)
for (t = this._[type], i = 0, n = t.length; i < n; ++i)
t[i].value.apply(that, args)
},
apply: function (type, that, args) {
if (!this._.hasOwnProperty(type)) throw new Error('unknown type: ' + type)
for (var t = this._[type], i = 0, n = t.length; i < n; ++i)
t[i].value.apply(that, args)
},
}
function get$1(type, name) {
for (var i = 0, n = type.length, c; i < n; ++i) {
if ((c = type[i]).name === name) {
return c.value
}
}
}
function set$1(type, name, callback) {
for (var i = 0, n = type.length; i < n; ++i) {
if (type[i].name === name) {
;(type[i] = noop), (type = type.slice(0, i).concat(type.slice(i + 1)))
break
}
}
if (callback != null) type.push({ name: name, value: callback })
return type
}
var xhtml = 'http://www.w3.org/1999/xhtml'
var namespaces = {
svg: 'http://www.w3.org/2000/svg',
xhtml: xhtml,
xlink: 'http://www.w3.org/1999/xlink',
xml: 'http://www.w3.org/XML/1998/namespace',
xmlns: 'http://www.w3.org/2000/xmlns/',
}
function namespace(name) {
var prefix = (name += ''),
i = prefix.indexOf(':')
if (i >= 0 && (prefix = name.slice(0, i)) !== 'xmlns')
name = name.slice(i + 1)
return namespaces.hasOwnProperty(prefix)
? { space: namespaces[prefix], local: name }
: name // eslint-disable-line no-prototype-builtins
}
function creatorInherit(name) {
return function () {
var document = this.ownerDocument,
uri = this.namespaceURI
return uri === xhtml && document.documentElement.namespaceURI === xhtml
? document.createElement(name)
: document.createElementNS(uri, name)
}
}
function creatorFixed(fullname) {
return function () {
return this.ownerDocument.createElementNS(fullname.space, fullname.local)
}
}
function creator(name) {
var fullname = namespace(name)
return (fullname.local ? creatorFixed : creatorInherit)(fullname)
}
function none() {}
function selector(selector) {
return selector == null
? none
: function () {
return this.querySelector(selector)
}
}
function selection_select(select) {
if (typeof select !== 'function') select = selector(select)
for (
var groups = this._groups,
m = groups.length,
subgroups = new Array(m),
j = 0;
j < m;
++j
) {
for (
var group = groups[j],
n = group.length,
subgroup = (subgroups[j] = new Array(n)),
node,
subnode,
i = 0;
i < n;
++i
) {
if (
(node = group[i]) &&
(subnode = select.call(node, node.__data__, i, group))
) {
if ('__data__' in node) subnode.__data__ = node.__data__
subgroup[i] = subnode
}
}
}
return new Selection$1(subgroups, this._parents)
}
// Given something array like (or null), returns something that is strictly an
// array. This is used to ensure that array-like objects passed to d3.selectAll
// or selection.selectAll are converted into proper arrays when creating a
// selection; we don’t ever want to create a selection backed by a live
// HTMLCollection or NodeList. However, note that selection.selectAll will use a
// static NodeList as a group, since it safely derived from querySelectorAll.
function array(x) {
return x == null ? [] : Array.isArray(x) ? x : Array.from(x)
}
function empty() {
return []
}
function selectorAll(selector) {
return selector == null
? empty
: function () {
return this.querySelectorAll(selector)
}
}
function arrayAll(select) {
return function () {
return array(select.apply(this, arguments))
}
}
function selection_selectAll(select) {
if (typeof select === 'function') select = arrayAll(select)
else select = selectorAll(select)
for (
var groups = this._groups,
m = groups.length,
subgroups = [],
parents = [],
j = 0;
j < m;
++j
) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if ((node = group[i])) {
subgroups.push(select.call(node, node.__data__, i, group))
parents.push(node)
}
}
}
return new Selection$1(subgroups, parents)
}
function matcher(selector) {
return function () {
return this.matches(selector)
}
}
function childMatcher(selector) {
return function (node) {
return node.matches(selector)
}
}
var find$1 = Array.prototype.find
function childFind(match) {
return function () {
return find$1.call(this.children, match)
}
}
function childFirst() {
return this.firstElementChild
}
function selection_selectChild(match) {
return this.select(
match == null
? childFirst
: childFind(typeof match === 'function' ? match : childMatcher(match)),
)
}
var filter$1 = Array.prototype.filter
function children() {
return Array.from(this.children)
}
function childrenFilter(match) {
return function () {
return filter$1.call(this.children, match)
}
}
function selection_selectChildren(match) {
return this.selectAll(
match == null
? children
: childrenFilter(
typeof match === 'function' ? match : childMatcher(match),
),
)
}
function selection_filter(match) {
if (typeof match !== 'function') match = matcher(match)
for (
var groups = this._groups,
m = groups.length,
subgroups = new Array(m),
j = 0;
j < m;
++j
) {
for (
var group = groups[j],
n = group.length,
subgroup = (subgroups[j] = []),
node,
i = 0;
i < n;
++i
) {
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
subgroup.push(node)
}
}
}
return new Selection$1(subgroups, this._parents)
}
function sparse(update) {
return new Array(update.length)
}
function selection_enter() {
return new Selection$1(this._enter || this._groups.map(sparse), this._parents)
}
function EnterNode(parent, datum) {
this.ownerDocument = parent.ownerDocument
this.namespaceURI = parent.namespaceURI
this._next = null
this._parent = parent
this.__data__ = datum
}
EnterNode.prototype = {
constructor: EnterNode,
appendChild: function (child) {
return this._parent.insertBefore(child, this._next)
},
insertBefore: function (child, next) {
return this._parent.insertBefore(child, next)
},
querySelector: function (selector) {
return this._parent.querySelector(selector)
},
querySelectorAll: function (selector) {
return this._parent.querySelectorAll(selector)
},
}
function constant$3(x) {
return function () {
return x
}
}
function bindIndex(parent, group, enter, update, exit, data) {
var i = 0,
node,
groupLength = group.length,
dataLength = data.length
// Put any non-null nodes that fit into update.
// Put any null nodes into enter.
// Put any remaining data into enter.
for (; i < dataLength; ++i) {
if ((node = group[i])) {
node.__data__ = data[i]
update[i] = node
} else {
enter[i] = new EnterNode(parent, data[i])
}
}
// Put any non-null nodes that don’t fit into exit.
for (; i < groupLength; ++i) {
if ((node = group[i])) {
exit[i] = node
}
}
}
function bindKey(parent, group, enter, update, exit, data, key) {
var i,
node,
nodeByKeyValue = new Map(),
groupLength = group.length,
dataLength = data.length,
keyValues = new Array(groupLength),
keyValue
// Compute the key for each node.
// If multiple nodes have the same key, the duplicates are added to exit.
for (i = 0; i < groupLength; ++i) {
if ((node = group[i])) {
keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + ''
if (nodeByKeyValue.has(keyValue)) {
exit[i] = node
} else {
nodeByKeyValue.set(keyValue, node)
}
}
}
// Compute the key for each datum.
// If there a node associated with this key, join and add it to update.
// If there is not (or the key is a duplicate), add it to enter.
for (i = 0; i < dataLength; ++i) {
keyValue = key.call(parent, data[i], i, data) + ''
if ((node = nodeByKeyValue.get(keyValue))) {
update[i] = node
node.__data__ = data[i]
nodeByKeyValue.delete(keyValue)
} else {
enter[i] = new EnterNode(parent, data[i])
}
}
// Add any remaining nodes that were not bound to data to exit.
for (i = 0; i < groupLength; ++i) {
if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) {
exit[i] = node
}
}
}
function datum(node) {
return node.__data__
}
function selection_data(value, key) {
if (!arguments.length) return Array.from(this, datum)
var bind = key ? bindKey : bindIndex,
parents = this._parents,
groups = this._groups
if (typeof value !== 'function') value = constant$3(value)
for (
var m = groups.length,
update = new Array(m),
enter = new Array(m),
exit = new Array(m),
j = 0;
j < m;
++j
) {
var parent = parents[j],
group = groups[j],
groupLength = group.length,
data = arraylike(
value.call(parent, parent && parent.__data__, j, parents),
),
dataLength = data.length,
enterGroup = (enter[j] = new Array(dataLength)),
updateGroup = (update[j] = new Array(dataLength)),
exitGroup = (exit[j] = new Array(groupLength))
bind(parent, group, enterGroup, updateGroup, exitGroup, data, key)
// Now connect the enter nodes to their following update node, such that
// appendChild can insert the materialized enter node before this node,
// rather than at the end of the parent node.
for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
if ((previous = enterGroup[i0])) {
if (i0 >= i1) i1 = i0 + 1
while (!(next = updateGroup[i1]) && ++i1 < dataLength);
previous._next = next || null
}
}
}
update = new Selection$1(update, parents)
update._enter = enter
update._exit = exit
return update
}
// Given some data, this returns an array-like view of it: an object that
// exposes a length property and allows numeric indexing. Note that unlike
// selectAll, this isn’t worried about “live” collections because the resulting
// array will only be used briefly while data is being bound. (It is possible to
// cause the data to change while iterating by using a key function, but please
// don’t; we’d rather avoid a gratuitous copy.)
function arraylike(data) {
return typeof data === 'object' && 'length' in data
? data // Array, TypedArray, NodeList, array-like
: Array.from(data) // Map, Set, iterable, string, or anything else
}
function selection_exit() {
return new Selection$1(this._exit || this._groups.map(sparse), this._parents)
}
function selection_join(onenter, onupdate, onexit) {
var enter = this.enter(),
update = this,
exit = this.exit()
if (typeof onenter === 'function') {
enter = onenter(enter)
if (enter) enter = enter.selection()
} else {
enter = enter.append(onenter + '')
}
if (onupdate != null) {
update = onupdate(update)
if (update) update = update.selection()
}
if (onexit == null) exit.remove()
else onexit(exit)
return enter && update ? enter.merge(update).order() : update
}
function selection_merge(context) {
var selection = context.selection ? context.selection() : context
for (
var groups0 = this._groups,
groups1 = selection._groups,
m0 = groups0.length,
m1 = groups1.length,
m = Math.min(m0, m1),
merges = new Array(m0),
j = 0;
j < m;
++j
) {
for (
var group0 = groups0[j],
group1 = groups1[j],
n = group0.length,
merge = (merges[j] = new Array(n)),
node,
i = 0;
i < n;
++i
) {
if ((node = group0[i] || group1[i])) {
merge[i] = node
}
}
}
for (; j < m0; ++j) {
merges[j] = groups0[j]
}
return new Selection$1(merges, this._parents)
}
function selection_order() {
for (var groups = this._groups, j = -1, m = groups.length; ++j < m; ) {
for (
var group = groups[j], i = group.length - 1, next = group[i], node;
--i >= 0;
) {
if ((node = group[i])) {
if (next && node.compareDocumentPosition(next) ^ 4)
next.parentNode.insertBefore(node, next)
next = node
}
}
}
return this
}
function selection_sort(compare) {
if (!compare) compare = ascending
function compareNode(a, b) {
return a && b ? compare(a.__data__, b.__data__) : !a - !b
}
for (
var groups = this._groups,
m = groups.length,
sortgroups = new Array(m),
j = 0;
j < m;
++j
) {
for (
var group = groups[j],
n = group.length,
sortgroup = (sortgroups[j] = new Array(n)),
node,
i = 0;
i < n;
++i
) {
if ((node = group[i])) {
sortgroup[i] = node
}
}
sortgroup.sort(compareNode)
}
return new Selection$1(sortgroups, this._parents).order()
}
function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN
}
function selection_call() {
var callback = arguments[0]
arguments[0] = this
callback.apply(null, arguments)
return this
}
function selection_nodes() {
return Array.from(this)
}
function selection_node() {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
var node = group[i]
if (node) return node
}
}
return null
}
function selection_size() {
let size = 0
for (const node of this) ++size // eslint-disable-line no-unused-vars
return size
}
function selection_empty() {
return !this.node()
}
function selection_each(callback) {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
if ((node = group[i])) callback.call(node, node.__data__, i, group)
}
}
return this
}
function attrRemove$1(name) {
return function () {
this.removeAttribute(name)
}
}
function attrRemoveNS$1(fullname) {
return function () {
this.removeAttributeNS(fullname.space, fullname.local)
}
}
function attrConstant$1(name, value) {
return function () {
this.setAttribute(name, value)
}
}
function attrConstantNS$1(fullname, value) {
return function () {
this.setAttributeNS(fullname.space, fullname.local, value)
}
}
function attrFunction$1(name, value) {
return function () {
var v = value.apply(this, arguments)
if (v == null) this.removeAttribute(name)
else this.setAttribute(name, v)
}
}
function attrFunctionNS$1(fullname, value) {
return function () {
var v = value.apply(this, arguments)
if (v == null) this.removeAttributeNS(fullname.space, fullname.local)
else this.setAttributeNS(fullname.space, fullname.local, v)
}
}
function selection_attr(name, value) {
var fullname = namespace(name)
if (arguments.length < 2) {
var node = this.node()
return fullname.local
? node.getAttributeNS(fullname.space, fullname.local)
: node.getAttribute(fullname)
}
return this.each(
(value == null
? fullname.local
? attrRemoveNS$1
: attrRemove$1
: typeof value === 'function'
? fullname.local
? attrFunctionNS$1
: attrFunction$1
: fullname.local
? attrConstantNS$1
: attrConstant$1)(fullname, value),
)
}
function defaultView(node) {
return (
(node.ownerDocument && node.ownerDocument.defaultView) || // node is a Node
(node.document && node) || // node is a Window
node.defaultView
) // node is a Document
}
function styleRemove$1(name) {
return function () {
this.style.removeProperty(name)
}
}
function styleConstant$1(name, value, priority) {
return function () {
this.style.setProperty(name, value, priority)
}
}
function styleFunction$1(name, value, priority) {
return function () {
var v = value.apply(this, arguments)
if (v == null) this.style.removeProperty(name)
else this.style.setProperty(name, v, priority)
}
}
function selection_style(name, value, priority) {
return arguments.length > 1
? this.each(
(value == null
? styleRemove$1
: typeof value === 'function'
? styleFunction$1
: styleConstant$1)(name, value, priority == null ? '' : priority),
)
: styleValue(this.node(), name)
}
function styleValue(node, name) {
return (
node.style.getPropertyValue(name) ||
defaultView(node).getComputedStyle(node, null).getPropertyValue(name)
)
}
function propertyRemove(name) {
return function () {
delete this[name]
}
}
function propertyConstant(name, value) {
return function () {
this[name] = value
}
}
function propertyFunction(name, value) {
return function () {
var v = value.apply(this, arguments)
if (v == null) delete this[name]
else this[name] = v
}
}
function selection_property(name, value) {
return arguments.length > 1
? this.each(
(value == null
? propertyRemove
: typeof value === 'function'
? propertyFunction
: propertyConstant)(name, value),
)
: this.node()[name]
}
function classArray(string) {
return string.trim().split(/^|\s+/)
}
function classList(node) {
return node.classList || new ClassList(node)
}
function ClassList(node) {
this._node = node
this._names = classArray(node.getAttribute('class') || '')
}
ClassList.prototype = {
add: function (name) {
var i = this._names.indexOf(name)
if (i < 0) {
this._names.push(name)
this._node.setAttribute('class', this._names.join(' '))
}
},
remove: function (name) {
var i = this._names.indexOf(name)
if (i >= 0) {
this._names.splice(i, 1)
this._node.setAttribute('class', this._names.join(' '))
}
},
contains: function (name) {
return this._names.indexOf(name) >= 0
},
}
function classedAdd(node, names) {
var list = classList(node),
i = -1,
n = names.length
while (++i < n) list.add(names[i])
}
function classedRemove(node, names) {
var list = classList(node),
i = -1,
n = names.length
while (++i < n) list.remove(names[i])
}
function classedTrue(names) {
return function () {
classedAdd(this, names)
}
}
function classedFalse(names) {
return function () {
classedRemove(this, names)
}
}
function classedFunction(names, value) {
return function () {
;(value.apply(this, arguments) ? classedAdd : classedRemove)(this, names)
}
}
function selection_classed(name, value) {
var names = classArray(name + '')
if (arguments.length < 2) {
var list = classList(this.node()),
i = -1,
n = names.length
while (++i < n) if (!list.contains(names[i])) return false
return true
}
return this.each(
(typeof value === 'function'
? classedFunction
: value
? classedTrue
: classedFalse)(names, value),
)
}
function textRemove() {
this.textContent = ''
}
function textConstant$1(value) {
return function () {
this.textContent = value
}
}
function textFunction$1(value) {
return function () {
var v = value.apply(this, arguments)
this.textContent = v == null ? '' : v
}
}
function selection_text(value) {
return arguments.length
? this.each(
value == null
? textRemove
: (typeof value === 'function' ? textFunction$1 : textConstant$1)(
value,
),
)
: this.node().textContent
}
function htmlRemove() {
this.innerHTML = ''
}
function htmlConstant(value) {
return function () {
this.innerHTML = value
}
}
function htmlFunction(value) {
return function () {
var v = value.apply(this, arguments)
this.innerHTML = v == null ? '' : v
}
}
function selection_html(value) {
return arguments.length
? this.each(
value == null
? htmlRemove
: (typeof value === 'function' ? htmlFunction : htmlConstant)(value),
)
: this.node().innerHTML
}
function raise() {
if (this.nextSibling) this.parentNode.appendChild(this)
}
function selection_raise() {
return this.each(raise)
}
function lower() {
if (this.previousSibling)
this.parentNode.insertBefore(this, this.parentNode.firstChild)
}
function selection_lower() {
return this.each(lower)
}
function selection_append(name) {
var create = typeof name === 'function' ? name : creator(name)
return this.select(function () {
return this.appendChild(create.apply(this, arguments))
})
}
function constantNull() {
return null
}
function selection_insert(name, before) {
var create = typeof name === 'function' ? name : creator(name),
select =
before == null
? constantNull
: typeof before === 'function'
? before
: selector(before)
return this.select(function () {
return this.insertBefore(
create.apply(this, arguments),
select.apply(this, arguments) || null,
)
})
}
function remove() {
var parent = this.parentNode
if (parent) parent.removeChild(this)
}
function selection_remove() {
return this.each(remove)
}
function selection_cloneShallow() {
var clone = this.cloneNode(false),
parent = this.parentNode
return parent ? parent.insertBefore(clone, this.nextSibling) : clone
}
function selection_cloneDeep() {
var clone = this.cloneNode(true),
parent = this.parentNode
return parent ? parent.insertBefore(clone, this.nextSibling) : clone
}
function selection_clone(deep) {
return this.select(deep ? selection_cloneDeep : selection_cloneShallow)
}
function selection_datum(value) {
return arguments.length
? this.property('__data__', value)
: this.node().__data__
}
function contextListener(listener) {
return function (event) {
listener.call(this, event, this.__data__)
}
}
function parseTypenames(typenames) {
return typenames
.trim()
.split(/^|\s+/)
.map(function (t) {
var name = '',
i = t.indexOf('.')
if (i >= 0) (name = t.slice(i + 1)), (t = t.slice(0, i))
return { type: t, name: name }
})
}
function onRemove(typename) {
return function () {
var on = this.__on
if (!on) return
for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
if (
((o = on[j]),
(!typename.type || o.type === typename.type) &&
o.name === typename.name)
) {
this.removeEventListener(o.type, o.listener, o.options)
} else {
on[++i] = o
}
}
if (++i) on.length = i
else delete this.__on
}
}
function onAdd(typename, value, options) {
return function () {
var on = this.__on,
o,
listener = contextListener(value)
if (on)
for (var j = 0, m = on.length; j < m; ++j) {
if ((o = on[j]).type === typename.type && o.name === typename.name) {
this.removeEventListener(o.type, o.listener, o.options)
this.addEventListener(
o.type,
(o.listener = listener),
(o.options = options),
)
o.value = value
return
}
}
this.addEventListener(typename.type, listener, options)
o = {
type: typename.type,
name: typename.name,
value: value,
listener: listener,
options: options,
}
if (!on) this.__on = [o]
else on.push(o)
}
}
function selection_on(typename, value, options) {
var typenames = parseTypenames(typename + ''),
i,
n = typenames.length,
t
if (arguments.length < 2) {
var on = this.node().__on
if (on)
for (var j = 0, m = on.length, o; j < m; ++j) {
for (i = 0, o = on[j]; i < n; ++i) {
if ((t = typenames[i]).type === o.type && t.name === o.name) {
return o.value
}
}
}
return
}
on = value ? onAdd : onRemove
for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options))
return this
}
function dispatchEvent(node, type, params) {
var window = defaultView(node),
event = window.CustomEvent
if (typeof event === 'function') {
event = new event(type, params)
} else {
event = window.document.createEvent('Event')
if (params)
event.initEvent(type, params.bubbles, params.cancelable),
(event.detail = params.detail)
else event.initEvent(type, false, false)
}
node.dispatchEvent(event)
}
function dispatchConstant(type, params) {
return function () {
return dispatchEvent(this, type, params)
}
}
function dispatchFunction(type, params) {
return function () {
return dispatchEvent(this, type, params.apply(this, arguments))
}
}
function selection_dispatch(type, params) {
return this.each(
(typeof params === 'function' ? dispatchFunction : dispatchConstant)(
type,
params,
),
)
}
function* selection_iterator() {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
if ((node = group[i])) yield node
}
}
}
var root$2 = [null]
function Selection$1(groups, parents) {
this._groups = groups
this._parents = parents
}
function selection() {
return new Selection$1([[document.documentElement]], root$2)
}
function selection_selection() {
return this
}
Selection$1.prototype = selection.prototype = {
constructor: Selection$1,
select: selection_select,
selectAll: selection_selectAll,
selectChild: selection_selectChild,
selectChildren: selection_selectChildren,
filter: selection_filter,
data: selection_data,
enter: selection_enter,
exit: selection_exit,
join: selection_join,
merge: selection_merge,
selection: selection_selection,
order: selection_order,
sort: selection_sort,
call: selection_call,
nodes: selection_nodes,
node: selection_node,
size: selection_size,
empty: selection_empty,
each: selection_each,
attr: selection_attr,
style: selection_style,
property: selection_property,
classed: selection_classed,
text: selection_text,
html: selection_html,
raise: selection_raise,
lower: selection_lower,
append: selection_append,
insert: selection_insert,
remove: selection_remove,
clone: selection_clone,
datum: selection_datum,
on: selection_on,
dispatch: selection_dispatch,
[Symbol.iterator]: selection_iterator,
}
function select(selector) {
return typeof selector === 'string'
? new Selection$1(
[[document.querySelector(selector)]],
[document.documentElement],
)
: new Selection$1([[selector]], root$2)
}
function create$1(name) {
return select(creator(name).call(document.documentElement))
}
function sourceEvent(event) {
let sourceEvent
while ((sourceEvent = event.sourceEvent)) event = sourceEvent
return event
}
function pointer(event, node) {
event = sourceEvent(event)
if (node === undefined) node = event.currentTarget
if (node) {
var svg = node.ownerSVGElement || node
if (svg.createSVGPoint) {
var point = svg.createSVGPoint()
;(point.x = event.clientX), (point.y = event.clientY)
point = point.matrixTransform(node.getScreenCTM().inverse())
return [point.x, point.y]
}
if (node.getBoundingClientRect) {
var rect = node.getBoundingClientRect()
return [
event.clientX - rect.left - node.clientLeft,
event.clientY - rect.top - node.clientTop,
]
}
}
return [event.pageX, event.pageY]
}
// These are typically used in conjunction with noevent to ensure that we can
// preventDefault on the event.
const nonpassive = { passive: false }
const nonpassivecapture = { capture: true, passive: false }
function nopropagation(event) {
event.stopImmediatePropagation()
}
function noevent(event) {
event.preventDefault()
event.stopImmediatePropagation()
}
function dragDisable(view) {
var root = view.document.documentElement,
selection = select(view).on('dragstart.drag', noevent, nonpassivecapture)
if ('onselectstart' in root) {
selection.on('selectstart.drag', noevent, nonpassivecapture)
} else {
root.__noselect = root.style.MozUserSelect
root.style.MozUserSelect = 'none'
}
}
function yesdrag(view, noclick) {
var root = view.document.documentElement,
selection = select(view).on('dragstart.drag', null)
if (noclick) {
selection.on('click.drag', noevent, nonpassivecapture)
setTimeout(function () {
selection.on('click.drag', null)
}, 0)
}
if ('onselectstart' in root) {
selection.on('selectstart.drag', null)
} else {
root.style.MozUserSelect = root.__noselect
delete root.__noselect
}
}
var constant$2 = (x) => () => x
function DragEvent(
type,
{ sourceEvent, subject, target, identifier, active, x, y, dx, dy, dispatch },
) {
Object.defineProperties(this, {
type: { value: type, enumerable: true, configurable: true },
sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },
subject: { value: subject, enumerable: true, configurable: true },
target: { value: target, enumerable: true, configurable: true },
identifier: { value: identifier, enumerable: true, configurable: true },
active: { value: active, enumerable: true, configurable: true },
x: { value: x, enumerable: true, configurable: true },
y: { value: y, enumerable: true, configurable: true },
dx: { value: dx, enumerable: true, configurable: true },
dy: { value: dy, enumerable: true, configurable: true },
_: { value: dispatch },
})
}
DragEvent.prototype.on = function () {
var value = this._.on.apply(this._, arguments)
return value === this._ ? this : value
}
// Ignore right-click, since that should open the context menu.
function defaultFilter(event) {
return !event.ctrlKey && !event.button
}
function defaultContainer() {
return this.parentNode
}
function defaultSubject(event, d) {
return d == null ? { x: event.x, y: event.y } : d
}
function defaultTouchable() {
return navigator.maxTouchPoints || 'ontouchstart' in this
}
function drag() {
var filter = defaultFilter,
container = defaultContainer,
subject = defaultSubject,
touchable = defaultTouchable,
gestures = {},
listeners = dispatch('start', 'drag', 'end'),
active = 0,
mousedownx,
mousedowny,
mousemoving,
touchending,
clickDistance2 = 0
function drag(selection) {
selection
.on('mousedown.drag', mousedowned)
.filter(touchable)
.on('touchstart.drag', touchstarted)
.on('touchmove.drag', touchmoved, nonpassive)
.on('touchend.drag touchcancel.drag', touchended)
.style('touch-action', 'none')
.style('-webkit-tap-highlight-color', 'rgba(0,0,0,0)')
}
function mousedowned(event, d) {
if (touchending || !filter.call(this, event, d)) return
var gesture = beforestart(
this,
container.call(this, event, d),
event,
d,
'mouse',
)
if (!gesture) return
select(event.view)
.on('mousemove.drag', mousemoved, nonpassivecapture)
.on('mouseup.drag', mouseupped, nonpassivecapture)
dragDisable(event.view)
nopropagation(event)
mousemoving = false
mousedownx = event.clientX
mousedowny = event.clientY
gesture('start', event)
}
function mousemoved(event) {
noevent(event)
if (!mousemoving) {
var dx = event.clientX - mousedownx,
dy = event.clientY - mousedowny
mousemoving = dx * dx + dy * dy > clickDistance2
}
gestures.mouse('drag', event)
}
function mouseupped(event) {
select(event.view).on('mousemove.drag mouseup.drag', null)
yesdrag(event.view, mousemoving)
noevent(event)
gestures.mouse('end', event)
}
function touchstarted(event, d) {
if (!filter.call(this, event, d)) return
var touches = event.changedTouches,
c = container.call(this, event, d),
n = touches.length,
i,
gesture
for (i = 0; i < n; ++i) {
if (
(gesture = beforestart(
this,
c,
event,
d,
touches[i].identifier,
touches[i],
))
) {
nopropagation(event)
gesture('start', event, touches[i])
}
}
}
function touchmoved(event) {
var touches = event.changedTouches,
n = touches.length,
i,
gesture
for (i = 0; i < n; ++i) {
if ((gesture = gestures[touches[i].identifier])) {
noevent(event)
gesture('drag', event, touches[i])
}
}
}
function touchended(event) {
var touches = event.changedTouches,
n = touches.length,
i,
gesture
if (touchending) clearTimeout(touchending)
touchending = setTimeout(function () {
touchending = null
}, 500) // Ghost clicks are delayed!
for (i = 0; i < n; ++i) {
if ((gesture = gestures[touches[i].identifier])) {
nopropagation(event)
gesture('end', event, touches[i])
}
}
}
function beforestart(that, container, event, d, identifier, touch) {
var dispatch = listeners.copy(),
p = pointer(touch || event, container),
dx,
dy,
s
if (
(s = subject.call(
that,
new DragEvent('beforestart', {
sourceEvent: event,
target: drag,
identifier,
active,
x: p[0],
y: p[1],
dx: 0,
dy: 0,
dispatch,
}),
d,
)) == null
)
return
dx = s.x - p[0] || 0
dy = s.y - p[1] || 0
return function gesture(type, event, touch) {
var p0 = p,
n
switch (type) {
case 'start':
;(gestures[identifier] = gesture), (n = active++)
break
case 'end':
delete gestures[identifier], --active // falls through
case 'drag':
;(p = pointer(touch || event, container)), (n = active)
break
}
dispatch.call(
type,
that,
new DragEvent(type, {
sourceEvent: event,
subject: s,
target: drag,
identifier,
active: n,
x: p[0] + dx,
y: p[1] + dy,
dx: p[0] - p0[0],
dy: p[1] - p0[1],
dispatch,
}),
d,
)
}
}
drag.filter = function (_) {
return arguments.length
? ((filter = typeof _ === 'function' ? _ : constant$2(!!_)), drag)
: filter
}
drag.container = function (_) {
return arguments.length
? ((container = typeof _ === 'function' ? _ : constant$2(_)), drag)
: container
}
drag.subject = function (_) {
return arguments.length
? ((subject = typeof _ === 'function' ? _ : constant$2(_)), drag)
: subject
}
drag.touchable = function (_) {
return arguments.length
? ((touchable = typeof _ === 'function' ? _ : constant$2(!!_)), drag)
: touchable
}
drag.on = function () {
var value = listeners.on.apply(listeners, arguments)
return value === listeners ? drag : value
}
drag.clickDistance = function (_) {
return arguments.length
? ((clickDistance2 = (_ = +_) * _), drag)
: Math.sqrt(clickDistance2)
}
return drag
}
function define(constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype
prototype.constructor = constructor
}
function extend(parent, definition) {
var prototype = Object.create(parent.prototype)
for (var key in definition) prototype[key] = definition[key]
return prototype
}
function Color() {}
var darker = 0.7
var brighter = 1 / darker
var reI = '\\s*([+-]?\\d+)\\s*',
reN = '\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*',
reP = '\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*',
reHex = /^#([0-9a-f]{3,8})$/,
reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`),
reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`),
reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`),
reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`),
reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`),
reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`)
var named = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32,
}
define(Color, color, {
copy(channels) {
return Object.assign(new this.constructor(), this, channels)
},
displayable() {
return this.rgb().displayable()
},
hex: color_formatHex, // Deprecated! Use color.formatHex.
formatHex: color_formatHex,
formatHex8: color_formatHex8,
formatHsl: color_formatHsl,
formatRgb: color_formatRgb,
toString: color_formatRgb,
})
function color_formatHex() {
return this.rgb().formatHex()
}
function color_formatHex8() {
return this.rgb().formatHex8()
}
function color_formatHsl() {
return hslConvert(this).formatHsl()
}
function color_formatRgb() {
return this.rgb().formatRgb()
}
function color(format) {
var m, l
format = (format + '').trim().toLowerCase()
return (m = reHex.exec(format))
? ((l = m[1].length),
(m = parseInt(m[1], 16)),
l === 6
? rgbn(m) // #ff0000
: l === 3
? new Rgb(
((m >> 8) & 0xf) | ((m >> 4) & 0xf0),
((m >> 4) & 0xf) | (m & 0xf0),
((m & 0xf) << 4) | (m & 0xf),
1,
) // #f00
: l === 8
? rgba(
(m >> 24) & 0xff,
(m >> 16) & 0xff,
(m >> 8) & 0xff,
(m & 0xff) / 0xff,
) // #ff000000
: l === 4
? rgba(
((m >> 12) & 0xf) | ((m >> 8) & 0xf0),
((m >> 8) & 0xf) | ((m >> 4) & 0xf0),
((m >> 4) & 0xf) | (m & 0xf0),
(((m & 0xf) << 4) | (m & 0xf)) / 0xff,
) // #f000
: null) // invalid hex
: (m = reRgbInteger.exec(format))
? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent.exec(format))
? new Rgb((m[1] * 255) / 100, (m[2] * 255) / 100, (m[3] * 255) / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger.exec(format))
? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent.exec(format))
? rgba(
(m[1] * 255) / 100,
(m[2] * 255) / 100,
(m[3] * 255) / 100,
m[4],
) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent.exec(format))
? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent.exec(format))
? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named.hasOwnProperty(format)
? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
: format === 'transparent'
? new Rgb(NaN, NaN, NaN, 0)
: null
}
function rgbn(n) {
return new Rgb((n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff, 1)
}
function rgba(r, g, b, a) {
if (a <= 0) r = g = b = NaN
return new Rgb(r, g, b, a)
}
function rgbConvert(o) {
if (!(o instanceof Color)) o = color(o)
if (!o) return new Rgb()
o = o.rgb()
return new Rgb(o.r, o.g, o.b, o.opacity)
}
function rgb(r, g, b, opacity) {
return arguments.length === 1
? rgbConvert(r)
: new Rgb(r, g, b, opacity == null ? 1 : opacity)
}
function Rgb(r, g, b, opacity) {
this.r = +r
this.g = +g
this.b = +b
this.opacity = +opacity
}
define(
Rgb,
rgb,
extend(Color, {
brighter(k) {
k = k == null ? brighter : Math.pow(brighter, k)
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity)
},
darker(k) {
k = k == null ? darker : Math.pow(darker, k)
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity)
},
rgb() {
return this
},
clamp() {
return new Rgb(
clampi(this.r),
clampi(this.g),
clampi(this.b),
clampa(this.opacity),
)
},
displayable() {
return (
-0.5 <= this.r &&
this.r < 255.5 &&
-0.5 <= this.g &&
this.g < 255.5 &&
-0.5 <= this.b &&
this.b < 255.5 &&
0 <= this.opacity &&
this.opacity <= 1
)
},
hex: rgb_formatHex, // Deprecated! Use color.formatHex.
formatHex: rgb_formatHex,
formatHex8: rgb_formatHex8,
formatRgb: rgb_formatRgb,
toString: rgb_formatRgb,
}),
)
function rgb_formatHex() {
return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`
}
function rgb_formatHex8() {
return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`
}
function rgb_formatRgb() {
const a = clampa(this.opacity)
return `${a === 1 ? 'rgb(' : 'rgba('}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? ')' : `, ${a})`}`
}
function clampa(opacity) {
return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity))
}
function clampi(value) {
return Math.max(0, Math.min(255, Math.round(value) || 0))
}
function hex(value) {
value = clampi(value)
return (value < 16 ? '0' : '') + value.toString(16)
}
function hsla(h, s, l, a) {
if (a <= 0) h = s = l = NaN
else if (l <= 0 || l >= 1) h = s = NaN
else if (s <= 0) h = NaN
return new Hsl(h, s, l, a)
}
function hslConvert(o) {
if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity)
if (!(o instanceof Color)) o = color(o)
if (!o) return new Hsl()
if (o instanceof Hsl) return o
o = o.rgb()
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
min = Math.min(r, g, b),
max = Math.max(r, g, b),
h = NaN,
s = max - min,
l = (max + min) / 2
if (s) {
if (r === max) h = (g - b) / s + (g < b) * 6
else if (g === max) h = (b - r) / s + 2
else h = (r - g) / s + 4
s /= l < 0.5 ? max + min : 2 - max - min
h *= 60
} else {
s = l > 0 && l < 1 ? 0 : h
}
return new Hsl(h, s, l, o.opacity)
}
function hsl(h, s, l, opacity) {
return arguments.length === 1
? hslConvert(h)
: new Hsl(h, s, l, opacity == null ? 1 : opacity)
}
function Hsl(h, s, l, opacity) {
this.h = +h
this.s = +s
this.l = +l
this.opacity = +opacity
}
define(
Hsl,
hsl,
extend(Color, {
brighter(k) {
k = k == null ? brighter : Math.pow(brighter, k)
return new Hsl(this.h, this.s, this.l * k, this.opacity)
},
darker(k) {
k = k == null ? darker : Math.pow(darker, k)
return new Hsl(this.h, this.s, this.l * k, this.opacity)
},
rgb() {
var h = (this.h % 360) + (this.h < 0) * 360,
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
l = this.l,
m2 = l + (l < 0.5 ? l : 1 - l) * s,
m1 = 2 * l - m2
return new Rgb(
hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
hsl2rgb(h, m1, m2),
hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
this.opacity,
)
},
clamp() {
return new Hsl(
clamph(this.h),
clampt(this.s),
clampt(this.l),
clampa(this.opacity),
)
},
displayable() {
return (
((0 <= this.s && this.s <= 1) || isNaN(this.s)) &&
0 <= this.l &&
this.l <= 1 &&
0 <= this.opacity &&
this.opacity <= 1
)
},
formatHsl() {
const a = clampa(this.opacity)
return `${a === 1 ? 'hsl(' : 'hsla('}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ')' : `, ${a})`}`
},
}),
)
function clamph(value) {
value = (value || 0) % 360
return value < 0 ? value + 360 : value
}
function clampt(value) {
return Math.max(0, Math.min(1, value || 0))
}
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb(h, m1, m2) {
return (
(h < 60
? m1 + ((m2 - m1) * h) / 60
: h < 180
? m2
: h < 240
? m1 + ((m2 - m1) * (240 - h)) / 60
: m1) * 255
)
}
var constant$1 = (x) => () => x
function linear(a, d) {
return function (t) {
return a + t * d
}
}
function exponential(a, b, y) {
return (
(a = Math.pow(a, y)),
(b = Math.pow(b, y) - a),
(y = 1 / y),
function (t) {
return Math.pow(a + t * b, y)
}
)
}
function gamma(y) {
return (y = +y) === 1
? nogamma
: function (a, b) {
return b - a ? exponential(a, b, y) : constant$1(isNaN(a) ? b : a)
}
}
function nogamma(a, b) {
var d = b - a
return d ? linear(a, d) : constant$1(isNaN(a) ? b : a)
}
var interpolateRgb = (function rgbGamma(y) {
var color = gamma(y)
function rgb$1(start, end) {
var r = color((start = rgb(start)).r, (end = rgb(end)).r),
g = color(start.g, end.g),
b = color(start.b, end.b),
opacity = nogamma(start.opacity, end.opacity)
return function (t) {
start.r = r(t)
start.g = g(t)
start.b = b(t)
start.opacity = opacity(t)
return start + ''
}
}
rgb$1.gamma = rgbGamma
return rgb$1
})(1)
function interpolateNumber(a, b) {
return (
(a = +a),
(b = +b),
function (t) {
return a * (1 - t) + b * t
}
)
}
var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
reB = new RegExp(reA.source, 'g')
function zero(b) {
return function () {
return b
}
}
function one(b) {
return function (t) {
return b(t) + ''
}
}
function interpolateString(a, b) {
var bi = (reA.lastIndex = reB.lastIndex = 0), // scan index for next number in b
am, // current match in a
bm, // current match in b
bs, // string preceding current number in b, if any
i = -1, // index in s
s = [], // string constants and placeholders
q = [] // number interpolators
// Coerce inputs to strings.
;(a = a + ''), (b = b + '')
// Interpolate pairs of numbers in a & b.
while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
if ((bs = bm.index) > bi) {
// a string precedes the next number in b
bs = b.slice(bi, bs)
if (s[i])
s[i] += bs // coalesce with previous string
else s[++i] = bs
}
if ((am = am[0]) === (bm = bm[0])) {
// numbers in a & b match
if (s[i])
s[i] += bm // coalesce with previous string
else s[++i] = bm
} else {
// interpolate non-matching numbers
s[++i] = null
q.push({ i: i, x: interpolateNumber(am, bm) })
}
bi = reB.lastIndex
}
// Add remains of b.
if (bi < b.length) {
bs = b.slice(bi)
if (s[i])
s[i] += bs // coalesce with previous string
else s[++i] = bs
}
// Special optimization for only a single match.
// Otherwise, interpolate each of the numbers and rejoin the string.
return s.length < 2
? q[0]
? one(q[0].x)
: zero(b)
: ((b = q.length),
function (t) {
for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t)
return s.join('')
})
}
var degrees = 180 / Math.PI
var identity$2 = {
translateX: 0,
translateY: 0,
rotate: 0,
skewX: 0,
scaleX: 1,
scaleY: 1,
}
function decompose(a, b, c, d, e, f) {
var scaleX, scaleY, skewX
if ((scaleX = Math.sqrt(a * a + b * b))) (a /= scaleX), (b /= scaleX)
if ((skewX = a * c + b * d)) (c -= a * skewX), (d -= b * skewX)
if ((scaleY = Math.sqrt(c * c + d * d)))
(c /= scaleY), (d /= scaleY), (skewX /= scaleY)
if (a * d < b * c) (a = -a), (b = -b), (skewX = -skewX), (scaleX = -scaleX)
return {
translateX: e,
translateY: f,
rotate: Math.atan2(b, a) * degrees,
skewX: Math.atan(skewX) * degrees,
scaleX: scaleX,
scaleY: scaleY,
}
}
var svgNode
/* eslint-disable no-undef */
function parseCss(value) {
const m = new (typeof DOMMatrix === 'function' ? DOMMatrix : WebKitCSSMatrix)(
value + '',
)
return m.isIdentity ? identity$2 : decompose(m.a, m.b, m.c, m.d, m.e, m.f)
}
function parseSvg(value) {
if (value == null) return identity$2
if (!svgNode)
svgNode = document.createElementNS('http://www.w3.org/2000/svg', 'g')
svgNode.setAttribute('transform', value)
if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2
value = value.matrix
return decompose(value.a, value.b, value.c, value.d, value.e, value.f)
}
function interpolateTransform(parse, pxComma, pxParen, degParen) {
function pop(s) {
return s.length ? s.pop() + ' ' : ''
}
function translate(xa, ya, xb, yb, s, q) {
if (xa !== xb || ya !== yb) {
var i = s.push('translate(', null, pxComma, null, pxParen)
q.push(
{ i: i - 4, x: interpolateNumber(xa, xb) },
{ i: i - 2, x: interpolateNumber(ya, yb) },
)
} else if (xb || yb) {
s.push('translate(' + xb + pxComma + yb + pxParen)
}
}
function rotate(a, b, s, q) {
if (a !== b) {
if (a - b > 180) b += 360
else if (b - a > 180) a += 360 // shortest path
q.push({
i: s.push(pop(s) + 'rotate(', null, degParen) - 2,
x: interpolateNumber(a, b),
})
} else if (b) {
s.push(pop(s) + 'rotate(' + b + degParen)
}
}
function skewX(a, b, s, q) {
if (a !== b) {
q.push({
i: s.push(pop(s) + 'skewX(', null, degParen) - 2,
x: interpolateNumber(a, b),
})
} else if (b) {
s.push(pop(s) + 'skewX(' + b + degParen)
}
}
function scale(xa, ya, xb, yb, s, q) {
if (xa !== xb || ya !== yb) {
var i = s.push(pop(s) + 'scale(', null, ',', null, ')')
q.push(
{ i: i - 4, x: interpolateNumber(xa, xb) },
{ i: i - 2, x: interpolateNumber(ya, yb) },
)
} else if (xb !== 1 || yb !== 1) {
s.push(pop(s) + 'scale(' + xb + ',' + yb + ')')
}
}
return function (a, b) {
var s = [], // string constants and placeholders
q = [] // number interpolators
;(a = parse(a)), (b = parse(b))
translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q)
rotate(a.rotate, b.rotate, s, q)
skewX(a.skewX, b.skewX, s, q)
scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q)
a = b = null // gc
return function (t) {
var i = -1,
n = q.length,
o
while (++i < n) s[(o = q[i]).i] = o.x(t)
return s.join('')
}
}
}
var interpolateTransformCss = interpolateTransform(
parseCss,
'px, ',
'px)',
'deg)',
)
var interpolateTransformSvg = interpolateTransform(parseSvg, ', ', ')', ')')
var frame = 0, // is an animation frame pending?
timeout$1 = 0, // is a timeout pending?
interval = 0, // are any timers active?
pokeDelay = 1000, // how frequently we check for clock skew
taskHead,
taskTail,
clockLast = 0,
clockNow = 0,
clockSkew = 0,
clock =
typeof performance === 'object' && performance.now ? performance : Date,
setFrame =
typeof window === 'object' && window.requestAnimationFrame
? window.requestAnimationFrame.bind(window)
: function (f) {
setTimeout(f, 17)
}
function now() {
return clockNow || (setFrame(clearNow), (clockNow = clock.now() + clockSkew))
}
function clearNow() {
clockNow = 0
}
function Timer() {
this._call = this._time = this._next = null
}
Timer.prototype = timer.prototype = {
constructor: Timer,
restart: function (callback, delay, time) {
if (typeof callback !== 'function')
throw new TypeError('callback is not a function')
time = (time == null ? now() : +time) + (delay == null ? 0 : +delay)
if (!this._next && taskTail !== this) {
if (taskTail) taskTail._next = this
else taskHead = this
taskTail = this
}
this._call = callback
this._time = time
sleep()
},
stop: function () {
if (this._call) {
this._call = null
this._time = Infinity
sleep()
}
},
}
function timer(callback, delay, time) {
var t = new Timer()
t.restart(callback, delay, time)
return t
}
function timerFlush() {
now() // Get the current time, if not already set.
++frame // Pretend we’ve set an alarm, if we haven’t already.
var t = taskHead,
e
while (t) {
if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e)
t = t._next
}
--frame
}
function wake() {
clockNow = (clockLast = clock.now()) + clockSkew
frame = timeout$1 = 0
try {
timerFlush()
} finally {
frame = 0
nap()
clockNow = 0
}
}
function poke() {
var now = clock.now(),
delay = now - clockLast
if (delay > pokeDelay) (clockSkew -= delay), (clockLast = now)
}
function nap() {
var t0,
t1 = taskHead,
t2,
time = Infinity
while (t1) {
if (t1._call) {
if (time > t1._time) time = t1._time
;(t0 = t1), (t1 = t1._next)
} else {
;(t2 = t1._next), (t1._next = null)
t1 = t0 ? (t0._next = t2) : (taskHead = t2)
}
}
taskTail = t0
sleep(time)
}
function sleep(time) {
if (frame) return // Soonest alarm already set, or will be.
if (timeout$1) timeout$1 = clearTimeout(timeout$1)
var delay = time - clockNow // Strictly less than if we recomputed clockNow.
if (delay > 24) {
if (time < Infinity)
timeout$1 = setTimeout(wake, time - clock.now() - clockSkew)
if (interval) interval = clearInterval(interval)
} else {
if (!interval)
(clockLast = clock.now()), (interval = setInterval(poke, pokeDelay))
;(frame = 1), setFrame(wake)
}
}
function timeout(callback, delay, time) {
var t = new Timer()
delay = delay == null ? 0 : +delay
t.restart(
(elapsed) => {
t.stop()
callback(elapsed + delay)
},
delay,
time,
)
return t
}
var emptyOn = dispatch('start', 'end', 'cancel', 'interrupt')
var emptyTween = []
var CREATED = 0
var SCHEDULED = 1
var STARTING = 2
var STARTED = 3
var RUNNING = 4
var ENDING = 5
var ENDED = 6
function schedule(node, name, id, index, group, timing) {
var schedules = node.__transition
if (!schedules) node.__transition = {}
else if (id in schedules) return
create(node, id, {
name: name,
index: index, // For context during callback.
group: group, // For context during callback.
on: emptyOn,
tween: emptyTween,
time: timing.time,
delay: timing.delay,
duration: timing.duration,
ease: timing.ease,
timer: null,
state: CREATED,
})
}
function init(node, id) {
var schedule = get(node, id)
if (schedule.state > CREATED) throw new Error('too late; already scheduled')
return schedule
}
function set(node, id) {
var schedule = get(node, id)
if (schedule.state > STARTED) throw new Error('too late; already running')
return schedule
}
function get(node, id) {
var schedule = node.__transition
if (!schedule || !(schedule = schedule[id]))
throw new Error('transition not found')
return schedule
}
function create(node, id, self) {
var schedules = node.__transition,
tween
// Initialize the self timer when the transition is created.
// Note the actual delay is not known until the first callback!
schedules[id] = self
self.timer = timer(schedule, 0, self.time)
function schedule(elapsed) {
self.state = SCHEDULED
self.timer.restart(start, self.delay, self.time)
// If the elapsed delay is less than our first sleep, start immediately.
if (self.delay <= elapsed) start(elapsed - self.delay)
}
function start(elapsed) {
var i, j, n, o
// If the state is not SCHEDULED, then we previously errored on start.
if (self.state !== SCHEDULED) return stop()
for (i in schedules) {
o = schedules[i]
if (o.name !== self.name) continue
// While this element already has a starting transition during this frame,
// defer starting an interrupting transition until that transition has a
// chance to tick (and possibly end); see d3/d3-transition#54!
if (o.state === STARTED) return timeout(start)
// Interrupt the active transition, if any.
if (o.state === RUNNING) {
o.state = ENDED
o.timer.stop()
o.on.call('interrupt', node, node.__data__, o.index, o.group)
delete schedules[i]
}
// Cancel any pre-empted transitions.
else if (+i < id) {
o.state = ENDED
o.timer.stop()
o.on.call('cancel', node, node.__data__, o.index, o.group)
delete schedules[i]
}
}
// Defer the first tick to end of the current frame; see d3/d3#1576.
// Note the transition may be canceled after start and before the first tick!
// Note this must be scheduled before the start event; see d3/d3-transition#16!
// Assuming this is successful, subsequent callbacks go straight to tick.
timeout(function () {
if (self.state === STARTED) {
self.state = RUNNING
self.timer.restart(tick, self.delay, self.time)
tick(elapsed)
}
})
// Dispatch the start event.
// Note this must be done before the tween are initialized.
self.state = STARTING
self.on.call('start', node, node.__data__, self.index, self.group)
if (self.state !== STARTING) return // interrupted
self.state = STARTED
// Initialize the tween, deleting null tween.
tween = new Array((n = self.tween.length))
for (i = 0, j = -1; i < n; ++i) {
if (
(o = self.tween[i].value.call(
node,
node.__data__,
self.index,
self.group,
))
) {
tween[++j] = o
}
}
tween.length = j + 1
}
function tick(elapsed) {
var t =
elapsed < self.duration
? self.ease.call(null, elapsed / self.duration)
: (self.timer.restart(stop), (self.state = ENDING), 1),
i = -1,
n = tween.length
while (++i < n) {
tween[i].call(node, t)
}
// Dispatch the end event.
if (self.state === ENDING) {
self.on.call('end', node, node.__data__, self.index, self.group)
stop()
}
}
function stop() {
self.state = ENDED
self.timer.stop()
delete schedules[id]
for (var i in schedules) return // eslint-disable-line no-unused-vars
delete node.__transition
}
}
function interrupt(node, name) {
var schedules = node.__transition,
schedule,
active,
empty = true,
i
if (!schedules) return
name = name == null ? null : name + ''
for (i in schedules) {
if ((schedule = schedules[i]).name !== name) {
empty = false
continue
}
active = schedule.state > STARTING && schedule.state < ENDING
schedule.state = ENDED
schedule.timer.stop()
schedule.on.call(
active ? 'interrupt' : 'cancel',
node,
node.__data__,
schedule.index,
schedule.group,
)
delete schedules[i]
}
if (empty) delete node.__transition
}
function selection_interrupt(name) {
return this.each(function () {
interrupt(this, name)
})
}
function tweenRemove(id, name) {
var tween0, tween1
return function () {
var schedule = set(this, id),
tween = schedule.tween
// If this node shared tween with the previous node,
// just assign the updated shared tween and we’re done!
// Otherwise, copy-on-write.
if (tween !== tween0) {
tween1 = tween0 = tween
for (var i = 0, n = tween1.length; i < n; ++i) {
if (tween1[i].name === name) {
tween1 = tween1.slice()
tween1.splice(i, 1)
break
}
}
}
schedule.tween = tween1
}
}
function tweenFunction(id, name, value) {
var tween0, tween1
if (typeof value !== 'function') throw new Error()
return function () {
var schedule = set(this, id),
tween = schedule.tween
// If this node shared tween with the previous node,
// just assign the updated shared tween and we’re done!
// Otherwise, copy-on-write.
if (tween !== tween0) {
tween1 = (tween0 = tween).slice()
for (
var t = { name: name, value: value }, i = 0, n = tween1.length;
i < n;
++i
) {
if (tween1[i].name === name) {
tween1[i] = t
break
}
}
if (i === n) tween1.push(t)
}
schedule.tween = tween1
}
}
function transition_tween(name, value) {
var id = this._id
name += ''
if (arguments.length < 2) {
var tween = get(this.node(), id).tween
for (var i = 0, n = tween.length, t; i < n; ++i) {
if ((t = tween[i]).name === name) {
return t.value
}
}
return null
}
return this.each(
(value == null ? tweenRemove : tweenFunction)(id, name, value),
)
}
function tweenValue(transition, name, value) {
var id = transition._id
transition.each(function () {
var schedule = set(this, id)
;(schedule.value || (schedule.value = {}))[name] = value.apply(
this,
arguments,
)
})
return function (node) {
return get(node, id).value[name]
}
}
function interpolate(a, b) {
var c
return (
typeof b === 'number'
? interpolateNumber
: b instanceof color
? interpolateRgb
: (c = color(b))
? ((b = c), interpolateRgb)
: interpolateString
)(a, b)
}
function attrRemove(name) {
return function () {
this.removeAttribute(name)
}
}
function attrRemoveNS(fullname) {
return function () {
this.removeAttributeNS(fullname.space, fullname.local)
}
}
function attrConstant(name, interpolate, value1) {
var string00,
string1 = value1 + '',
interpolate0
return function () {
var string0 = this.getAttribute(name)
return string0 === string1
? null
: string0 === string00
? interpolate0
: (interpolate0 = interpolate((string00 = string0), value1))
}
}
function attrConstantNS(fullname, interpolate, value1) {
var string00,
string1 = value1 + '',
interpolate0
return function () {
var string0 = this.getAttributeNS(fullname.space, fullname.local)
return string0 === string1
? null
: string0 === string00
? interpolate0
: (interpolate0 = interpolate((string00 = string0), value1))
}
}
function attrFunction(name, interpolate, value) {
var string00, string10, interpolate0
return function () {
var string0,
value1 = value(this),
string1
if (value1 == null) return void this.removeAttribute(name)
string0 = this.getAttribute(name)
string1 = value1 + ''
return string0 === string1
? null
: string0 === string00 && string1 === string10
? interpolate0
: ((string10 = string1),
(interpolate0 = interpolate((string00 = string0), value1)))
}
}
function attrFunctionNS(fullname, interpolate, value) {
var string00, string10, interpolate0
return function () {
var string0,
value1 = value(this),
string1
if (value1 == null)
return void this.removeAttributeNS(fullname.space, fullname.local)
string0 = this.getAttributeNS(fullname.space, fullname.local)
string1 = value1 + ''
return string0 === string1
? null
: string0 === string00 && string1 === string10
? interpolate0
: ((string10 = string1),
(interpolate0 = interpolate((string00 = string0), value1)))
}
}
function transition_attr(name, value) {
var fullname = namespace(name),
i = fullname === 'transform' ? interpolateTransformSvg : interpolate
return this.attrTween(
name,
typeof value === 'function'
? (fullname.local ? attrFunctionNS : attrFunction)(
fullname,
i,
tweenValue(this, 'attr.' + name, value),
)
: value == null
? (fullname.local ? attrRemoveNS : attrRemove)(fullname)
: (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value),
)
}
function attrInterpolate(name, i) {
return function (t) {
this.setAttribute(name, i.call(this, t))
}
}
function attrInterpolateNS(fullname, i) {
return function (t) {
this.setAttributeNS(fullname.space, fullname.local, i.call(this, t))
}
}
function attrTweenNS(fullname, value) {
var t0, i0
function tween() {
var i = value.apply(this, arguments)
if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i)
return t0
}
tween._value = value
return tween
}
function attrTween(name, value) {
var t0, i0
function tween() {
var i = value.apply(this, arguments)
if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i)
return t0
}
tween._value = value
return tween
}
function transition_attrTween(name, value) {
var key = 'attr.' + name
if (arguments.length < 2) return (key = this.tween(key)) && key._value
if (value == null) return this.tween(key, null)
if (typeof value !== 'function') throw new Error()
var fullname = namespace(name)
return this.tween(
key,
(fullname.local ? attrTweenNS : attrTween)(fullname, value),
)
}
function delayFunction(id, value) {
return function () {
init(this, id).delay = +value.apply(this, arguments)
}
}
function delayConstant(id, value) {
return (
(value = +value),
function () {
init(this, id).delay = value
}
)
}
function transition_delay(value) {
var id = this._id
return arguments.length
? this.each(
(typeof value === 'function' ? delayFunction : delayConstant)(
id,
value,
),
)
: get(this.node(), id).delay
}
function durationFunction(id, value) {
return function () {
set(this, id).duration = +value.apply(this, arguments)
}
}
function durationConstant(id, value) {
return (
(value = +value),
function () {
set(this, id).duration = value
}
)
}
function transition_duration(value) {
var id = this._id
return arguments.length
? this.each(
(typeof value === 'function' ? durationFunction : durationConstant)(
id,
value,
),
)
: get(this.node(), id).duration
}
function easeConstant(id, value) {
if (typeof value !== 'function') throw new Error()
return function () {
set(this, id).ease = value
}
}
function transition_ease(value) {
var id = this._id
return arguments.length
? this.each(easeConstant(id, value))
: get(this.node(), id).ease
}
function easeVarying(id, value) {
return function () {
var v = value.apply(this, arguments)
if (typeof v !== 'function') throw new Error()
set(this, id).ease = v
}
}
function transition_easeVarying(value) {
if (typeof value !== 'function') throw new Error()
return this.each(easeVarying(this._id, value))
}
function transition_filter(match) {
if (typeof match !== 'function') match = matcher(match)
for (
var groups = this._groups,
m = groups.length,
subgroups = new Array(m),
j = 0;
j < m;
++j
) {
for (
var group = groups[j],
n = group.length,
subgroup = (subgroups[j] = []),
node,
i = 0;
i < n;
++i
) {
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
subgroup.push(node)
}
}
}
return new Transition(subgroups, this._parents, this._name, this._id)
}
function transition_merge(transition) {
if (transition._id !== this._id) throw new Error()
for (
var groups0 = this._groups,
groups1 = transition._groups,
m0 = groups0.length,
m1 = groups1.length,
m = Math.min(m0, m1),
merges = new Array(m0),
j = 0;
j < m;
++j
) {
for (
var group0 = groups0[j],
group1 = groups1[j],
n = group0.length,
merge = (merges[j] = new Array(n)),
node,
i = 0;
i < n;
++i
) {
if ((node = group0[i] || group1[i])) {
merge[i] = node
}
}
}
for (; j < m0; ++j) {
merges[j] = groups0[j]
}
return new Transition(merges, this._parents, this._name, this._id)
}
function start(name) {
return (name + '')
.trim()
.split(/^|\s+/)
.every(function (t) {
var i = t.indexOf('.')
if (i >= 0) t = t.slice(0, i)
return !t || t === 'start'
})
}
function onFunction(id, name, listener) {
var on0,
on1,
sit = start(name) ? init : set
return function () {
var schedule = sit(this, id),
on = schedule.on
// If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and we’re done!
// Otherwise, copy-on-write.
if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener)
schedule.on = on1
}
}
function transition_on(name, listener) {
var id = this._id
return arguments.length < 2
? get(this.node(), id).on.on(name)
: this.each(onFunction(id, name, listener))
}
function removeFunction(id) {
return function () {
var parent = this.parentNode
for (var i in this.__transition) if (+i !== id) return
if (parent) parent.removeChild(this)
}
}
function transition_remove() {
return this.on('end.remove', removeFunction(this._id))
}
function transition_select(select) {
var name = this._name,
id = this._id
if (typeof select !== 'function') select = selector(select)
for (
var groups = this._groups,
m = groups.length,
subgroups = new Array(m),
j = 0;
j < m;
++j
) {
for (
var group = groups[j],
n = group.length,
subgroup = (subgroups[j] = new Array(n)),
node,
subnode,
i = 0;
i < n;
++i
) {
if (
(node = group[i]) &&
(subnode = select.call(node, node.__data__, i, group))
) {
if ('__data__' in node) subnode.__data__ = node.__data__
subgroup[i] = subnode
schedule(subgroup[i], name, id, i, subgroup, get(node, id))
}
}
}
return new Transition(subgroups, this._parents, name, id)
}
function transition_selectAll(select) {
var name = this._name,
id = this._id
if (typeof select !== 'function') select = selectorAll(select)
for (
var groups = this._groups,
m = groups.length,
subgroups = [],
parents = [],
j = 0;
j < m;
++j
) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if ((node = group[i])) {
for (
var children = select.call(node, node.__data__, i, group),
child,
inherit = get(node, id),
k = 0,
l = children.length;
k < l;
++k
) {
if ((child = children[k])) {
schedule(child, name, id, k, children, inherit)
}
}
subgroups.push(children)
parents.push(node)
}
}
}
return new Transition(subgroups, parents, name, id)
}
var Selection = selection.prototype.constructor
function transition_selection() {
return new Selection(this._groups, this._parents)
}
function styleNull(name, interpolate) {
var string00, string10, interpolate0
return function () {
var string0 = styleValue(this, name),
string1 = (this.style.removeProperty(name), styleValue(this, name))
return string0 === string1
? null
: string0 === string00 && string1 === string10
? interpolate0
: (interpolate0 = interpolate(
(string00 = string0),
(string10 = string1),
))
}
}
function styleRemove(name) {
return function () {
this.style.removeProperty(name)
}
}
function styleConstant(name, interpolate, value1) {
var string00,
string1 = value1 + '',
interpolate0
return function () {
var string0 = styleValue(this, name)
return string0 === string1
? null
: string0 === string00
? interpolate0
: (interpolate0 = interpolate((string00 = string0), value1))
}
}
function styleFunction(name, interpolate, value) {
var string00, string10, interpolate0
return function () {
var string0 = styleValue(this, name),
value1 = value(this),
string1 = value1 + ''
if (value1 == null)
string1 = value1 =
(this.style.removeProperty(name), styleValue(this, name))
return string0 === string1
? null
: string0 === string00 && string1 === string10
? interpolate0
: ((string10 = string1),
(interpolate0 = interpolate((string00 = string0), value1)))
}
}
function styleMaybeRemove(id, name) {
var on0,
on1,
listener0,
key = 'style.' + name,
event = 'end.' + key,
remove
return function () {
var schedule = set(this, id),
on = schedule.on,
listener =
schedule.value[key] == null
? remove || (remove = styleRemove(name))
: undefined
// If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and we’re done!
// Otherwise, copy-on-write.
if (on !== on0 || listener0 !== listener)
(on1 = (on0 = on).copy()).on(event, (listener0 = listener))
schedule.on = on1
}
}
function transition_style(name, value, priority) {
var i = (name += '') === 'transform' ? interpolateTransformCss : interpolate
return value == null
? this.styleTween(name, styleNull(name, i)).on(
'end.style.' + name,
styleRemove(name),
)
: typeof value === 'function'
? this.styleTween(
name,
styleFunction(name, i, tweenValue(this, 'style.' + name, value)),
).each(styleMaybeRemove(this._id, name))
: this.styleTween(name, styleConstant(name, i, value), priority).on(
'end.style.' + name,
null,
)
}
function styleInterpolate(name, i, priority) {
return function (t) {
this.style.setProperty(name, i.call(this, t), priority)
}
}
function styleTween(name, value, priority) {
var t, i0
function tween() {
var i = value.apply(this, arguments)
if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority)
return t
}
tween._value = value
return tween
}
function transition_styleTween(name, value, priority) {
var key = 'style.' + (name += '')
if (arguments.length < 2) return (key = this.tween(key)) && key._value
if (value == null) return this.tween(key, null)
if (typeof value !== 'function') throw new Error()
return this.tween(
key,
styleTween(name, value, priority == null ? '' : priority),
)
}
function textConstant(value) {
return function () {
this.textContent = value
}
}
function textFunction(value) {
return function () {
var value1 = value(this)
this.textContent = value1 == null ? '' : value1
}
}
function transition_text(value) {
return this.tween(
'text',
typeof value === 'function'
? textFunction(tweenValue(this, 'text', value))
: textConstant(value == null ? '' : value + ''),
)
}
function textInterpolate(i) {
return function (t) {
this.textContent = i.call(this, t)
}
}
function textTween(value) {
var t0, i0
function tween() {
var i = value.apply(this, arguments)
if (i !== i0) t0 = (i0 = i) && textInterpolate(i)
return t0
}
tween._value = value
return tween
}
function transition_textTween(value) {
var key = 'text'
if (arguments.length < 1) return (key = this.tween(key)) && key._value
if (value == null) return this.tween(key, null)
if (typeof value !== 'function') throw new Error()
return this.tween(key, textTween(value))
}
function transition_transition() {
var name = this._name,
id0 = this._id,
id1 = newId()
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if ((node = group[i])) {
var inherit = get(node, id0)
schedule(node, name, id1, i, group, {
time: inherit.time + inherit.delay + inherit.duration,
delay: 0,
duration: inherit.duration,
ease: inherit.ease,
})
}
}
}
return new Transition(groups, this._parents, name, id1)
}
function transition_end() {
var on0,
on1,
that = this,
id = that._id,
size = that.size()
return new Promise(function (resolve, reject) {
var cancel = { value: reject },
end = {
value: function () {
if (--size === 0) resolve()
},
}
that.each(function () {
var schedule = set(this, id),
on = schedule.on
// If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and we’re done!
// Otherwise, copy-on-write.
if (on !== on0) {
on1 = (on0 = on).copy()
on1._.cancel.push(cancel)
on1._.interrupt.push(cancel)
on1._.end.push(end)
}
schedule.on = on1
})
// The selection was empty, resolve end immediately
if (size === 0) resolve()
})
}
var id = 0
function Transition(groups, parents, name, id) {
this._groups = groups
this._parents = parents
this._name = name
this._id = id
}
function newId() {
return ++id
}
var selection_prototype = selection.prototype
Transition.prototype = {
constructor: Transition,
select: transition_select,
selectAll: transition_selectAll,
selectChild: selection_prototype.selectChild,
selectChildren: selection_prototype.selectChildren,
filter: transition_filter,
merge: transition_merge,
selection: transition_selection,
transition: transition_transition,
call: selection_prototype.call,
nodes: selection_prototype.nodes,
node: selection_prototype.node,
size: selection_prototype.size,
empty: selection_prototype.empty,
each: selection_prototype.each,
on: transition_on,
attr: transition_attr,
attrTween: transition_attrTween,
style: transition_style,
styleTween: transition_styleTween,
text: transition_text,
textTween: transition_textTween,
remove: transition_remove,
tween: transition_tween,
delay: transition_delay,
duration: transition_duration,
ease: transition_ease,
easeVarying: transition_easeVarying,
end: transition_end,
[Symbol.iterator]: selection_prototype[Symbol.iterator],
}
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2
}
var defaultTiming = {
time: null, // Set on use.
delay: 0,
duration: 250,
ease: cubicInOut,
}
function inherit(node, id) {
var timing
while (!(timing = node.__transition) || !(timing = timing[id])) {
if (!(node = node.parentNode)) {
throw new Error(`transition ${id} not found`)
}
}
return timing
}
function selection_transition(name) {
var id, timing
if (name instanceof Transition) {
;(id = name._id), (name = name._name)
} else {
;(id = newId()),
((timing = defaultTiming).time = now()),
(name = name == null ? null : name + '')
}
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if ((node = group[i])) {
schedule(node, name, id, i, group, timing || inherit(node, id))
}
}
}
return new Transition(groups, this._parents, name, id)
}
selection.prototype.interrupt = selection_interrupt
selection.prototype.transition = selection_transition
function center(x, y) {
var nodes,
strength = 1
if (x == null) x = 0
if (y == null) y = 0
function force() {
var i,
n = nodes.length,
node,
sx = 0,
sy = 0
for (i = 0; i < n; ++i) {
;(node = nodes[i]), (sx += node.x), (sy += node.y)
}
for (
sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, i = 0;
i < n;
++i
) {
;(node = nodes[i]), (node.x -= sx), (node.y -= sy)
}
}
force.initialize = function (_) {
nodes = _
}
force.x = function (_) {
return arguments.length ? ((x = +_), force) : x
}
force.y = function (_) {
return arguments.length ? ((y = +_), force) : y
}
force.strength = function (_) {
return arguments.length ? ((strength = +_), force) : strength
}
return force
}
function tree_add(d) {
const x = +this._x.call(null, d),
y = +this._y.call(null, d)
return add(this.cover(x, y), x, y, d)
}
function add(tree, x, y, d) {
if (isNaN(x) || isNaN(y)) return tree // ignore invalid points
var parent,
node = tree._root,
leaf = { data: d },
x0 = tree._x0,
y0 = tree._y0,
x1 = tree._x1,
y1 = tree._y1,
xm,
ym,
xp,
yp,
right,
bottom,
i,
j
// If the tree is empty, initialize the root as a leaf.
if (!node) return (tree._root = leaf), tree
// Find the existing leaf for the new point, or add it.
while (node.length) {
if ((right = x >= (xm = (x0 + x1) / 2))) x0 = xm
else x1 = xm
if ((bottom = y >= (ym = (y0 + y1) / 2))) y0 = ym
else y1 = ym
if (((parent = node), !(node = node[(i = (bottom << 1) | right)])))
return (parent[i] = leaf), tree
}
// Is the new point is exactly coincident with the existing point?
xp = +tree._x.call(null, node.data)
yp = +tree._y.call(null, node.data)
if (x === xp && y === yp)
return (
(leaf.next = node),
parent ? (parent[i] = leaf) : (tree._root = leaf),
tree
)
// Otherwise, split the leaf node until the old and new point are separated.
do {
parent = parent ? (parent[i] = new Array(4)) : (tree._root = new Array(4))
if ((right = x >= (xm = (x0 + x1) / 2))) x0 = xm
else x1 = xm
if ((bottom = y >= (ym = (y0 + y1) / 2))) y0 = ym
else y1 = ym
} while ((i = (bottom << 1) | right) === (j = ((yp >= ym) << 1) | (xp >= xm)))
return (parent[j] = node), (parent[i] = leaf), tree
}
function addAll(data) {
var d,
i,
n = data.length,
x,
y,
xz = new Array(n),
yz = new Array(n),
x0 = Infinity,
y0 = Infinity,
x1 = -Infinity,
y1 = -Infinity
// Compute the points and their extent.
for (i = 0; i < n; ++i) {
if (
isNaN((x = +this._x.call(null, (d = data[i])))) ||
isNaN((y = +this._y.call(null, d)))
)
continue
xz[i] = x
yz[i] = y
if (x < x0) x0 = x
if (x > x1) x1 = x
if (y < y0) y0 = y
if (y > y1) y1 = y
}
// If there were no (valid) points, abort.
if (x0 > x1 || y0 > y1) return this
// Expand the tree to cover the new points.
this.cover(x0, y0).cover(x1, y1)
// Add the new points.
for (i = 0; i < n; ++i) {
add(this, xz[i], yz[i], data[i])
}
return this
}
function tree_cover(x, y) {
if (isNaN((x = +x)) || isNaN((y = +y))) return this // ignore invalid points
var x0 = this._x0,
y0 = this._y0,
x1 = this._x1,
y1 = this._y1
// If the quadtree has no extent, initialize them.
// Integer extent are necessary so that if we later double the extent,
// the existing quadrant boundaries don’t change due to floating point error!
if (isNaN(x0)) {
x1 = (x0 = Math.floor(x)) + 1
y1 = (y0 = Math.floor(y)) + 1
}
// Otherwise, double repeatedly to cover.
else {
var z = x1 - x0 || 1,
node = this._root,
parent,
i
while (x0 > x || x >= x1 || y0 > y || y >= y1) {
i = ((y < y0) << 1) | (x < x0)
;(parent = new Array(4)), (parent[i] = node), (node = parent), (z *= 2)
switch (i) {
case 0:
;(x1 = x0 + z), (y1 = y0 + z)
break
case 1:
;(x0 = x1 - z), (y1 = y0 + z)
break
case 2:
;(x1 = x0 + z), (y0 = y1 - z)
break
case 3:
;(x0 = x1 - z), (y0 = y1 - z)
break
}
}
if (this._root && this._root.length) this._root = node
}
this._x0 = x0
this._y0 = y0
this._x1 = x1
this._y1 = y1
return this
}
function tree_data() {
var data = []
this.visit(function (node) {
if (!node.length)
do data.push(node.data)
while ((node = node.next))
})
return data
}
function tree_extent(_) {
return arguments.length
? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
: isNaN(this._x0)
? undefined
: [
[this._x0, this._y0],
[this._x1, this._y1],
]
}
function Quad(node, x0, y0, x1, y1) {
this.node = node
this.x0 = x0
this.y0 = y0
this.x1 = x1
this.y1 = y1
}
function tree_find(x, y, radius) {
var data,
x0 = this._x0,
y0 = this._y0,
x1,
y1,
x2,
y2,
x3 = this._x1,
y3 = this._y1,
quads = [],
node = this._root,
q,
i
if (node) quads.push(new Quad(node, x0, y0, x3, y3))
if (radius == null) radius = Infinity
else {
;(x0 = x - radius), (y0 = y - radius)
;(x3 = x + radius), (y3 = y + radius)
radius *= radius
}
while ((q = quads.pop())) {
// Stop searching if this quadrant can’t contain a closer node.
if (
!(node = q.node) ||
(x1 = q.x0) > x3 ||
(y1 = q.y0) > y3 ||
(x2 = q.x1) < x0 ||
(y2 = q.y1) < y0
)
continue
// Bisect the current quadrant.
if (node.length) {
var xm = (x1 + x2) / 2,
ym = (y1 + y2) / 2
quads.push(
new Quad(node[3], xm, ym, x2, y2),
new Quad(node[2], x1, ym, xm, y2),
new Quad(node[1], xm, y1, x2, ym),
new Quad(node[0], x1, y1, xm, ym),
)
// Visit the closest quadrant first.
if ((i = ((y >= ym) << 1) | (x >= xm))) {
q = quads[quads.length - 1]
quads[quads.length - 1] = quads[quads.length - 1 - i]
quads[quads.length - 1 - i] = q
}
}
// Visit this point. (Visiting coincident points isn’t necessary!)
else {
var dx = x - +this._x.call(null, node.data),
dy = y - +this._y.call(null, node.data),
d2 = dx * dx + dy * dy
if (d2 < radius) {
var d = Math.sqrt((radius = d2))
;(x0 = x - d), (y0 = y - d)
;(x3 = x + d), (y3 = y + d)
data = node.data
}
}
}
return data
}
function tree_remove(d) {
if (
isNaN((x = +this._x.call(null, d))) ||
isNaN((y = +this._y.call(null, d)))
)
return this // ignore invalid points
var parent,
node = this._root,
retainer,
previous,
next,
x0 = this._x0,
y0 = this._y0,
x1 = this._x1,
y1 = this._y1,
x,
y,
xm,
ym,
right,
bottom,
i,
j
// If the tree is empty, initialize the root as a leaf.
if (!node) return this
// Find the leaf node for the point.
// While descending, also retain the deepest parent with a non-removed sibling.
if (node.length)
while (true) {
if ((right = x >= (xm = (x0 + x1) / 2))) x0 = xm
else x1 = xm
if ((bottom = y >= (ym = (y0 + y1) / 2))) y0 = ym
else y1 = ym
if (!((parent = node), (node = node[(i = (bottom << 1) | right)])))
return this
if (!node.length) break
if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3])
(retainer = parent), (j = i)
}
// Find the point to remove.
while (node.data !== d)
if (!((previous = node), (node = node.next))) return this
if ((next = node.next)) delete node.next
// If there are multiple coincident points, remove just the point.
if (previous)
return next ? (previous.next = next) : delete previous.next, this
// If this is the root point, remove it.
if (!parent) return (this._root = next), this
// Remove this leaf.
next ? (parent[i] = next) : delete parent[i]
// If the parent now contains exactly one leaf, collapse superfluous parents.
if (
(node = parent[0] || parent[1] || parent[2] || parent[3]) &&
node === (parent[3] || parent[2] || parent[1] || parent[0]) &&
!node.length
) {
if (retainer) retainer[j] = node
else this._root = node
}
return this
}
function removeAll(data) {
for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i])
return this
}
function tree_root() {
return this._root
}
function tree_size() {
var size = 0
this.visit(function (node) {
if (!node.length)
do ++size
while ((node = node.next))
})
return size
}
function tree_visit(callback) {
var quads = [],
q,
node = this._root,
child,
x0,
y0,
x1,
y1
if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1))
while ((q = quads.pop())) {
if (
!callback(
(node = q.node),
(x0 = q.x0),
(y0 = q.y0),
(x1 = q.x1),
(y1 = q.y1),
) &&
node.length
) {
var xm = (x0 + x1) / 2,
ym = (y0 + y1) / 2
if ((child = node[3])) quads.push(new Quad(child, xm, ym, x1, y1))
if ((child = node[2])) quads.push(new Quad(child, x0, ym, xm, y1))
if ((child = node[1])) quads.push(new Quad(child, xm, y0, x1, ym))
if ((child = node[0])) quads.push(new Quad(child, x0, y0, xm, ym))
}
}
return this
}
function tree_visitAfter(callback) {
var quads = [],
next = [],
q
if (this._root)
quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1))
while ((q = quads.pop())) {
var node = q.node
if (node.length) {
var child,
x0 = q.x0,
y0 = q.y0,
x1 = q.x1,
y1 = q.y1,
xm = (x0 + x1) / 2,
ym = (y0 + y1) / 2
if ((child = node[0])) quads.push(new Quad(child, x0, y0, xm, ym))
if ((child = node[1])) quads.push(new Quad(child, xm, y0, x1, ym))
if ((child = node[2])) quads.push(new Quad(child, x0, ym, xm, y1))
if ((child = node[3])) quads.push(new Quad(child, xm, ym, x1, y1))
}
next.push(q)
}
while ((q = next.pop())) {
callback(q.node, q.x0, q.y0, q.x1, q.y1)
}
return this
}
function defaultX(d) {
return d[0]
}
function tree_x(_) {
return arguments.length ? ((this._x = _), this) : this._x
}
function defaultY(d) {
return d[1]
}
function tree_y(_) {
return arguments.length ? ((this._y = _), this) : this._y
}
function quadtree(nodes, x, y) {
var tree = new Quadtree(
x == null ? defaultX : x,
y == null ? defaultY : y,
NaN,
NaN,
NaN,
NaN,
)
return nodes == null ? tree : tree.addAll(nodes)
}
function Quadtree(x, y, x0, y0, x1, y1) {
this._x = x
this._y = y
this._x0 = x0
this._y0 = y0
this._x1 = x1
this._y1 = y1
this._root = undefined
}
function leaf_copy(leaf) {
var copy = { data: leaf.data },
next = copy
while ((leaf = leaf.next)) next = next.next = { data: leaf.data }
return copy
}
var treeProto = (quadtree.prototype = Quadtree.prototype)
treeProto.copy = function () {
var copy = new Quadtree(
this._x,
this._y,
this._x0,
this._y0,
this._x1,
this._y1,
),
node = this._root,
nodes,
child
if (!node) return copy
if (!node.length) return (copy._root = leaf_copy(node)), copy
nodes = [{ source: node, target: (copy._root = new Array(4)) }]
while ((node = nodes.pop())) {
for (var i = 0; i < 4; ++i) {
if ((child = node.source[i])) {
if (child.length)
nodes.push({ source: child, target: (node.target[i] = new Array(4)) })
else node.target[i] = leaf_copy(child)
}
}
}
return copy
}
treeProto.add = tree_add
treeProto.addAll = addAll
treeProto.cover = tree_cover
treeProto.data = tree_data
treeProto.extent = tree_extent
treeProto.find = tree_find
treeProto.remove = tree_remove
treeProto.removeAll = removeAll
treeProto.root = tree_root
treeProto.size = tree_size
treeProto.visit = tree_visit
treeProto.visitAfter = tree_visitAfter
treeProto.x = tree_x
treeProto.y = tree_y
function constant(x) {
return function () {
return x
}
}
function jiggle(random) {
return (random() - 0.5) * 1e-6
}
function index(d) {
return d.index
}
function find(nodeById, nodeId) {
var node = nodeById.get(nodeId)
if (!node) throw new Error('node not found: ' + nodeId)
return node
}
function link(links) {
var id = index,
strength = defaultStrength,
strengths,
distance = constant(30),
distances,
nodes,
count,
bias,
random,
iterations = 1
if (links == null) links = []
function defaultStrength(link) {
return 1 / Math.min(count[link.source.index], count[link.target.index])
}
function force(alpha) {
for (var k = 0, n = links.length; k < iterations; ++k) {
for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
;(link = links[i]), (source = link.source), (target = link.target)
x = target.x + target.vx - source.x - source.vx || jiggle(random)
y = target.y + target.vy - source.y - source.vy || jiggle(random)
l = Math.sqrt(x * x + y * y)
l = ((l - distances[i]) / l) * alpha * strengths[i]
;(x *= l), (y *= l)
target.vx -= x * (b = bias[i])
target.vy -= y * b
source.vx += x * (b = 1 - b)
source.vy += y * b
}
}
}
function initialize() {
if (!nodes) return
var i,
n = nodes.length,
m = links.length,
nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),
link
for (i = 0, count = new Array(n); i < m; ++i) {
;(link = links[i]), (link.index = i)
if (typeof link.source !== 'object')
link.source = find(nodeById, link.source)
if (typeof link.target !== 'object')
link.target = find(nodeById, link.target)
count[link.source.index] = (count[link.source.index] || 0) + 1
count[link.target.index] = (count[link.target.index] || 0) + 1
}
for (i = 0, bias = new Array(m); i < m; ++i) {
;(link = links[i]),
(bias[i] =
count[link.source.index] /
(count[link.source.index] + count[link.target.index]))
}
;(strengths = new Array(m)), initializeStrength()
;(distances = new Array(m)), initializeDistance()
}
function initializeStrength() {
if (!nodes) return
for (var i = 0, n = links.length; i < n; ++i) {
strengths[i] = +strength(links[i], i, links)
}
}
function initializeDistance() {
if (!nodes) return
for (var i = 0, n = links.length; i < n; ++i) {
distances[i] = +distance(links[i], i, links)
}
}
force.initialize = function (_nodes, _random) {
nodes = _nodes
random = _random
initialize()
}
force.links = function (_) {
return arguments.length ? ((links = _), initialize(), force) : links
}
force.id = function (_) {
return arguments.length ? ((id = _), force) : id
}
force.iterations = function (_) {
return arguments.length ? ((iterations = +_), force) : iterations
}
force.strength = function (_) {
return arguments.length
? ((strength = typeof _ === 'function' ? _ : constant(+_)),
initializeStrength(),
force)
: strength
}
force.distance = function (_) {
return arguments.length
? ((distance = typeof _ === 'function' ? _ : constant(+_)),
initializeDistance(),
force)
: distance
}
return force
}
// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
const a = 1664525
const c = 1013904223
const m = 4294967296 // 2^32
function lcg() {
let s = 1
return () => (s = (a * s + c) % m) / m
}
function x(d) {
return d.x
}
function y(d) {
return d.y
}
var initialRadius = 10,
initialAngle = Math.PI * (3 - Math.sqrt(5))
function simulation(nodes) {
var simulation,
alpha = 1,
alphaMin = 0.001,
alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
alphaTarget = 0,
velocityDecay = 0.6,
forces = new Map(),
stepper = timer(step),
event = dispatch('tick', 'end'),
random = lcg()
if (nodes == null) nodes = []
function step() {
tick()
event.call('tick', simulation)
if (alpha < alphaMin) {
stepper.stop()
event.call('end', simulation)
}
}
function tick(iterations) {
var i,
n = nodes.length,
node
if (iterations === undefined) iterations = 1
for (var k = 0; k < iterations; ++k) {
alpha += (alphaTarget - alpha) * alphaDecay
forces.forEach(function (force) {
force(alpha)
})
for (i = 0; i < n; ++i) {
node = nodes[i]
if (node.fx == null) node.x += node.vx *= velocityDecay
else (node.x = node.fx), (node.vx = 0)
if (node.fy == null) node.y += node.vy *= velocityDecay
else (node.y = node.fy), (node.vy = 0)
}
}
return simulation
}
function initializeNodes() {
for (var i = 0, n = nodes.length, node; i < n; ++i) {
;(node = nodes[i]), (node.index = i)
if (node.fx != null) node.x = node.fx
if (node.fy != null) node.y = node.fy
if (isNaN(node.x) || isNaN(node.y)) {
var radius = initialRadius * Math.sqrt(0.5 + i),
angle = i * initialAngle
node.x = radius * Math.cos(angle)
node.y = radius * Math.sin(angle)
}
if (isNaN(node.vx) || isNaN(node.vy)) {
node.vx = node.vy = 0
}
}
}
function initializeForce(force) {
if (force.initialize) force.initialize(nodes, random)
return force
}
initializeNodes()
return (simulation = {
tick: tick,
restart: function () {
return stepper.restart(step), simulation
},
stop: function () {
return stepper.stop(), simulation
},
nodes: function (_) {
return arguments.length
? ((nodes = _),
initializeNodes(),
forces.forEach(initializeForce),
simulation)
: nodes
},
alpha: function (_) {
return arguments.length ? ((alpha = +_), simulation) : alpha
},
alphaMin: function (_) {
return arguments.length ? ((alphaMin = +_), simulation) : alphaMin
},
alphaDecay: function (_) {
return arguments.length ? ((alphaDecay = +_), simulation) : +alphaDecay
},
alphaTarget: function (_) {
return arguments.length ? ((alphaTarget = +_), simulation) : alphaTarget
},
velocityDecay: function (_) {
return arguments.length
? ((velocityDecay = 1 - _), simulation)
: 1 - velocityDecay
},
randomSource: function (_) {
return arguments.length
? ((random = _), forces.forEach(initializeForce), simulation)
: random
},
force: function (name, _) {
return arguments.length > 1
? (_ == null
? forces.delete(name)
: forces.set(name, initializeForce(_)),
simulation)
: forces.get(name)
},
find: function (x, y, radius) {
var i = 0,
n = nodes.length,
dx,
dy,
d2,
node,
closest
if (radius == null) radius = Infinity
else radius *= radius
for (i = 0; i < n; ++i) {
node = nodes[i]
dx = x - node.x
dy = y - node.y
d2 = dx * dx + dy * dy
if (d2 < radius) (closest = node), (radius = d2)
}
return closest
},
on: function (name, _) {
return arguments.length > 1
? (event.on(name, _), simulation)
: event.on(name)
},
})
}
function manyBody() {
var nodes,
node,
random,
alpha,
strength = constant(-30),
strengths,
distanceMin2 = 1,
distanceMax2 = Infinity,
theta2 = 0.81
function force(_) {
var i,
n = nodes.length,
tree = quadtree(nodes, x, y).visitAfter(accumulate)
for (alpha = _, i = 0; i < n; ++i) (node = nodes[i]), tree.visit(apply)
}
function initialize() {
if (!nodes) return
var i,
n = nodes.length,
node
strengths = new Array(n)
for (i = 0; i < n; ++i)
(node = nodes[i]), (strengths[node.index] = +strength(node, i, nodes))
}
function accumulate(quad) {
var strength = 0,
q,
c,
weight = 0,
x,
y,
i
// For internal nodes, accumulate forces from child quadrants.
if (quad.length) {
for (x = y = i = 0; i < 4; ++i) {
if ((q = quad[i]) && (c = Math.abs(q.value))) {
;(strength += q.value), (weight += c), (x += c * q.x), (y += c * q.y)
}
}
quad.x = x / weight
quad.y = y / weight
}
// For leaf nodes, accumulate forces from coincident quadrants.
else {
q = quad
q.x = q.data.x
q.y = q.data.y
do strength += strengths[q.data.index]
while ((q = q.next))
}
quad.value = strength
}
function apply(quad, x1, _, x2) {
if (!quad.value) return true
var x = quad.x - node.x,
y = quad.y - node.y,
w = x2 - x1,
l = x * x + y * y
// Apply the Barnes-Hut approximation if possible.
// Limit forces for very close nodes; randomize direction if coincident.
if ((w * w) / theta2 < l) {
if (l < distanceMax2) {
if (x === 0) (x = jiggle(random)), (l += x * x)
if (y === 0) (y = jiggle(random)), (l += y * y)
if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l)
node.vx += (x * quad.value * alpha) / l
node.vy += (y * quad.value * alpha) / l
}
return true
}
// Otherwise, process points directly.
else if (quad.length || l >= distanceMax2) return
// Limit forces for very close nodes; randomize direction if coincident.
if (quad.data !== node || quad.next) {
if (x === 0) (x = jiggle(random)), (l += x * x)
if (y === 0) (y = jiggle(random)), (l += y * y)
if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l)
}
do
if (quad.data !== node) {
w = (strengths[quad.data.index] * alpha) / l
node.vx += x * w
node.vy += y * w
}
while ((quad = quad.next))
}
force.initialize = function (_nodes, _random) {
nodes = _nodes
random = _random
initialize()
}
force.strength = function (_) {
return arguments.length
? ((strength = typeof _ === 'function' ? _ : constant(+_)),
initialize(),
force)
: strength
}
force.distanceMin = function (_) {
return arguments.length
? ((distanceMin2 = _ * _), force)
: Math.sqrt(distanceMin2)
}
force.distanceMax = function (_) {
return arguments.length
? ((distanceMax2 = _ * _), force)
: Math.sqrt(distanceMax2)
}
force.theta = function (_) {
return arguments.length ? ((theta2 = _ * _), force) : Math.sqrt(theta2)
}
return force
}
function initRange(domain, range) {
switch (arguments.length) {
case 0:
break
case 1:
this.range(domain)
break
default:
this.range(range).domain(domain)
break
}
return this
}
const implicit = Symbol('implicit')
function ordinal() {
var index = new InternMap(),
domain = [],
range = [],
unknown = implicit
function scale(d) {
let i = index.get(d)
if (i === undefined) {
if (unknown !== implicit) return unknown
index.set(d, (i = domain.push(d) - 1))
}
return range[i % range.length]
}
scale.domain = function (_) {
if (!arguments.length) return domain.slice()
;(domain = []), (index = new InternMap())
for (const value of _) {
if (index.has(value)) continue
index.set(value, domain.push(value) - 1)
}
return scale
}
scale.range = function (_) {
return arguments.length ? ((range = Array.from(_)), scale) : range.slice()
}
scale.unknown = function (_) {
return arguments.length ? ((unknown = _), scale) : unknown
}
scale.copy = function () {
return ordinal(domain, range).unknown(unknown)
}
initRange.apply(scale, arguments)
return scale
}
function colors(specifier) {
var n = (specifier.length / 6) | 0,
colors = new Array(n),
i = 0
while (i < n) colors[i] = '#' + specifier.slice(i * 6, ++i * 6)
return colors
}
var category10 = colors(
'1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf',
)
var Dark2 = colors('1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666')
function Transform(k, x, y) {
this.k = k
this.x = x
this.y = y
}
Transform.prototype = {
constructor: Transform,
scale: function (k) {
return k === 1 ? this : new Transform(this.k * k, this.x, this.y)
},
translate: function (x, y) {
return (x === 0) & (y === 0)
? this
: new Transform(this.k, this.x + this.k * x, this.y + this.k * y)
},
apply: function (point) {
return [point[0] * this.k + this.x, point[1] * this.k + this.y]
},
applyX: function (x) {
return x * this.k + this.x
},
applyY: function (y) {
return y * this.k + this.y
},
invert: function (location) {
return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]
},
invertX: function (x) {
return (x - this.x) / this.k
},
invertY: function (y) {
return (y - this.y) / this.k
},
rescaleX: function (x) {
return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x))
},
rescaleY: function (y) {
return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y))
},
toString: function () {
return 'translate(' + this.x + ',' + this.y + ') scale(' + this.k + ')'
},
}
Transform.prototype
function _isPlaceholder(a) {
return (
a != null && typeof a === 'object' && a['@@functional/placeholder'] === true
)
}
/**
* Optimized internal one-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
function _curry1(fn) {
return function f1(a) {
if (arguments.length === 0 || _isPlaceholder(a)) {
return f1
} else {
return fn.apply(this, arguments)
}
}
}
/**
* Optimized internal two-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
function _curry2(fn) {
return function f2(a, b) {
switch (arguments.length) {
case 0:
return f2
case 1:
return _isPlaceholder(a)
? f2
: _curry1(function (_b) {
return fn(a, _b)
})
default:
return _isPlaceholder(a) && _isPlaceholder(b)
? f2
: _isPlaceholder(a)
? _curry1(function (_a) {
return fn(_a, b)
})
: _isPlaceholder(b)
? _curry1(function (_b) {
return fn(a, _b)
})
: fn(a, b)
}
}
}
function _arity(n, fn) {
/* eslint-disable no-unused-vars */
switch (n) {
case 0:
return function () {
return fn.apply(this, arguments)
}
case 1:
return function (a0) {
return fn.apply(this, arguments)
}
case 2:
return function (a0, a1) {
return fn.apply(this, arguments)
}
case 3:
return function (a0, a1, a2) {
return fn.apply(this, arguments)
}
case 4:
return function (a0, a1, a2, a3) {
return fn.apply(this, arguments)
}
case 5:
return function (a0, a1, a2, a3, a4) {
return fn.apply(this, arguments)
}
case 6:
return function (a0, a1, a2, a3, a4, a5) {
return fn.apply(this, arguments)
}
case 7:
return function (a0, a1, a2, a3, a4, a5, a6) {
return fn.apply(this, arguments)
}
case 8:
return function (a0, a1, a2, a3, a4, a5, a6, a7) {
return fn.apply(this, arguments)
}
case 9:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
return fn.apply(this, arguments)
}
case 10:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
return fn.apply(this, arguments)
}
default:
throw new Error(
'First argument to _arity must be a non-negative integer no greater than ten',
)
}
}
/**
* Internal curryN function.
*
* @private
* @category Function
* @param {Number} length The arity of the curried function.
* @param {Array} received An array of arguments received thus far.
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
function _curryN(length, received, fn) {
return function () {
var combined = []
var argsIdx = 0
var left = length
var combinedIdx = 0
var hasPlaceholder = false
while (combinedIdx < received.length || argsIdx < arguments.length) {
var result
if (
combinedIdx < received.length &&
(!_isPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)
) {
result = received[combinedIdx]
} else {
result = arguments[argsIdx]
argsIdx += 1
}
combined[combinedIdx] = result
if (!_isPlaceholder(result)) {
left -= 1
} else {
hasPlaceholder = true
}
combinedIdx += 1
}
return !hasPlaceholder && left <= 0
? fn.apply(this, combined)
: _arity(Math.max(0, left), _curryN(length, combined, fn))
}
}
/**
* Returns a curried equivalent of the provided function, with the specified
* arity. The curried function has two unusual capabilities. First, its
* arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the
* following are equivalent:
*
* - `g(1)(2)(3)`
* - `g(1)(2, 3)`
* - `g(1, 2)(3)`
* - `g(1, 2, 3)`
*
* Secondly, the special placeholder value [`R.__`](#__) may be used to specify
* "gaps", allowing partial application of any combination of arguments,
* regardless of their positions. If `g` is as above and `_` is [`R.__`](#__),
* the following are equivalent:
*
* - `g(1, 2, 3)`
* - `g(_, 2, 3)(1)`
* - `g(_, _, 3)(1)(2)`
* - `g(_, _, 3)(1, 2)`
* - `g(_, 2)(1)(3)`
* - `g(_, 2)(1, 3)`
* - `g(_, 2)(_, 3)(1)`
*
* @func
* @memberOf R
* @since v0.5.0
* @category Function
* @sig Number -> (* -> a) -> (* -> a)
* @param {Number} length The arity for the returned function.
* @param {Function} fn The function to curry.
* @return {Function} A new, curried function.
* @see R.curry
* @example
*
* const sumArgs = (...args) => R.sum(args);
*
* const curriedAddFourNumbers = R.curryN(4, sumArgs);
* const f = curriedAddFourNumbers(1, 2);
* const g = f(3);
* g(4); //=> 10
*/
var curryN =
/*#__PURE__*/
_curry2(function curryN(length, fn) {
if (length === 1) {
return _curry1(fn)
}
return _arity(length, _curryN(length, [], fn))
})
/**
* Optimized internal three-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
function _curry3(fn) {
return function f3(a, b, c) {
switch (arguments.length) {
case 0:
return f3
case 1:
return _isPlaceholder(a)
? f3
: _curry2(function (_b, _c) {
return fn(a, _b, _c)
})
case 2:
return _isPlaceholder(a) && _isPlaceholder(b)
? f3
: _isPlaceholder(a)
? _curry2(function (_a, _c) {
return fn(_a, b, _c)
})
: _isPlaceholder(b)
? _curry2(function (_b, _c) {
return fn(a, _b, _c)
})
: _curry1(function (_c) {
return fn(a, b, _c)
})
default:
return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c)
? f3
: _isPlaceholder(a) && _isPlaceholder(b)
? _curry2(function (_a, _b) {
return fn(_a, _b, c)
})
: _isPlaceholder(a) && _isPlaceholder(c)
? _curry2(function (_a, _c) {
return fn(_a, b, _c)
})
: _isPlaceholder(b) && _isPlaceholder(c)
? _curry2(function (_b, _c) {
return fn(a, _b, _c)
})
: _isPlaceholder(a)
? _curry1(function (_a) {
return fn(_a, b, c)
})
: _isPlaceholder(b)
? _curry1(function (_b) {
return fn(a, _b, c)
})
: _isPlaceholder(c)
? _curry1(function (_c) {
return fn(a, b, _c)
})
: fn(a, b, c)
}
}
}
/**
* Tests whether or not an object is an array.
*
* @private
* @param {*} val The object to test.
* @return {Boolean} `true` if `val` is an array, `false` otherwise.
* @example
*
* _isArray([]); //=> true
* _isArray(null); //=> false
* _isArray({}); //=> false
*/
var _isArray =
Array.isArray ||
function _isArray(val) {
return (
val != null &&
val.length >= 0 &&
Object.prototype.toString.call(val) === '[object Array]'
)
}
function _isTransformer(obj) {
return obj != null && typeof obj['@@transducer/step'] === 'function'
}
/**
* Returns a function that dispatches with different strategies based on the
* object in list position (last argument). If it is an array, executes [fn].
* Otherwise, if it has a function with one of the given method names, it will
* execute that function (functor case). Otherwise, if it is a transformer,
* uses transducer created by [transducerCreator] to return a new transformer
* (transducer case).
* Otherwise, it will default to executing [fn].
*
* @private
* @param {Array} methodNames properties to check for a custom implementation
* @param {Function} transducerCreator transducer factory if object is transformer
* @param {Function} fn default ramda implementation
* @return {Function} A function that dispatches on object in list position
*/
function _dispatchable(methodNames, transducerCreator, fn) {
return function () {
if (arguments.length === 0) {
return fn()
}
var obj = arguments[arguments.length - 1]
if (!_isArray(obj)) {
var idx = 0
while (idx < methodNames.length) {
if (typeof obj[methodNames[idx]] === 'function') {
return obj[methodNames[idx]].apply(
obj,
Array.prototype.slice.call(arguments, 0, -1),
)
}
idx += 1
}
if (_isTransformer(obj)) {
var transducer = transducerCreator.apply(
null,
Array.prototype.slice.call(arguments, 0, -1),
)
return transducer(obj)
}
}
return fn.apply(this, arguments)
}
}
var _xfBase = {
init: function () {
return this.xf['@@transducer/init']()
},
result: function (result) {
return this.xf['@@transducer/result'](result)
},
}
function _arrayFromIterator(iter) {
var list = []
var next
while (!(next = iter.next()).done) {
list.push(next.value)
}
return list
}
function _includesWith(pred, x, list) {
var idx = 0
var len = list.length
while (idx < len) {
if (pred(x, list[idx])) {
return true
}
idx += 1
}
return false
}
function _functionName(f) {
// String(x => x) evaluates to "x => x", so the pattern may not match.
var match = String(f).match(/^function (\w*)/)
return match == null ? '' : match[1]
}
function _has(prop, obj) {
return Object.prototype.hasOwnProperty.call(obj, prop)
}
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
function _objectIs(a, b) {
// SameValue algorithm
if (a === b) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return a !== 0 || 1 / a === 1 / b
} else {
// Step 6.a: NaN == NaN
return a !== a && b !== b
}
}
var _objectIs$1 = typeof Object.is === 'function' ? Object.is : _objectIs
var toString = Object.prototype.toString
var _isArguments =
/*#__PURE__*/
(function () {
return toString.call(arguments) === '[object Arguments]'
? function _isArguments(x) {
return toString.call(x) === '[object Arguments]'
}
: function _isArguments(x) {
return _has('callee', x)
}
})()
var hasEnumBug = !(
/*#__PURE__*/
{
toString: null,
}.propertyIsEnumerable('toString')
)
var nonEnumerableProps = [
'constructor',
'valueOf',
'isPrototypeOf',
'toString',
'propertyIsEnumerable',
'hasOwnProperty',
'toLocaleString',
] // Safari bug
var hasArgsEnumBug =
/*#__PURE__*/
(function () {
return arguments.propertyIsEnumerable('length')
})()
var contains = function contains(list, item) {
var idx = 0
while (idx < list.length) {
if (list[idx] === item) {
return true
}
idx += 1
}
return false
}
/**
* Returns a list containing the names of all the enumerable own properties of
* the supplied object.
* Note that the order of the output array is not guaranteed to be consistent
* across different JS platforms.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig {k: v} -> [k]
* @param {Object} obj The object to extract properties from
* @return {Array} An array of the object's own properties.
* @see R.keysIn, R.values, R.toPairs
* @example
*
* R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
*/
var keys =
typeof Object.keys === 'function' && !hasArgsEnumBug
? /*#__PURE__*/
_curry1(function keys(obj) {
return Object(obj) !== obj ? [] : Object.keys(obj)
})
: /*#__PURE__*/
_curry1(function keys(obj) {
if (Object(obj) !== obj) {
return []
}
var prop, nIdx
var ks = []
var checkArgsLength = hasArgsEnumBug && _isArguments(obj)
for (prop in obj) {
if (_has(prop, obj) && (!checkArgsLength || prop !== 'length')) {
ks[ks.length] = prop
}
}
if (hasEnumBug) {
nIdx = nonEnumerableProps.length - 1
while (nIdx >= 0) {
prop = nonEnumerableProps[nIdx]
if (_has(prop, obj) && !contains(ks, prop)) {
ks[ks.length] = prop
}
nIdx -= 1
}
}
return ks
})
/**
* Gives a single-word string description of the (native) type of a value,
* returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not
* attempt to distinguish user Object types any further, reporting them all as
* 'Object'.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Type
* @sig * -> String
* @param {*} val The value to test
* @return {String}
* @example
*
* R.type({}); //=> "Object"
* R.type(1); //=> "Number"
* R.type(false); //=> "Boolean"
* R.type('s'); //=> "String"
* R.type(null); //=> "Null"
* R.type([]); //=> "Array"
* R.type(/[A-z]/); //=> "RegExp"
* R.type(() => {}); //=> "Function"
* R.type(async () => {}); //=> "AsyncFunction"
* R.type(undefined); //=> "Undefined"
*/
var type =
/*#__PURE__*/
_curry1(function type(val) {
return val === null
? 'Null'
: val === undefined
? 'Undefined'
: Object.prototype.toString.call(val).slice(8, -1)
})
/**
* private _uniqContentEquals function.
* That function is checking equality of 2 iterator contents with 2 assumptions
* - iterators lengths are the same
* - iterators values are unique
*
* false-positive result will be returned for comparison of, e.g.
* - [1,2,3] and [1,2,3,4]
* - [1,1,1] and [1,2,3]
* */
function _uniqContentEquals(aIterator, bIterator, stackA, stackB) {
var a = _arrayFromIterator(aIterator)
var b = _arrayFromIterator(bIterator)
function eq(_a, _b) {
return _equals(_a, _b, stackA.slice(), stackB.slice())
} // if *a* array contains any element that is not included in *b*
return !_includesWith(
function (b, aItem) {
return !_includesWith(eq, aItem, b)
},
b,
a,
)
}
function _equals(a, b, stackA, stackB) {
if (_objectIs$1(a, b)) {
return true
}
var typeA = type(a)
if (typeA !== type(b)) {
return false
}
if (
typeof a['fantasy-land/equals'] === 'function' ||
typeof b['fantasy-land/equals'] === 'function'
) {
return (
typeof a['fantasy-land/equals'] === 'function' &&
a['fantasy-land/equals'](b) &&
typeof b['fantasy-land/equals'] === 'function' &&
b['fantasy-land/equals'](a)
)
}
if (typeof a.equals === 'function' || typeof b.equals === 'function') {
return (
typeof a.equals === 'function' &&
a.equals(b) &&
typeof b.equals === 'function' &&
b.equals(a)
)
}
switch (typeA) {
case 'Arguments':
case 'Array':
case 'Object':
if (
typeof a.constructor === 'function' &&
_functionName(a.constructor) === 'Promise'
) {
return a === b
}
break
case 'Boolean':
case 'Number':
case 'String':
if (!(typeof a === typeof b && _objectIs$1(a.valueOf(), b.valueOf()))) {
return false
}
break
case 'Date':
if (!_objectIs$1(a.valueOf(), b.valueOf())) {
return false
}
break
case 'Error':
return a.name === b.name && a.message === b.message
case 'RegExp':
if (
!(
a.source === b.source &&
a.global === b.global &&
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline &&
a.sticky === b.sticky &&
a.unicode === b.unicode
)
) {
return false
}
break
}
var idx = stackA.length - 1
while (idx >= 0) {
if (stackA[idx] === a) {
return stackB[idx] === b
}
idx -= 1
}
switch (typeA) {
case 'Map':
if (a.size !== b.size) {
return false
}
return _uniqContentEquals(
a.entries(),
b.entries(),
stackA.concat([a]),
stackB.concat([b]),
)
case 'Set':
if (a.size !== b.size) {
return false
}
return _uniqContentEquals(
a.values(),
b.values(),
stackA.concat([a]),
stackB.concat([b]),
)
case 'Arguments':
case 'Array':
case 'Object':
case 'Boolean':
case 'Number':
case 'String':
case 'Date':
case 'Error':
case 'RegExp':
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
case 'ArrayBuffer':
break
default:
// Values of other types are only equal if identical.
return false
}
var keysA = keys(a)
if (keysA.length !== keys(b).length) {
return false
}
var extendedStackA = stackA.concat([a])
var extendedStackB = stackB.concat([b])
idx = keysA.length - 1
while (idx >= 0) {
var key = keysA[idx]
if (
!(_has(key, b) && _equals(b[key], a[key], extendedStackA, extendedStackB))
) {
return false
}
idx -= 1
}
return true
}
/**
* Returns `true` if its arguments are equivalent, `false` otherwise. Handles
* cyclical data structures.
*
* Dispatches symmetrically to the `equals` methods of both arguments, if
* present.
*
* @func
* @memberOf R
* @since v0.15.0
* @category Relation
* @sig a -> b -> Boolean
* @param {*} a
* @param {*} b
* @return {Boolean}
* @example
*
* R.equals(1, 1); //=> true
* R.equals(1, '1'); //=> false
* R.equals([1, 2, 3], [1, 2, 3]); //=> true
*
* const a = {}; a.v = a;
* const b = {}; b.v = b;
* R.equals(a, b); //=> true
*/
var equals =
/*#__PURE__*/
_curry2(function equals(a, b) {
return _equals(a, b, [], [])
})
function _indexOf(list, a, idx) {
var inf, item // Array.prototype.indexOf doesn't exist below IE9
if (typeof list.indexOf === 'function') {
switch (typeof a) {
case 'number':
if (a === 0) {
// manually crawl the list to distinguish between +0 and -0
inf = 1 / a
while (idx < list.length) {
item = list[idx]
if (item === 0 && 1 / item === inf) {
return idx
}
idx += 1
}
return -1
} else if (a !== a) {
// NaN
while (idx < list.length) {
item = list[idx]
if (typeof item === 'number' && item !== item) {
return idx
}
idx += 1
}
return -1
} // non-zero numbers can utilise Set
return list.indexOf(a, idx)
// all these types can utilise Set
case 'string':
case 'boolean':
case 'function':
case 'undefined':
return list.indexOf(a, idx)
case 'object':
if (a === null) {
// null can utilise Set
return list.indexOf(a, idx)
}
}
} // anything else not covered above, defer to R.equals
while (idx < list.length) {
if (equals(list[idx], a)) {
return idx
}
idx += 1
}
return -1
}
function _includes(a, list) {
return _indexOf(list, a, 0) >= 0
}
function _map(fn, functor) {
var idx = 0
var len = functor.length
var result = Array(len)
while (idx < len) {
result[idx] = fn(functor[idx])
idx += 1
}
return result
}
function _arrayReduce(reducer, acc, list) {
var index = 0
var length = list.length
while (index < length) {
acc = reducer(acc, list[index])
index += 1
}
return acc
}
function _filter(fn, list) {
var idx = 0
var len = list.length
var result = []
while (idx < len) {
if (fn(list[idx])) {
result[result.length] = list[idx]
}
idx += 1
}
return result
}
function _isObject(x) {
return Object.prototype.toString.call(x) === '[object Object]'
}
var XFilter =
/*#__PURE__*/
(function () {
function XFilter(f, xf) {
this.xf = xf
this.f = f
}
XFilter.prototype['@@transducer/init'] = _xfBase.init
XFilter.prototype['@@transducer/result'] = _xfBase.result
XFilter.prototype['@@transducer/step'] = function (result, input) {
return this.f(input)
? this.xf['@@transducer/step'](result, input)
: result
}
return XFilter
})()
function _xfilter(f) {
return function (xf) {
return new XFilter(f, xf)
}
}
/**
* Takes a predicate and a `Filterable`, and returns a new filterable of the
* same type containing the members of the given filterable which satisfy the
* given predicate. Filterable objects include plain objects or any object
* that has a filter method such as `Array`.
*
* Dispatches to the `filter` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @category Object
* @sig Filterable f => (a -> Boolean) -> f a -> f a
* @param {Function} pred
* @param {Array} filterable
* @return {Array} Filterable
* @see R.reject, R.transduce, R.addIndex
* @example
*
* const isEven = n => n % 2 === 0;
*
* R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
*
* R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
*/
var filter =
/*#__PURE__*/
_curry2(
/*#__PURE__*/
_dispatchable(
['fantasy-land/filter', 'filter'],
_xfilter,
function (pred, filterable) {
return _isObject(filterable)
? _arrayReduce(
function (acc, key) {
if (pred(filterable[key])) {
acc[key] = filterable[key]
}
return acc
},
{},
keys(filterable),
) // else
: _filter(pred, filterable)
},
),
)
var XMap =
/*#__PURE__*/
(function () {
function XMap(f, xf) {
this.xf = xf
this.f = f
}
XMap.prototype['@@transducer/init'] = _xfBase.init
XMap.prototype['@@transducer/result'] = _xfBase.result
XMap.prototype['@@transducer/step'] = function (result, input) {
return this.xf['@@transducer/step'](result, this.f(input))
}
return XMap
})()
var _xmap = function _xmap(f) {
return function (xf) {
return new XMap(f, xf)
}
}
var _xmap$1 = _xmap
/**
* Takes a function and
* a [functor](https://github.com/fantasyland/fantasy-land#functor),
* applies the function to each of the functor's values, and returns
* a functor of the same shape.
*
* Ramda provides suitable `map` implementations for `Array` and `Object`,
* so this function may be applied to `[1, 2, 3]` or `{x: 1, y: 2, z: 3}`.
*
* Dispatches to the `map` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* Also treats functions as functors and will compose them together.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Functor f => (a -> b) -> f a -> f b
* @param {Function} fn The function to be called on every element of the input `list`.
* @param {Array} list The list to be iterated over.
* @return {Array} The new list.
* @see R.transduce, R.addIndex, R.pluck, R.project
* @example
*
* const double = x => x * 2;
*
* R.map(double, [1, 2, 3]); //=> [2, 4, 6]
*
* R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}
* @symb R.map(f, [a, b]) = [f(a), f(b)]
* @symb R.map(f, { x: a, y: b }) = { x: f(a), y: f(b) }
* @symb R.map(f, functor_o) = functor_o.map(f)
*/
var map =
/*#__PURE__*/
_curry2(
/*#__PURE__*/
_dispatchable(
['fantasy-land/map', 'map'],
_xmap$1,
function map(fn, functor) {
switch (Object.prototype.toString.call(functor)) {
case '[object Function]':
return curryN(functor.length, function () {
return fn.call(this, functor.apply(this, arguments))
})
case '[object Object]':
return _arrayReduce(
function (acc, key) {
acc[key] = fn(functor[key])
return acc
},
{},
keys(functor),
)
default:
return _map(fn, functor)
}
},
),
)
function _isString(x) {
return Object.prototype.toString.call(x) === '[object String]'
}
/**
* Tests whether or not an object is similar to an array.
*
* @private
* @category Type
* @category List
* @sig * -> Boolean
* @param {*} x The object to test.
* @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise.
* @example
*
* _isArrayLike([]); //=> true
* _isArrayLike(true); //=> false
* _isArrayLike({}); //=> false
* _isArrayLike({length: 10}); //=> false
* _isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true
* _isArrayLike({nodeType: 1, length: 1}) // => false
*/
var _isArrayLike =
/*#__PURE__*/
_curry1(function isArrayLike(x) {
if (_isArray(x)) {
return true
}
if (!x) {
return false
}
if (typeof x !== 'object') {
return false
}
if (_isString(x)) {
return false
}
if (x.length === 0) {
return true
}
if (x.length > 0) {
return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1)
}
return false
})
var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator'
function _createReduce(arrayReduce, methodReduce, iterableReduce) {
return function _reduce(xf, acc, list) {
if (_isArrayLike(list)) {
return arrayReduce(xf, acc, list)
}
if (list == null) {
return acc
}
if (typeof list['fantasy-land/reduce'] === 'function') {
return methodReduce(xf, acc, list, 'fantasy-land/reduce')
}
if (list[symIterator] != null) {
return iterableReduce(xf, acc, list[symIterator]())
}
if (typeof list.next === 'function') {
return iterableReduce(xf, acc, list)
}
if (typeof list.reduce === 'function') {
return methodReduce(xf, acc, list, 'reduce')
}
throw new TypeError('reduce: list must be array or iterable')
}
}
function _xArrayReduce(xf, acc, list) {
var idx = 0
var len = list.length
while (idx < len) {
acc = xf['@@transducer/step'](acc, list[idx])
if (acc && acc['@@transducer/reduced']) {
acc = acc['@@transducer/value']
break
}
idx += 1
}
return xf['@@transducer/result'](acc)
}
/**
* Creates a function that is bound to a context.
* Note: `R.bind` does not provide the additional argument-binding capabilities of
* [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
*
* @func
* @memberOf R
* @since v0.6.0
* @category Function
* @category Object
* @sig (* -> *) -> {*} -> (* -> *)
* @param {Function} fn The function to bind to context
* @param {Object} thisObj The context to bind `fn` to
* @return {Function} A function that will execute in the context of `thisObj`.
* @see R.partial
* @example
*
* const log = R.bind(console.log, console);
* R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3}
* // logs {a: 2}
* @symb R.bind(f, o)(a, b) = f.call(o, a, b)
*/
var bind =
/*#__PURE__*/
_curry2(function bind(fn, thisObj) {
return _arity(fn.length, function () {
return fn.apply(thisObj, arguments)
})
})
function _xIterableReduce(xf, acc, iter) {
var step = iter.next()
while (!step.done) {
acc = xf['@@transducer/step'](acc, step.value)
if (acc && acc['@@transducer/reduced']) {
acc = acc['@@transducer/value']
break
}
step = iter.next()
}
return xf['@@transducer/result'](acc)
}
function _xMethodReduce(xf, acc, obj, methodName) {
return xf['@@transducer/result'](
obj[methodName](bind(xf['@@transducer/step'], xf), acc),
)
}
var _xReduce =
/*#__PURE__*/
_createReduce(_xArrayReduce, _xMethodReduce, _xIterableReduce)
var XWrap =
/*#__PURE__*/
(function () {
function XWrap(fn) {
this.f = fn
}
XWrap.prototype['@@transducer/init'] = function () {
throw new Error('init not implemented on XWrap')
}
XWrap.prototype['@@transducer/result'] = function (acc) {
return acc
}
XWrap.prototype['@@transducer/step'] = function (acc, x) {
return this.f(acc, x)
}
return XWrap
})()
function _xwrap(fn) {
return new XWrap(fn)
}
/**
* Returns a single item by iterating through the list, successively calling
* the iterator function and passing it an accumulator value and the current
* value from the array, and then passing the result to the next call.
*
* The iterator function receives two values: *(acc, value)*. It may use
* [`R.reduced`](#reduced) to shortcut the iteration.
*
* The arguments' order of [`reduceRight`](#reduceRight)'s iterator function
* is *(value, acc)*.
*
* Note: `R.reduce` does not skip deleted or unassigned indices (sparse
* arrays), unlike the native `Array.prototype.reduce` method. For more details
* on this behavior, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description
*
* Be cautious of mutating and returning the accumulator. If you reuse it across
* invocations, it will continue to accumulate onto the same value. The general
* recommendation is to always return a new value. If you can't do so for
* performance reasons, then be sure to reinitialize the accumulator on each
* invocation.
*
* Dispatches to the `reduce` method of the third argument, if present. When
* doing so, it is up to the user to handle the [`R.reduced`](#reduced)
* shortcuting, as this is not implemented by `reduce`.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig ((a, b) -> a) -> a -> [b] -> a
* @param {Function} fn The iterator function. Receives two values, the accumulator and the
* current element from the array.
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.reduced, R.addIndex, R.reduceRight
* @example
*
* R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10
* // - -10
* // / \ / \
* // - 4 -6 4
* // / \ / \
* // - 3 ==> -3 3
* // / \ / \
* // - 2 -1 2
* // / \ / \
* // 0 1 0 1
*
* @symb R.reduce(f, a, [b, c, d]) = f(f(f(a, b), c), d)
*/
var reduce =
/*#__PURE__*/
_curry3(function (xf, acc, list) {
return _xReduce(typeof xf === 'function' ? _xwrap(xf) : xf, acc, list)
})
/**
* `_makeFlat` is a helper function that returns a one-level or fully recursive
* function based on the flag passed in.
*
* @private
*/
function _makeFlat(recursive) {
return function flatt(list) {
var value, jlen, j
var result = []
var idx = 0
var ilen = list.length
while (idx < ilen) {
if (_isArrayLike(list[idx])) {
value = recursive ? flatt(list[idx]) : list[idx]
j = 0
jlen = value.length
while (j < jlen) {
result[result.length] = value[j]
j += 1
}
} else {
result[result.length] = list[idx]
}
idx += 1
}
return result
}
}
function _pipe(f, g) {
return function () {
return g.call(this, f.apply(this, arguments))
}
}
/**
* This checks whether a function has a [methodname] function. If it isn't an
* array it will execute that function otherwise it will default to the ramda
* implementation.
*
* @private
* @param {Function} fn ramda implementation
* @param {String} methodname property to check for a custom implementation
* @return {Object} Whatever the return value of the method is.
*/
function _checkForMethod(methodname, fn) {
return function () {
var length = arguments.length
if (length === 0) {
return fn()
}
var obj = arguments[length - 1]
return _isArray(obj) || typeof obj[methodname] !== 'function'
? fn.apply(this, arguments)
: obj[methodname].apply(
obj,
Array.prototype.slice.call(arguments, 0, length - 1),
)
}
}
/**
* Returns the elements of the given list or string (or object with a `slice`
* method) from `fromIndex` (inclusive) to `toIndex` (exclusive).
*
* Dispatches to the `slice` method of the third argument, if present.
*
* @func
* @memberOf R
* @since v0.1.4
* @category List
* @sig Number -> Number -> [a] -> [a]
* @sig Number -> Number -> String -> String
* @param {Number} fromIndex The start index (inclusive).
* @param {Number} toIndex The end index (exclusive).
* @param {*} list
* @return {*}
* @example
*
* R.slice(1, 3, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
* R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd']
* R.slice(0, -1, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c']
* R.slice(-3, -1, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
* R.slice(0, 3, 'ramda'); //=> 'ram'
*/
var slice =
/*#__PURE__*/
_curry3(
/*#__PURE__*/
_checkForMethod('slice', function slice(fromIndex, toIndex, list) {
return Array.prototype.slice.call(list, fromIndex, toIndex)
}),
)
/**
* Returns all but the first element of the given list or string (or object
* with a `tail` method).
*
* Dispatches to the `slice` method of the first argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a]
* @sig String -> String
* @param {*} list
* @return {*}
* @see R.head, R.init, R.last
* @example
*
* R.tail([1, 2, 3]); //=> [2, 3]
* R.tail([1, 2]); //=> [2]
* R.tail([1]); //=> []
* R.tail([]); //=> []
*
* R.tail('abc'); //=> 'bc'
* R.tail('ab'); //=> 'b'
* R.tail('a'); //=> ''
* R.tail(''); //=> ''
*/
var tail =
/*#__PURE__*/
_curry1(
/*#__PURE__*/
_checkForMethod(
'tail',
/*#__PURE__*/
slice(1, Infinity),
),
)
/**
* Performs left-to-right function composition. The first argument may have
* any arity; the remaining arguments must be unary.
*
* In some libraries this function is named `sequence`.
*
* **Note:** The result of pipe is not automatically curried.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)) -> ((a, b, ..., n) -> z)
* @param {...Function} functions
* @return {Function}
* @see R.compose
* @example
*
* const f = R.pipe(Math.pow, R.negate, R.inc);
*
* f(3, 4); // -(3^4) + 1
* @symb R.pipe(f, g, h)(a, b) = h(g(f(a, b)))
* @symb R.pipe(f, g, h)(a)(b) = h(g(f(a)))(b)
*/
function pipe() {
if (arguments.length === 0) {
throw new Error('pipe requires at least one argument')
}
return _arity(
arguments[0].length,
reduce(_pipe, arguments[0], tail(arguments)),
)
}
function _identity(x) {
return x
}
/**
* A function that does nothing but return the parameter supplied to it. Good
* as a default or placeholder function.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig a -> a
* @param {*} x The value to return.
* @return {*} The input value, `x`.
* @example
*
* R.identity(1); //=> 1
*
* const obj = {};
* R.identity(obj) === obj; //=> true
* @symb R.identity(a) = a
*/
var identity =
/*#__PURE__*/
_curry1(_identity)
var identity$1 = identity
var _Set =
/*#__PURE__*/
(function () {
function _Set() {
/* globals Set */
this._nativeSet = typeof Set === 'function' ? new Set() : null
this._items = {}
}
// until we figure out why jsdoc chokes on this
// @param item The item to add to the Set
// @returns {boolean} true if the item did not exist prior, otherwise false
//
_Set.prototype.add = function (item) {
return !hasOrAdd(item, true, this)
} //
// @param item The item to check for existence in the Set
// @returns {boolean} true if the item exists in the Set, otherwise false
//
_Set.prototype.has = function (item) {
return hasOrAdd(item, false, this)
} //
// Combines the logic for checking whether an item is a member of the set and
// for adding a new item to the set.
//
// @param item The item to check or add to the Set instance.
// @param shouldAdd If true, the item will be added to the set if it doesn't
// already exist.
// @param set The set instance to check or add to.
// @return {boolean} true if the item already existed, otherwise false.
//
return _Set
})()
function hasOrAdd(item, shouldAdd, set) {
var type = typeof item
var prevSize, newSize
switch (type) {
case 'string':
case 'number':
// distinguish between +0 and -0
if (item === 0 && 1 / item === -Infinity) {
if (set._items['-0']) {
return true
} else {
if (shouldAdd) {
set._items['-0'] = true
}
return false
}
} // these types can all utilise the native Set
if (set._nativeSet !== null) {
if (shouldAdd) {
prevSize = set._nativeSet.size
set._nativeSet.add(item)
newSize = set._nativeSet.size
return newSize === prevSize
} else {
return set._nativeSet.has(item)
}
} else {
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = {}
set._items[type][item] = true
}
return false
} else if (item in set._items[type]) {
return true
} else {
if (shouldAdd) {
set._items[type][item] = true
}
return false
}
}
case 'boolean':
// set._items['boolean'] holds a two element array
// representing [ falseExists, trueExists ]
if (type in set._items) {
var bIdx = item ? 1 : 0
if (set._items[type][bIdx]) {
return true
} else {
if (shouldAdd) {
set._items[type][bIdx] = true
}
return false
}
} else {
if (shouldAdd) {
set._items[type] = item ? [false, true] : [true, false]
}
return false
}
case 'function':
// compare functions for reference equality
if (set._nativeSet !== null) {
if (shouldAdd) {
prevSize = set._nativeSet.size
set._nativeSet.add(item)
newSize = set._nativeSet.size
return newSize === prevSize
} else {
return set._nativeSet.has(item)
}
} else {
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = [item]
}
return false
}
if (!_includes(item, set._items[type])) {
if (shouldAdd) {
set._items[type].push(item)
}
return false
}
return true
}
case 'undefined':
if (set._items[type]) {
return true
} else {
if (shouldAdd) {
set._items[type] = true
}
return false
}
case 'object':
if (item === null) {
if (!set._items['null']) {
if (shouldAdd) {
set._items['null'] = true
}
return false
}
return true
}
/* falls through */
default:
// reduce the search size of heterogeneous sets by creating buckets
// for each type.
type = Object.prototype.toString.call(item)
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = [item]
}
return false
} // scan through all previously applied items
if (!_includes(item, set._items[type])) {
if (shouldAdd) {
set._items[type].push(item)
}
return false
}
return true
}
} // A simple Set type that honours R.equals semantics
/**
* Returns a new list by pulling every item out of it (and all its sub-arrays)
* and putting them in a new array, depth-first.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [b]
* @param {Array} list The array to consider.
* @return {Array} The flattened list.
* @see R.unnest
* @example
*
* R.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]);
* //=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
*/
var flatten =
/*#__PURE__*/
_curry1(
/*#__PURE__*/
_makeFlat(true),
)
var XUniqBy =
/*#__PURE__*/
(function () {
function XUniqBy(f, xf) {
this.xf = xf
this.f = f
this.set = new _Set()
}
XUniqBy.prototype['@@transducer/init'] = _xfBase.init
XUniqBy.prototype['@@transducer/result'] = _xfBase.result
XUniqBy.prototype['@@transducer/step'] = function (result, input) {
return this.set.add(this.f(input))
? this.xf['@@transducer/step'](result, input)
: result
}
return XUniqBy
})()
function _xuniqBy(f) {
return function (xf) {
return new XUniqBy(f, xf)
}
}
/**
* Returns a new list containing only one copy of each element in the original
* list, based upon the value returned by applying the supplied function to
* each list element. Prefers the first item if the supplied function produces
* the same value on two items. [`R.equals`](#equals) is used for comparison.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig (a -> b) -> [a] -> [a]
* @param {Function} fn A function used to produce a value to use during comparisons.
* @param {Array} list The array to consider.
* @return {Array} The list of unique items.
* @example
*
* R.uniqBy(Math.abs, [-1, -5, 2, 10, 1, 2]); //=> [-1, -5, 2, 10]
*/
var uniqBy =
/*#__PURE__*/
_curry2(
/*#__PURE__*/
_dispatchable([], _xuniqBy, function (fn, list) {
var set = new _Set()
var result = []
var idx = 0
var appliedItem, item
while (idx < list.length) {
item = list[idx]
appliedItem = fn(item)
if (set.add(appliedItem)) {
result.push(item)
}
idx += 1
}
return result
}),
)
/**
* Returns a new list containing only one copy of each element in the original
* list. [`R.equals`](#equals) is used to determine equality.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a]
* @param {Array} list The array to consider.
* @return {Array} The list of unique items.
* @example
*
* R.uniq([1, 1, 2, 1]); //=> [1, 2]
* R.uniq([1, '1']); //=> [1, '1']
* R.uniq([[42], [42]]); //=> [[42]]
*/
var uniq =
/*#__PURE__*/
uniqBy(identity$1)
var uniq$1 = uniq
/**
* Returns a partial copy of an object containing only the keys specified. If
* the key does not exist, the property is ignored.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig [k] -> {k: v} -> {k: v}
* @param {Array} names an array of String property names to copy onto a new object
* @param {Object} obj The object to copy from
* @return {Object} A new object with only properties from `names` on it.
* @see R.omit, R.props
* @example
*
* R.pick(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1, d: 4}
* R.pick(['a', 'e', 'f'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
*/
var pick =
/*#__PURE__*/
_curry2(function pick(names, obj) {
var result = {}
var idx = 0
while (idx < names.length) {
if (names[idx] in obj) {
result[names[idx]] = obj[names[idx]]
}
idx += 1
}
return result
})
var XTap =
/*#__PURE__*/
(function () {
function XTap(f, xf) {
this.xf = xf
this.f = f
}
XTap.prototype['@@transducer/init'] = _xfBase.init
XTap.prototype['@@transducer/result'] = _xfBase.result
XTap.prototype['@@transducer/step'] = function (result, input) {
this.f(input)
return this.xf['@@transducer/step'](result, input)
}
return XTap
})()
function _xtap(f) {
return function (xf) {
return new XTap(f, xf)
}
}
/**
* Runs the given function with the supplied object, then returns the object.
*
* Acts as a transducer if a transformer is given as second parameter.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a -> *) -> a -> a
* @param {Function} fn The function to call with `x`. The return value of `fn` will be thrown away.
* @param {*} x
* @return {*} `x`.
* @example
*
* const sayX = x => console.log('x is ' + x);
* R.tap(sayX, 100); //=> 100
* // logs 'x is 100'
* @symb R.tap(f, a) = (f(a), a)
*/
var tap =
/*#__PURE__*/
_curry2(
/*#__PURE__*/
_dispatchable([], _xtap, function tap(fn, x) {
fn(x)
return x
}),
)
// Table.wc.svelte (Svelte v5.0.0-next.94)
// Note: compiler output will change before 5.0 is released!
var root$1 = template(`table`, 1)
function Table_wc($$anchor, $$props) {
push($$props, true)
var fragment = root$1()
append($$anchor, fragment)
pop()
}
customElements.define(
'db-table',
create_custom_element(Table_wc, {}, [], [], true),
)
// separator must only contain chars valid for .querySelector()
const labelSeparator = '_'
const idSeparator = labelSeparator + labelSeparator
const connectionId = ({ table_name, name, connectionTo: to }) =>
`connection${idSeparator}${table_name}${labelSeparator}${name}${idSeparator}${to.table_name}${labelSeparator}${to.name}`
const anchorId = ({ table_name, name }) =>
`anchor${idSeparator}${table_name}_${name}`
const d = tap(console.info)
const connections = (tables) =>
flatten(
map(
pipe(
d,
({ table_name, schema }) =>
pipe(
map(
pipe(d, ({ name, connectionTo }) =>
connectionTo
? connectionId({ table_name, name, connectionTo })
: null,
),
),
filter(identity$1),
)(schema),
d,
),
)(tables),
)
const getBoundingClientRect = (node) => (id) =>
node.querySelector(id)?.getBoundingClientRect()
const getCoordinates = (node) => (prefix) =>
map((segment) =>
getBoundingClientRect(node)(`#${prefix}${idSeparator}${segment}`),
)
const coordinates = (node) =>
map(
pipe((id) => {
// FIXME: we need coordinates of
// - source box
// - destination box
// plus determine left and right anchor point for connection path
const [prefix, source, destination] = id.split(idSeparator)
console.log({ prefix, source, destination })
const [[src_table, src_column], [dst_table, dst_column]] = [
source,
destination,
].map((s) => s.split(labelSeparator))
const c = getCoordinates(node)
const th_els = c('th')([src_table, dst_table])
const tr_els = c('anchor')([source, destination])
console.log(tr_els, th_els)
return [{ id, source, destination }, ...tr_els, ...th_els]
}),
)
const transform = ({ tables, onlyConnected }) => {
if (!tables) {
return
}
const isConnected = uniq$1(
flatten(
map((con) => {
const [, s, d] = con.split(idSeparator)
return [s, d]
})(connections(tables)),
),
)
let counter = 0
const nodes = flatten(
tables.map(({ table_name, schema }) => ({
id: ++counter,
name: table_name,
columns: pipe(
filter(({ name }) =>
onlyConnected
? isConnected?.includes(`${table_name}${labelSeparator}${name}`)
: true,
),
map(({ name, type, connectionTo: to }) => [
name,
type,
to ? `${to.table_name}${labelSeparator}${to.name}` : undefined,
]),
)(schema),
})),
)
const indexedNodes = pipe(
map(({ id, name }) => ({ [name]: id })),
reduce((p, c) => ({ ...p, ...c }), {}),
)(nodes)
const links = pipe(
filter(({ columns }) => columns.filter((c) => c[2]).length > 0),
map(({ id, columns }) =>
columns
.map(([, , link]) =>
link
? {
source: id,
target: indexedNodes[link?.split(labelSeparator)[0]],
}
: undefined,
)
.filter(identity$1),
),
flatten,
)(nodes)
return {
links,
indexedNodes,
nodes: map(pick(['id', 'name', 'columns']))(nodes),
}
}
const chart = (
tables,
dimensions = {
width: 1000,
height: 1000,
table_width: 160,
table_height: 100,
distanceFactor: 4,
},
cb,
) => {
console.log('chart', tables)
if (!tables.tables) {
return
}
const { width, height, table_width, table_height, distanceFactor } =
dimensions
const data = transform({ tables: tables.tables, onlyConnected: true })
// Specify the dimensions of the chart.
// Specify the color scale.
ordinal(category10)
// The force simulation mutates links and nodes, so create a copy
// so that re-evaluating this cell produces the same result.
const links = data.links.map((d) => ({ ...d }))
const nodes = data.nodes.map((d) => ({ ...d }))
// Create a simulation with several forces.
const simulation$1 = simulation(nodes)
.force(
'link',
link(links)
.id((d) => d.id)
.distance(width / (distanceFactor ?? 4)),
)
.force('charge', manyBody().distanceMin(300).strength(1))
.force('center', center(width / 2, height / 2))
.on('tick', ticked)
// Create the SVG container.
const svg = create$1('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', [0, 0, width, height])
.attr('style', 'max-width: 100%; height: auto; min-width 30vw;')
// Add a line for each link, and a circle for each node.
const link$1 = svg
.append('g')
.attr('id', 'links')
.attr('stroke', '#999')
.attr('stroke-opacity', 0)
.selectAll()
.data(links)
.join('line')
.attr('stroke-width', (d) => Math.sqrt(d.value))
const node = svg
.append('g')
.attr('id', 'tables')
.attr('stroke', '#fff')
.attr('stroke-width', 1.5)
.selectAll()
.data(nodes)
.join('foreignObject')
// .attr('id', (d) => `foreignObject_table${idSeparator}${d.name}`)
.attr('width', (d) => Math.max(200, table_width))
.attr('height', (d) => Math.max(d.columns.length * 27 + 20, table_height))
// .attr('fill', (d) => color(d.group))
node
.append('xhtml:section')
.attr('id', (d) => `section${idSeparator}${d.name}`)
.style('border-bottom', '2px solid #5a5e64')
.style('user-select', 'none')
.style('border-width', '3px')
.style('border-style', 'solid')
.style('border-color', '#5a5e64')
.style('border-radius', '0.5em')
// .style('margin', '0.5em')
.append('xhtml:table')
.style('border-collapse', 'collapse')
.attr('id', (d) => `table${idSeparator}${d.name}`)
.html(
(d) =>
`<caption
style="border-bottom: 2px solid #5a5e64;
width: calc(100% - 1em);
caption-side: top;
text-align: left;
font-weight: bold;
padding: 0.2em 0.5em;
margin: 0;
">${d.name}</caption>`,
)
.append('xhtml:tbody')
.append('xhtml:th')
.attr('id', (d) => `th${idSeparator}${d.name}`)
.style('padding', 0)
// FIXME: iterate over columns from transformed nodes instead of schema
tables.tables.map(({ table_name, schema }, i) => {
console.log({ table_name })
node.selectAll(`th#th${idSeparator}${table_name}`).each(function (th) {
console.log(th.name)
const that = this
schema
.map(({ name, type, constrains, connectionTo }) => [
anchorId({ table_name, name }),
`<tr style="display: inline-block;">
<td style="
border-right: 2px solid rgba(127,127,127,0.9);
padding: 0.2em 0.5em;
text-overflow: ellipsis;
overflow: hidden;
max-width: 5em;
">${name}</td>
<td style="padding: 0.2em 0.5em;">${type}</td>
<td style="padding: 0.2em 0.5em; color: lightblue">${constrains ?? ''}</td>
${connectionTo === true ? `<td>(${connectionTo})</td>` : ''}
</tr>
`,
])
.map(([id, html]) => {
// console.log({ html })
const t = document.createElement('tr')
if (id) {
t.id = id
}
t.innerHTML = html
that.parentNode.appendChild(t, that.nextSibling)
console.debug(
`appendChild [${id}] here, we need the coordinates somehow... (this is before mounting??)`,
t.getBoundingClientRect(),
)
})
})
})
node.call(
drag().on('start', dragstarted).on('drag', dragged).on('end', dragended),
)
// // TODO implement anchor points
// const anchor = svg.append('g').attr('id', 'anchors')
// Set the position attributes of links and nodes each time the simulation ticks.
function ticked() {
link$1
.attr('x1', (d) => d.source.x + table_width / 2)
.attr('y1', (d) => d.source.y + table_height / 2)
.attr('x2', (d) => d.target.x + table_width / 2)
.attr('y2', (d) => d.target.y + table_height / 2)
node
.attr('x', (d) => {
// console.debug(`${d.id}: x ${d.x}`)
cb('move', { id: d.id, x: d.x, width: d.width })
return d.x
})
.attr('y', (d) => {
// console.debug(`${d.id}: y ${d.y}`)
cb('move', { id: d.id, y: d.y, height: d.height })
return d.y
})
// .dispatch('move', { detail: 'blub', bubbles: true })
}
// Reheat the simulation when drag starts, and fix the subject position.
function dragstarted(event) {
if (!event.active) simulation$1.alphaTarget(0.3).restart()
event.subject.fx = event.subject.x
event.subject.fy = event.subject.y
}
// Update the subject (dragged node) position during drag.
function dragged(event) {
event.subject.fx = event.x
event.subject.fy = event.y
}
// Restore the target alpha so the simulation cools after dragging ends.
// Unfix the subject position now that it’s no longer being dragged.
function dragended(event) {
if (!event.active) simulation$1.alphaTarget(0)
event.subject.fx = null
event.subject.fy = null
}
// When this cell is re-run, stop the previous simulation. (This doesn’t
// really matter since the target alpha is zero and the simulation will
// stop naturally, but it’s a good practice.)
// invalidation.then(() => simulation.stop());
return svg.node()
}
// Tables.wc.svelte (Svelte v5.0.0-next.94)
// Note: compiler output will change before 5.0 is released!
var root_4 = svg_template(
`<circle r="6"></circle><rect width="10" height="10" style="transform-origin: center; transform-box: fill-box;" transform="translate(-5, -5), rotate(45)"></rect><path></path>`,
1,
)
var root_5 = svg_template(`<line stroke-width="2"></line>`)
var root_7 = template(`<li> </li>`)
var root_6 = template(
`<ul style="list-style: none; color: rgba(20,127,127,0.6); font-weight: 100; font-family: arial"></ul>`,
)
var root_1 = template(
`<div class="overlay" style="width: 100%; max-width: 100%; height: 100%;
position: absolute; top: 0; left: 0;"><svg style="max-width: 100%; height: auto; min-width 30vw;"><g id="connectionprojections"></g></svg></div> <div class="baseline" style="width: 100%;
max-width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;"></div> <!>`,
1,
)
var root = template(
`<div style="display: flex; background-color: #191b1f; color: #e4eaed;"><!></div>`,
)
function Tables_wc($$anchor, $$props) {
push($$props, true)
let data = prop($$props, 'data', 7),
curves = prop($$props, 'curves', 7),
debug = prop($$props, 'debug', 7)
let _props = JSON.parse(data()) || { tables: [] }
// TODO: pass in dimensions
const { tables, dimensions } = _props
const width = dimensions?.width ?? 1000
/* Math.min(
1000,
// document.getRootNode().body.getBoundingClientRect().width,
)
*/
const height = dimensions?.height ?? 1000
/*Math.min(
1000,
// document.getRootNode().body.getBoundingClientRect().height,
)
*/
const table_width = dimensions?.table_width ?? 260
const table_height = dimensions?.table_height ?? 300
const distanceFactor = dimensions?.distanceFactor ?? 4
let table_position = source(proxy({}))
let label_position = source(proxy({}))
const color = ordinal(Dark2)
// get connections based on tables
const connections$1 = connections(tables)
// get a map of nodes for lookup
const { indexedNodes } = transform({ tables, onlyConnected: true })
Object.entries(indexedNodes).reduce((p, [key, value]) => {
return { ...p, [value]: key }
}, [])
const convertRect = (box) => {
if (!box) return {}
const { x, y, width, height, top, right, bottom, left } = box
return {
x,
y,
width,
height,
top,
right,
bottom,
left,
}
}
const unkey = (id) => {
// FIXME: use a different and safe separator
const [table, label] = id.split(labelSeparator)
return { id, table, label }
}
function visualize(node) {
const msg = (key, { id, ...rest }) => {
get$2(table_position)[id] = {
id,
...get$2(table_position)[id],
...rest,
}
}
select(node).html(null)
// mount the force simulated tables into div
node.appendChild(
chart(
{ tables },
{
width,
height,
table_width,
table_height,
distanceFactor,
},
msg,
),
)
coordinates(node)(connections$1).map(
tap(([{ source, destination }, srcRect, dstRect, srcTable, dstTable]) => {
get$2(label_position)[source] = {
...unkey(source),
...convertRect(srcRect),
thPos: convertRect(srcTable),
}
get$2(label_position)[destination] = {
...unkey(destination),
...convertRect(dstRect),
thPos: convertRect(dstTable),
}
}),
)
}
const posDebug = (o) =>
o ? `${o.id}: ${Math.floor(o.x)} ${Math.floor(o.y)}` : {}
const controlPointString = (o) => {
//INFO: inspired by: https://github.com/open-source-labs/Svelvet/blob/main/src/lib/components/Edge/Edge.svelte#L107
if (!o) {
return ''
}
const { source, target } = o
const rotateVector = ({ x, y }) => {
const angle = -45 * (Math.PI / 180)
return {
x: x * Math.cos(angle) - y * Math.sin(angle),
y: y * Math.sin(angle) + y * Math.cos(angle),
}
}
//Reactive declarations
const sourceX = source.x
const sourceY = source.y
const targetX = target.x
const targetY = target.y
// The distances between the points
const deltaX = targetX - sourceX
const deltaY = targetY - sourceY
const anchorWidth = Math.abs(deltaX)
const anchorHeight = Math.abs(deltaY)
// Strength of curvature
const maxCurveDisplaceX = Math.max(30, Math.min(600, anchorWidth / 2))
const maxCurveDisplaceY = Math.max(30, Math.min(600, anchorHeight / 2))
// Helper XY pair to offset the control points
const sourceControlVector = rotateVector({
x: sourceX < targetX ? 1 : -1,
y: 0,
})
const targetControlVector = rotateVector({
x: sourceX > targetX ? 1 : -1,
y: 0,
})
// Calculating the control points for the bezier curve
const sourceControlX = sourceX + sourceControlVector.x * maxCurveDisplaceX
const sourceControlY = sourceY + sourceControlVector.y * maxCurveDisplaceY
const targetControlX = targetX + targetControlVector.x * maxCurveDisplaceX
const targetControlY = targetY + targetControlVector.y * maxCurveDisplaceY
// Constructing the control point element of the path string
const controlPointString = `C ${sourceControlX}, ${sourceControlY} ${targetControlX}, ${targetControlY}`
return controlPointString
}
var div = root()
var node_1 = child(div)
if_block(
node_1,
() => tables,
($$anchor) => {
var fragment = root_1()
var div_1 = first_child(fragment)
var svg = child(div_1)
set_attribute(svg, 'viewBox', `0,0,${width},${height}`)
set_attribute(svg, 'width', width)
set_attribute(svg, 'height', height)
var g = child(svg)
each_indexed(
g,
73,
() => connections$1,
($$anchor, connection, i) => {
var fragment_1 = comment()
const computed_const = derived(() => {
const [prefix, source, destination] =
unwrap(connection).split(idSeparator)
return { prefix, source, destination }
})
const computed_const_1 = derived(() => {
const [src_t, src_l, dst_t, dst_l] = flatten(
[
get$2(computed_const).source,
get$2(computed_const).destination,
].map((s) => s.split(labelSeparator)),
)
return { src_t, src_l, dst_t, dst_l }
})
var node_2 = first_child(fragment_1)
if_block(
node_2,
() => get$2(computed_const).prefix === 'connection',
($$anchor) => {
var fragment_2 = comment()
const computed_const_2 = derived(() => {
const [t_src, t_dst] = [
get$2(computed_const_1).src_t,
get$2(computed_const_1).dst_t,
].map((id) => get$2(table_position)[indexedNodes[id]])
return { t_src, t_dst }
})
const computed_const_3 = derived(() => {
const [l_src, l_dst] = [
`${get$2(computed_const_1).src_t}${labelSeparator}${get$2(computed_const_1).src_l}`,
`${get$2(computed_const_1).dst_t}${labelSeparator}${get$2(computed_const_1).dst_l}`,
].map((id) => {
if (!Object.keys(get$2(label_position)).includes(id)) return
return get$2(label_position)[id]
})
return { l_src, l_dst }
})
var node_3 = first_child(fragment_2)
if_block(
node_3,
() =>
get$2(computed_const_2).t_src &&
get$2(computed_const_2).t_dst &&
get$2(computed_const_3).l_src &&
get$2(computed_const_3).l_dst,
($$anchor) => {
var fragment_3 = comment()
const box_offset = derived(() => ({ x: -3, y: +3 }))
const computed_const_4 = derived(() => {
const [x1, x2, y1, y2] = [
get$2(computed_const_3).l_src.x +
get$2(computed_const_2).t_src.x +
(get$2(computed_const_3).l_src.x +
get$2(computed_const_2).t_src.x <
get$2(computed_const_3).l_dst.x +
get$2(computed_const_2).t_dst.x
? table_width + get$2(box_offset).x
: 0),
get$2(computed_const_3).l_dst.x +
get$2(computed_const_2).t_dst.x +
(get$2(computed_const_3).l_src.x +
get$2(computed_const_2).t_src.x >
get$2(computed_const_3).l_dst.x +
get$2(computed_const_2).t_dst.x
? table_width + get$2(box_offset).x
: 0),
get$2(computed_const_3).l_src.y +
get$2(computed_const_3).l_src.height / 2 +
get$2(computed_const_2).t_src.y +
get$2(box_offset).y,
get$2(computed_const_3).l_dst.y +
get$2(computed_const_3).l_dst.height / 2 +
get$2(computed_const_2).t_dst.y +
get$2(box_offset).y,
]
return { x1, x2, y1, y2 }
})
var node_4 = first_child(fragment_3)
if_block(
node_4,
() => [true.toString(), true].includes(curves()),
($$anchor) => {
var fragment_4 = root_4()
var circle = first_child(fragment_4)
render_effect(() =>
set_attribute(circle, 'fill', color(unwrap(i))),
)
var rect = sibling(circle)
render_effect(() =>
set_attribute(rect, 'fill', color(unwrap(i))),
)
var path = sibling(rect)
render_effect(() =>
set_attribute(
path,
'd',
`M ${get$2(computed_const_4).x1}, ${get$2(computed_const_4).y1} ${controlPointString(
{
source: {
x: get$2(computed_const_4).x1,
y: get$2(computed_const_4).y1,
},
target: {
x: get$2(computed_const_4).x2,
y: get$2(computed_const_4).y2,
},
},
)} ${get$2(computed_const_4).x2}, ${get$2(computed_const_4).y2}`,
),
)
render_effect(() =>
set_attribute(path, 'stroke', color(unwrap(i))),
)
render_effect(() => {
set_attribute(circle, 'cx', get$2(computed_const_4).x1)
set_attribute(circle, 'cy', get$2(computed_const_4).y1)
set_attribute(rect, 'x', get$2(computed_const_4).x2)
set_attribute(rect, 'y', get$2(computed_const_4).y2)
})
append($$anchor, fragment_4)
},
($$anchor) => {
var line = root_5()
render_effect(() =>
set_attribute(line, 'stroke', color(unwrap(i))),
)
render_effect(() => {
set_attribute(line, 'x1', get$2(computed_const_4).x1)
set_attribute(line, 'x2', get$2(computed_const_4).x2)
set_attribute(line, 'y1', get$2(computed_const_4).y1)
set_attribute(line, 'y2', get$2(computed_const_4).y2)
})
append($$anchor, line)
},
)
append($$anchor, fragment_3)
},
)
append($$anchor, fragment_2)
},
)
append($$anchor, fragment_1)
},
)
var div_2 = sibling(sibling(div_1, true))
var node_5 = sibling(sibling(div_2, true))
if_block(node_5, debug, ($$anchor) => {
var ul = root_6()
each_indexed(
ul,
73,
() => connections$1,
($$anchor, connection, $$index_1) => {
var fragment_5 = comment()
const computed_const_5 = derived(() => {
const [prefix, source, destination] =
unwrap(connection).split(idSeparator)
return { prefix, source, destination }
})
const computed_const_6 = derived(() => {
const [src_t, src_l, dst_t, dst_l] = flatten(
[
get$2(computed_const_5).source,
get$2(computed_const_5).destination,
].map((s) => s.split(labelSeparator)),
)
return { src_t, src_l, dst_t, dst_l }
})
var node_6 = first_child(fragment_5)
if_block(
node_6,
() => get$2(computed_const_5).prefix === 'connection',
($$anchor) => {
var li = root_7()
const computed_const_7 = derived(() => {
const [t_src, t_dst] = [
get$2(computed_const_6).src_t,
get$2(computed_const_6).dst_t,
].map((id) => get$2(table_position)[indexedNodes[id]])
return { t_src, t_dst }
})
const computed_const_8 = derived(() => {
const [l_src, l_dst] = [
`${get$2(computed_const_6).src_t}${labelSeparator}${get$2(computed_const_6).src_l}`,
`${get$2(computed_const_6).dst_t}${labelSeparator}${get$2(computed_const_6).dst_l}`,
].map((id) => {
if (!Object.keys(get$2(label_position)).includes(id)) return
return get$2(label_position)[id]
})
return { l_src, l_dst }
})
var text = child(li)
render_effect(() =>
set_text(
text,
`${stringify(get$2(computed_const_6).src_t)}_${stringify(get$2(computed_const_6).src_l)} (${stringify(posDebug(get$2(computed_const_7).t_src))}) + (${stringify(posDebug(get$2(computed_const_8).l_src))}) -> ${stringify(get$2(computed_const_6).dst_t)}_${stringify(get$2(computed_const_6).dst_l)}
(${stringify(posDebug(get$2(computed_const_7).t_dst))}) + (${stringify(posDebug(get$2(computed_const_8).l_dst))})`,
),
)
append($$anchor, li)
},
)
append($$anchor, fragment_5)
},
)
append($$anchor, ul)
})
action(div_2, ($$node) => visualize($$node))
append($$anchor, fragment)
},
)
append($$anchor, div)
return pop({
get data() {
return data()
},
set data($$value) {
data($$value)
flush_sync()
},
get curves() {
return curves()
},
set curves($$value) {
curves($$value)
flush_sync()
},
get debug() {
return debug()
},
set debug($$value) {
debug($$value)
flush_sync()
},
})
}
customElements.define(
'visualize-tables',
create_custom_element(
Tables_wc,
{ data: {}, curves: {}, debug: {} },
[],
[],
true,
),
)
export { Tables_wc as Tables }
<!doctype html>
<html>
<head>
<script src="/build.js" type="module">
console.log('loading')
</script>
<style>
body {
margin: 0;
height: 100%;
background-color: grey;
color: white;
}
.dark {
background-color: blue;
}
</style>
</head>
<body>
test
<div class="dark">
<visualize-tables
dark="true"
data='{"dimensions": {"distanceFactor": 2},"tables":[{"table_name":"a","schema":[{"name":"A1","type":"ID","connectionTo":{"table_name":"b","name":"B2"}}]},{"table_name":"b","schema":[{"name":"B1","type":"Int","constrains":"autoincrement","connectionTo":{"table_name":"a","name":"A1"}},{"name":"B2","type":"Int","connectionTo":{"table_name":"c","name":"C1"}},{"name":"B3","type":"ID"},{"name":"B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4","type":"ID","connectionTo":{"table_name":"c","name":"C4"}}]},{"table_name":"c","schema":[{"name":"C1","type":"ID"},{"name":"C2","type":"ID","constrains":"not null","connectionTo":{"table_name":"a","name":"A1"}},{"name":"C3","type":"ID"},{"name":"C4","type":"String"},{"name":"C5C5C5C5C5C5C5C5C5C5C5C5","type":"Number","connectionTo":{"table_name":"b","name":"B1"}}]}]}'
curves="false"
/>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment