tailwind-screen-size
Version:
A framework-agnostic screen size indicator optimized for TailwindCSS but customizable for any CSS framework. Features real-time dimensions, breakpoints, themes, and development tools.
5,681 lines • 157 kB
JavaScript
'use strict';
var svelte = require('svelte');
// 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 PROPS_IS_BINDABLE = 1 << 3;
const TEMPLATE_FRAGMENT = 1;
const TEMPLATE_USE_IMPORT_NODE = 1 << 1;
const UNINITIALIZED = Symbol();
// Dev-time component properties
const FILENAME = Symbol('filename');
const node_env = globalThis.process?.env?.NODE_ENV;
if (!node_env) {
console.warn('If bundling, conditions should include development or production. If not bundling, conditions or NODE_ENV should include development or production. See https://www.npmjs.com/package/esm-env for tips on setting conditions in popular bundlers and runtimes.');
}
var DEV = node_env && !node_env.toLowerCase().includes('prod');
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
var bold = 'font-weight: bold';
var normal = 'font-weight: normal';
/**
* %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
* @param {string | undefined | null} [component]
* @param {string | undefined | null} [owner]
*/
function ownership_invalid_mutation(component, owner) {
if (DEV) {
console.warn(`%c[svelte] ownership_invalid_mutation\n%c${component ? `${component} mutated a value owned by ${owner}. This is strongly discouraged. Consider passing values to child components with \`bind:\`, or use a callback instead` : "Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead"}`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("ownership_invalid_mutation");
}
}
/**
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
* @param {string} operator
*/
function state_proxy_equality_mismatch(operator) {
if (DEV) {
console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("state_proxy_equality_mismatch");
}
}
// 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 define_property = Object.defineProperty;
var get_descriptor = Object.getOwnPropertyDescriptor;
var object_prototype = Object.prototype;
var array_prototype = Array.prototype;
var get_prototype_of = Object.getPrototypeOf;
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 DISCONNECTED = 1 << 8;
const CLEAN = 1 << 9;
const DIRTY = 1 << 10;
const MAYBE_DIRTY = 1 << 11;
const INERT = 1 << 12;
const DESTROYED = 1 << 13;
const EFFECT_RAN = 1 << 14;
/** 'Transparent' effects do not create a transition boundary */
const EFFECT_TRANSPARENT = 1 << 15;
const INSPECT_EFFECT = 1 << 17;
const HEAD_EFFECT = 1 << 18;
const EFFECT_HAS_DERIVED = 1 << 19;
const STATE_SYMBOL = Symbol('$state');
const STATE_SYMBOL_METADATA = Symbol('$state metadata');
const LEGACY_PROPS = Symbol('legacy props');
/** @import { Equals } from '#client' */
/** @type {Equals} */
function equals(value) {
return value === this.v;
}
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
/**
* Component %component% has an export named `%key%` that a consumer component is trying to access using `bind:%key%`, which is disallowed. Instead, use `bind:this` (e.g. `<%name% bind:this={component} />`) and then access the property on the bound component instance (e.g. `component.%key%`)
* @param {string} component
* @param {string} key
* @param {string} name
* @returns {never}
*/
function bind_invalid_export(component, key, name) {
if (DEV) {
const error = new Error(`bind_invalid_export\nComponent ${component} has an export named \`${key}\` that a consumer component is trying to access using \`bind:${key}\`, which is disallowed. Instead, use \`bind:this\` (e.g. \`<${name} bind:this={component} />\`) and then access the property on the bound component instance (e.g. \`component.${key}\`)`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("bind_invalid_export");
}
}
/**
* A component is attempting to bind to a non-bindable property `%key%` belonging to %component% (i.e. `<%name% bind:%key%={...}>`). To mark a property as bindable: `let { %key% = $bindable() } = $props()`
* @param {string} key
* @param {string} component
* @param {string} name
* @returns {never}
*/
function bind_not_bindable(key, component, name) {
if (DEV) {
const error = new Error(`bind_not_bindable\nA component is attempting to bind to a non-bindable property \`${key}\` belonging to ${component} (i.e. \`<${name} bind:${key}={...}>\`). To mark a property as bindable: \`let { ${key} = $bindable() } = $props()\``);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("bind_not_bindable");
}
}
/**
* %parent% called `%method%` on an instance of %component%, which is no longer valid in Svelte 5. See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information
* @param {string} parent
* @param {string} method
* @param {string} component
* @returns {never}
*/
function component_api_changed(parent, method, component) {
if (DEV) {
const error = new Error(`component_api_changed\n${parent} called \`${method}\` on an instance of ${component}, which is no longer valid in Svelte 5. See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("component_api_changed");
}
}
/**
* Attempted to instantiate %component% with `new %name%`, which is no longer valid in Svelte 5. If this component is not under your control, set the `compatibility.componentApi` compiler option to `4` to keep it working. See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information
* @param {string} component
* @param {string} name
* @returns {never}
*/
function component_api_invalid_new(component, name) {
if (DEV) {
const error = new Error(`component_api_invalid_new\nAttempted to instantiate ${component} with \`new ${name}\`, which is no longer valid in Svelte 5. If this component is not under your control, set the \`compatibility.componentApi\` compiler option to \`4\` to keep it working. See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("component_api_invalid_new");
}
}
/**
* A derived value cannot reference itself recursively
* @returns {never}
*/
function derived_references_self() {
if (DEV) {
const error = new Error(`derived_references_self\nA derived value cannot reference itself recursively`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("derived_references_self");
}
}
/**
* Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops
* @returns {never}
*/
function effect_update_depth_exceeded() {
if (DEV) {
const error = new Error(`effect_update_depth_exceeded\nMaximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("effect_update_depth_exceeded");
}
}
/**
* Cannot do `bind:%key%={undefined}` when `%key%` has a fallback value
* @param {string} key
* @returns {never}
*/
function props_invalid_value(key) {
if (DEV) {
const error = new Error(`props_invalid_value\nCannot do \`bind:${key}={undefined}\` when \`${key}\` has a fallback value`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("props_invalid_value");
}
}
/**
* The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
* @param {string} rune
* @returns {never}
*/
function rune_outside_svelte(rune) {
if (DEV) {
const error = new Error(`rune_outside_svelte\nThe \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("rune_outside_svelte");
}
}
/**
* Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.
* @returns {never}
*/
function state_descriptors_fixed() {
if (DEV) {
const error = new Error(`state_descriptors_fixed\nProperty descriptors defined on \`$state\` objects must contain \`value\` and always be \`enumerable\`, \`configurable\` and \`writable\`.`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("state_descriptors_fixed");
}
}
/**
* Cannot set prototype of `$state` object
* @returns {never}
*/
function state_prototype_fixed() {
if (DEV) {
const error = new Error(`state_prototype_fixed\nCannot set prototype of \`$state\` object`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("state_prototype_fixed");
}
}
/**
* Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
* @returns {never}
*/
function state_unsafe_local_read() {
if (DEV) {
const error = new Error(`state_unsafe_local_read\nReading state that was created inside the same derived is forbidden. Consider using \`untrack\` to read locally created state`);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("state_unsafe_local_read");
}
}
/**
* Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
* @returns {never}
*/
function state_unsafe_mutation() {
if (DEV) {
const error = new Error(`state_unsafe_mutation\nUpdating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without \`$state\``);
error.name = 'Svelte error';
throw error;
} else {
// TODO print a link to the documentation
throw new Error("state_unsafe_mutation");
}
}
let legacy_mode_flag = false;
/** @import { Derived, Effect, Reaction, Source, Value } from '#client' */
let inspect_effects = new Set();
/**
* @param {Set<any>} v
*/
function set_inspect_effects(v) {
inspect_effects = v;
}
/**
* @template V
* @param {V} v
* @returns {Source<V>}
*/
function source(v) {
return {
f: 0, // TODO ideally we could skip this altogether, but it causes type errors
v,
reactions: null,
equals,
version: 0
};
}
/**
* @template V
* @param {V} v
*/
function state(v) {
return push_derived_source(source(v));
}
/**
* @template V
* @param {Source<V>} source
*/
/*#__NO_SIDE_EFFECTS__*/
function push_derived_source(source) {
if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) {
if (derived_sources === null) {
set_derived_sources([source]);
} else {
derived_sources.push(source);
}
}
return source;
}
/**
* @template V
* @param {Source<V>} source
* @param {V} value
* @returns {V}
*/
function set(source, value) {
if (
active_reaction !== null &&
is_runes() &&
(active_reaction.f & (DERIVED | BLOCK_EFFECT)) !== 0 &&
// If the source was created locally within the current derived, then
// we allow the mutation.
(derived_sources === null || !derived_sources.includes(source))
) {
state_unsafe_mutation();
}
return internal_set(source, value);
}
/**
* @template V
* @param {Source<V>} source
* @param {V} value
* @returns {V}
*/
function internal_set(source, value) {
if (!source.equals(value)) {
source.v = value;
source.version = increment_version();
mark_reactions(source, DIRTY);
// 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++)`
if (
active_effect !== null &&
(active_effect.f & CLEAN) !== 0 &&
(active_effect.f & BRANCH_EFFECT) === 0
) {
if (new_deps !== null && new_deps.includes(source)) {
set_signal_status(active_effect, DIRTY);
schedule_effect(active_effect);
} else {
if (untracked_writes === null) {
set_untracked_writes([source]);
} else {
untracked_writes.push(source);
}
}
}
if (DEV && inspect_effects.size > 0) {
const inspects = Array.from(inspect_effects);
var previously_flushing_effect = is_flushing_effect;
set_is_flushing_effect(true);
try {
for (const effect of inspects) {
// Mark clean inspect-effects as maybe dirty and then check their dirtiness
// instead of just updating the effects - this way we avoid overfiring.
if ((effect.f & CLEAN) !== 0) {
set_signal_status(effect, MAYBE_DIRTY);
}
if (check_dirtiness(effect)) {
update_effect(effect);
}
}
} finally {
set_is_flushing_effect(previously_flushing_effect);
}
inspect_effects.clear();
}
}
return value;
}
/**
* @param {Value} signal
* @param {number} status should be DIRTY or MAYBE_DIRTY
* @returns {void}
*/
function mark_reactions(signal, status) {
var reactions = signal.reactions;
if (reactions === null) return;
var length = reactions.length;
for (var i = 0; i < length; i++) {
var reaction = reactions[i];
var flags = reaction.f;
// Skip any effects that are already dirty
if ((flags & DIRTY) !== 0) continue;
// Inspect effects need to run immediately, so that the stack trace makes sense
if (DEV && (flags & INSPECT_EFFECT) !== 0) {
inspect_effects.add(reaction);
continue;
}
set_signal_status(reaction, status);
// If the signal a) was previously clean or b) is an unowned derived, then mark it
if ((flags & (CLEAN | UNOWNED)) !== 0) {
if ((flags & DERIVED) !== 0) {
mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY);
} else {
schedule_effect(/** @type {Effect} */ (reaction));
}
}
}
}
/** @import { Derived, Effect } from '#client' */
/**
* @template V
* @param {() => V} fn
* @returns {Derived<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
function derived(fn) {
var flags = DERIVED | DIRTY;
if (active_effect === null) {
flags |= UNOWNED;
} else {
// Since deriveds are evaluated lazily, any effects created inside them are
// created too late to ensure that the parent effect is added to the tree
active_effect.f |= EFFECT_HAS_DERIVED;
}
var parent_derived =
active_reaction !== null && (active_reaction.f & DERIVED) !== 0
? /** @type {Derived} */ (active_reaction)
: null;
/** @type {Derived<V>} */
const signal = {
children: null,
ctx: component_context,
deps: null,
equals,
f: flags,
fn,
reactions: null,
v: /** @type {V} */ (null),
version: 0,
parent: parent_derived ?? active_effect
};
if (parent_derived !== null) {
(parent_derived.children ??= []).push(signal);
}
return signal;
}
/**
* @param {Derived} derived
* @returns {void}
*/
function destroy_derived_children(derived) {
var children = derived.children;
if (children !== null) {
derived.children = null;
for (var i = 0; i < children.length; i += 1) {
var child = children[i];
if ((child.f & DERIVED) !== 0) {
destroy_derived(/** @type {Derived} */ (child));
} else {
destroy_effect(/** @type {Effect} */ (child));
}
}
}
}
/**
* The currently updating deriveds, used to detect infinite recursion
* in dev mode and provide a nicer error than 'too much recursion'
* @type {Derived[]}
*/
let stack = [];
/**
* @param {Derived} derived
* @returns {Effect | null}
*/
function get_derived_parent_effect(derived) {
var parent = derived.parent;
while (parent !== null) {
if ((parent.f & DERIVED) === 0) {
return /** @type {Effect} */ (parent);
}
parent = parent.parent;
}
return null;
}
/**
* @template T
* @param {Derived} derived
* @returns {T}
*/
function execute_derived(derived) {
var value;
var prev_active_effect = active_effect;
set_active_effect(get_derived_parent_effect(derived));
if (DEV) {
let prev_inspect_effects = inspect_effects;
set_inspect_effects(new Set());
try {
if (stack.includes(derived)) {
derived_references_self();
}
stack.push(derived);
destroy_derived_children(derived);
value = update_reaction(derived);
} finally {
set_active_effect(prev_active_effect);
set_inspect_effects(prev_inspect_effects);
stack.pop();
}
} else {
try {
destroy_derived_children(derived);
value = update_reaction(derived);
} finally {
set_active_effect(prev_active_effect);
}
}
return value;
}
/**
* @param {Derived} derived
* @returns {void}
*/
function update_derived(derived) {
var value = execute_derived(derived);
var status =
(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;
set_signal_status(derived, status);
if (!derived.equals(value)) {
derived.v = value;
derived.version = increment_version();
}
}
/**
* @param {Derived} derived
* @returns {void}
*/
function destroy_derived(derived) {
destroy_derived_children(derived);
remove_reactions(derived, 0);
set_signal_status(derived, DESTROYED);
derived.v = derived.children = derived.deps = derived.ctx = derived.reactions = null;
}
/** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, Reaction, TemplateNode, TransitionManager } from '#client' */
/**
* @param {Effect} effect
* @param {Effect} 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 {null | (() => void | (() => void))} fn
* @param {boolean} sync
* @param {boolean} push
* @returns {Effect}
*/
function create_effect(type, fn, sync, push = true) {
var is_root = (type & ROOT_EFFECT) !== 0;
var parent_effect = active_effect;
if (DEV) {
// Ensure the parent is never an inspect effect
while (parent_effect !== null && (parent_effect.f & INSPECT_EFFECT) !== 0) {
parent_effect = parent_effect.parent;
}
}
/** @type {Effect} */
var effect = {
ctx: component_context,
deps: null,
deriveds: null,
nodes_start: null,
nodes_end: null,
f: type | DIRTY,
first: null,
fn,
last: null,
next: null,
parent: is_root ? null : parent_effect,
prev: null,
teardown: null,
transitions: null,
version: 0
};
if (DEV) {
effect.component_function = dev_current_component_function;
}
if (sync) {
var previously_flushing_effect = is_flushing_effect;
try {
set_is_flushing_effect(true);
update_effect(effect);
effect.f |= EFFECT_RAN;
} catch (e) {
destroy_effect(effect);
throw e;
} finally {
set_is_flushing_effect(previously_flushing_effect);
}
} else if (fn !== null) {
schedule_effect(effect);
}
// if an effect has no dependencies, no DOM and no teardown function,
// don't bother adding it to the effect tree
var inert =
sync &&
effect.deps === null &&
effect.first === null &&
effect.nodes_start === null &&
effect.teardown === null &&
(effect.f & EFFECT_HAS_DERIVED) === 0;
if (!inert && !is_root && push) {
if (parent_effect !== null) {
push_effect(effect, parent_effect);
}
// if we're in a derived, add the effect there too
if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) {
var derived = /** @type {Derived} */ (active_reaction);
(derived.children ??= []).push(effect);
}
}
return effect;
}
/**
* @param {() => void | (() => void)} fn
* @returns {Effect}
*/
function effect(fn) {
return create_effect(EFFECT, fn, false);
}
/**
* @param {() => void | (() => void)} fn
* @returns {Effect}
*/
function template_effect(fn) {
if (DEV) {
define_property(fn, 'name', {
value: '{expression}'
});
}
return block(fn);
}
/**
* @param {(() => void)} fn
* @param {number} flags
*/
function block(fn, flags = 0) {
return create_effect(RENDER_EFFECT | BLOCK_EFFECT | flags, fn, true);
}
/**
* @param {(() => void)} fn
* @param {boolean} [push]
*/
function branch(fn, push = true) {
return create_effect(RENDER_EFFECT | BRANCH_EFFECT, fn, true, push);
}
/**
* @param {Effect} effect
*/
function execute_effect_teardown(effect) {
var teardown = effect.teardown;
if (teardown !== null) {
const previous_reaction = active_reaction;
set_active_reaction(null);
try {
teardown.call(null);
} finally {
set_active_reaction(previous_reaction);
}
}
}
/**
* @param {Effect} signal
* @returns {void}
*/
function destroy_effect_deriveds(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 {Effect} signal
* @param {boolean} remove_dom
* @returns {void}
*/
function destroy_effect_children(signal, remove_dom = false) {
var effect = signal.first;
signal.first = signal.last = null;
while (effect !== null) {
var next = effect.next;
destroy_effect(effect, remove_dom);
effect = next;
}
}
/**
* @param {Effect} signal
* @returns {void}
*/
function destroy_block_effect_children(signal) {
var effect = signal.first;
while (effect !== null) {
var next = effect.next;
if ((effect.f & BRANCH_EFFECT) === 0) {
destroy_effect(effect);
}
effect = next;
}
}
/**
* @param {Effect} effect
* @param {boolean} [remove_dom]
* @returns {void}
*/
function destroy_effect(effect, remove_dom = true) {
var removed = false;
if ((remove_dom || (effect.f & HEAD_EFFECT) !== 0) && effect.nodes_start !== null) {
/** @type {TemplateNode | null} */
var node = effect.nodes_start;
var end = effect.nodes_end;
while (node !== null) {
/** @type {TemplateNode | null} */
var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node));
node.remove();
node = next;
}
removed = true;
}
destroy_effect_children(effect, remove_dom && !removed);
destroy_effect_deriveds(effect);
remove_reactions(effect, 0);
set_signal_status(effect, DESTROYED);
var transitions = effect.transitions;
if (transitions !== null) {
for (const transition of transitions) {
transition.stop();
}
}
execute_effect_teardown(effect);
var parent = effect.parent;
// If the parent doesn't have any children, then skip this work altogether
if (parent !== null && parent.first !== null) {
unlink_effect(effect);
}
if (DEV) {
effect.component_function = null;
}
// `first` and `child` are nulled out in destroy_effect_children
effect.next =
effect.prev =
effect.teardown =
effect.ctx =
effect.deps =
effect.parent =
effect.fn =
effect.nodes_start =
effect.nodes_end =
null;
}
/**
* Detach an effect from the effect tree, freeing up memory and
* reducing the amount of work that happens on subsequent traversals
* @param {Effect} effect
*/
function unlink_effect(effect) {
var parent = effect.parent;
var prev = effect.prev;
var next = effect.next;
if (prev !== null) prev.next = next;
if (next !== null) next.prev = prev;
if (parent !== null) {
if (parent.first === effect) parent.first = next;
if (parent.last === effect) parent.last = prev;
}
}
/**
* 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 {Effect} effect
* @param {() => void} [callback]
*/
function pause_effect(effect, callback) {
/** @type {TransitionManager[]} */
var transitions = [];
pause_children(effect, transitions, true);
run_out_transitions(transitions, () => {
destroy_effect(effect);
if (callback) callback();
});
}
/**
* @param {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 {Effect} effect
* @param {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 & EFFECT_TRANSPARENT) !== 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 {Effect} effect
*/
function resume_effect(effect) {
resume_children(effect, true);
}
/**
* @param {Effect} effect
* @param {boolean} local
*/
function resume_children(effect, local) {
if ((effect.f & INERT) === 0) return;
// If a dependency of this effect changed while it was paused,
// apply the change now
if (check_dirtiness(effect)) {
update_effect(effect);
}
// Ensure we toggle the flag after possibly updating the effect so that
// each block logic can correctly operate on inert items
effect.f ^= INERT;
var child = effect.first;
while (child !== null) {
var sibling = child.next;
var transparent = (child.f & EFFECT_TRANSPARENT) !== 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();
}
}
}
}
/** @import { ProxyMetadata } from '#client' */
/** @typedef {{ file: string, line: number, column: number }} Location */
/** @type {Record<string, Array<{ start: Location, end: Location, component: Function }>>} */
const boundaries = {};
const chrome_pattern = /at (?:.+ \()?(.+):(\d+):(\d+)\)?$/;
const firefox_pattern = /@(.+):(\d+):(\d+)$/;
function get_stack() {
const stack = new Error().stack;
if (!stack) return null;
const entries = [];
for (const line of stack.split('\n')) {
let match = chrome_pattern.exec(line) ?? firefox_pattern.exec(line);
if (match) {
entries.push({
file: match[1],
line: +match[2],
column: +match[3]
});
}
}
return entries;
}
/**
* Determines which `.svelte` component is responsible for a given state change
* @returns {Function | null}
*/
function get_component() {
// first 4 lines are svelte internals; adjust this number if we change the internal call stack
const stack = get_stack()?.slice(4);
if (!stack) return null;
for (let i = 0; i < stack.length; i++) {
const entry = stack[i];
const modules = boundaries[entry.file];
if (!modules) {
// If the first entry is not a component, that means the modification very likely happened
// within a .svelte.js file, possibly triggered by a component. Since these files are not part
// of the bondaries/component context heuristic, we need to bail in this case, else we would
// have false positives when the .svelte.ts file provides a state creator function, encapsulating
// the state and its mutations, and is being called from a component other than the one who
// called the state creator function.
if (i === 0) return null;
continue;
}
for (const module of modules) {
if (module.end == null) {
return null;
}
if (module.start.line < entry.line && module.end.line > entry.line) {
return module.component;
}
}
}
return null;
}
/**
* Together with `mark_module_end`, this function establishes the boundaries of a `.svelte` file,
* such that subsequent calls to `get_component` can tell us which component is responsible
* for a given state change
*/
function mark_module_start() {
const start = get_stack()?.[2];
if (start) {
(boundaries[start.file] ??= []).push({
start,
// @ts-expect-error
end: null,
// @ts-expect-error we add the component at the end, since HMR will overwrite the function
component: null
});
}
}
/**
* @param {Function} component
*/
function mark_module_end(component) {
const end = get_stack()?.[2];
if (end) {
const boundaries_file = boundaries[end.file];
const boundary = boundaries_file[boundaries_file.length - 1];
boundary.end = end;
boundary.component = component;
}
}
/**
* @param {ProxyMetadata | null} from
* @param {ProxyMetadata} to
*/
function widen_ownership(from, to) {
if (to.owners === null) {
return;
}
while (from) {
if (from.owners === null) {
to.owners = null;
break;
}
for (const owner of from.owners) {
to.owners.add(owner);
}
from = from.parent;
}
}
/**
* @param {ProxyMetadata} metadata
* @param {Function} component
* @returns {boolean}
*/
function has_owner(metadata, component) {
if (metadata.owners === null) {
return true;
}
return (
metadata.owners.has(component) ||
(metadata.parent !== null && has_owner(metadata.parent, component))
);
}
/**
* @param {ProxyMetadata} metadata
* @returns {any}
*/
function get_owner(metadata) {
return (
metadata?.owners?.values().next().value ??
get_owner(/** @type {ProxyMetadata} */ (metadata.parent))
);
}
/**
* @param {ProxyMetadata} metadata
*/
function check_ownership(metadata) {
const component = get_component();
if (component && !has_owner(metadata, component)) {
let original = get_owner(metadata);
// @ts-expect-error
if (original[FILENAME] !== component[FILENAME]) {
// @ts-expect-error
ownership_invalid_mutation(component[FILENAME], original[FILENAME]);
} else {
ownership_invalid_mutation();
}
}
}
/** @import { ComponentContext, Derived, Effect, Reaction, Signal, Source, Value } from '#client' */
// Used for DEV time error handling
/** @param {WeakSet<Error>} value */
const handled_errors = new WeakSet();
// 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 {Effect[]} */
let queued_root_effects = [];
let flush_count = 0;
/** @type {Effect[]} Stack of effects, dev only */
let dev_effect_stack = [];
// Handle signal reactivity tree dependencies and reactions
/** @type {null | Reaction} */
let active_reaction = null;
/** @param {null | Reaction} reaction */
function set_active_reaction(reaction) {
active_reaction = reaction;
}
/** @type {null | Effect} */
let active_effect = null;
/** @param {null | Effect} effect */
function set_active_effect(effect) {
active_effect = effect;
}
/**
* When sources are created within a derived, we record them so that we can safely allow
* local mutations to these sources without the side-effect error being invoked unnecessarily.
* @type {null | Source[]}
*/
let derived_sources = null;
/**
* @param {Source[] | null} sources
*/
function set_derived_sources(sources) {
derived_sources = sources;
}
/**
* The dependencies of the reaction that is currently being executed. In many cases,
* the dependencies are unchanged between runs, and so this will be `null` unless
* and until a new dependency is accessed — we track this via `skipped_deps`
* @type {null | Value[]}
*/
let new_deps = null;
let skipped_deps = 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 | Source[]}
*/
let untracked_writes = null;
/** @param {null | Source[]} value */
function set_untracked_writes(value) {
untracked_writes = value;
}
/** @type {number} Used by sources and deriveds for handling updates to unowned deriveds */
let current_version = 0;
// If we are working with a get() chain that has no active container,
// to prevent memory leaks, we skip adding the reaction.
let skip_reaction = false;
// Handling runtime component context
/** @type {ComponentContext | null} */
let component_context = null;
/**
* The current component function. Different from current component context:
* ```html
* <!-- App.svelte -->
* <Foo>
* <Bar /> <!-- context == Foo.svelte, function == App.svelte -->
* </Foo>
* ```
* @type {ComponentContext['function']}
*/
let dev_current_component_function = null;
function increment_version() {
return ++current_version;
}
/** @returns {boolean} */
function is_runes() {
return !legacy_mode_flag;
}
/**
* Determines whether a derived or effect is dirty.
* If it is MAYBE_DIRTY, will set the status to CLEAN
* @param {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 i;
if ((flags & DISCONNECTED) !== 0) {
for (i = 0; i < dependencies.length; i++) {
(dependencies[i].reactions ??= []).push(reaction);
}
reaction.f ^= DISCONNECTED;
}
for (i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (check_dirtiness(/** @type {Derived} */ (dependency))) {
update_derived(/** @type {Derived} */ (dependency));
}
// If we are working with an unowned signal as part of an effect (due to !skip_reaction)
// and the version hasn't changed, we still need to check that this reaction
// is linked to the dependency source – otherwise future updates will not be caught.
if (
is_unowned &&
active_effect !== null &&
!skip_reaction &&
!dependency?.reactions?.includes(reaction)
) {
(dependency.reactions ??= []).push(reaction);
}
if (dependency.version > reaction.version) {
return true;
}
}
}
// Unowned signals should never be marked as clean.
if (!is_unowned) {
set_signal_status(reaction, CLEAN);
}
}
return false;
}
/**
* @param {Error} error
* @param {Effect} effect
* @param {ComponentContext | null} component_context
*/
function handle_error(error, effect, component_context) {
// Given we don't yet have error boundaries, we will just always throw.
if (!DEV || handled_errors.has(error) || component_context === null) {
throw error;
}
const component_stack = [];
const effect_name = effect.fn?.name;
if (effect_name) {
component_stack.push(effect_name);
}
/** @type {ComponentContext | null} */
let current_context = component_context;
while (current_context !== null) {
if (DEV) {
/** @type {string} */
var filename = current_context.function?.[FILENAME];
if (filename) {
const file = filename.split('/').pop();
component_stack.push(file);
}
}
current_context = current_context.p;
}
const indent = /Firefox/.test(navigator.userAgent) ? ' ' : '\t';
define_property(error, 'message', {
value: error.message + `\n${component_stack.map((name) => `\n${indent}in ${name}`).join('')}\n`
});
const stack = error.stack;
// Filter out internal files from callstack
if (stack) {
const lines = stack.split('\n');
const new_lines = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.includes('svelte/src/internal')) {
continue;
}
new_lines.push(line);
}
define_property(error, 'stack', {
value: error.stack + new_lines.join('\n')
});
}
handled_errors.add(error);
throw error;
}
/**
* @template V
* @param {Reaction} reaction
* @returns {V}
*/
function update_reaction(reaction) {
var previous_deps = new_deps;
var previous_skipped_deps = skipped_deps;
var previous_untracked_writes = untracked_writes;
var previous_reaction = active_reaction;
var previous_skip_reaction = skip_reaction;
var prev_derived_sources = derived_sources;
var previous_component_context = component_context;
var flags = reaction.f;
new_deps = /** @type {null | Value[]} */ (null);
skipped_deps = 0;
untracked_writes = null;
active_reaction = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
skip_reaction = !is_flushing_effect && (flags & UNOWNED) !== 0;
derived_sources = null;
component_context = reaction.ctx;
try {
var result = /** @type {Function} */ (0, reaction.fn)();
var deps = reaction.deps;
if (new_deps !== null) {
var i;
remove_reactions(reaction, skipped_deps);
if (deps !== null && skipped_deps > 0) {
deps.length = skipped_deps + new_deps.length;
for (i = 0; i < new_deps.length; i++) {
deps[skipped_deps + i] = new_deps[i];
}
} else {
reaction.deps = deps = new_deps;
}
if (!skip_reaction) {
for (i = skipped_deps; i < deps.length; i++) {
(deps[i].reactions ??= []).push(reaction);
}
}
} else if (deps !== null && skipped_deps < deps.length) {
remove_reactions(reaction, skipped_deps);
deps.length = skipped_deps;
}
return result;
} finally {
new_deps = previous_deps;
skipped_deps = previous_skipped_deps;
untracked_writes = previous_untracked_writes;
active_reaction = previous_reaction;
skip_reaction = previous_skip_reaction;
derived_sources = prev_derived_sources;
component_context = previous_component_context;
}
}
/**
* @template V
* @param {Reaction} signal
* @param {Value<V>} dependency
* @returns {void}
*/
function remove_reaction(signal, dependency) {
let reactions = dependency.reactions;
if (reactions !== null) {
var index = reactions.indexOf(signal);
if (index !== -1) {
var new_length = reactions.length - 1;
if (new_length === 0) {
reactions = dependency.reactions = null;
} else {
// Swap with last element and then remove.
reactions[index] = reactions[new_length];
reactions.pop();
}
}
}
// If the derived has no reactions, then we can disconnect it from the graph,
// allowing it to either reconnect in the future, or be GC'd by the VM.
if (
reactions === null &&
(dependency.f & DERIVED) !== 0 &&
// Destroying a child effect while updating a parent effect can cause a dependency to appear
// to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps`
// allows us to skip the expensive work of disconnecting and immediately reconnecting it
(new_deps === null || !new_deps.includes(dependency))
) {
set_signal_status(dependency, MAYBE_DIRTY);
// If we are working with a derived that is owned by an effect, then mark it as being
// disconnected.
if ((dependency.f & (UNOWNED | DISCONNECTED)) === 0) {
dependency.f ^= DISCONNECTED;
}
remove_reactions(/** @type {Derived} **/ (dependency), 0);
}
}
/**
* @param {Reaction} signal
* @param {number} start_index
* @returns {void}
*/
function remove_reactions(signal, start_index) {
var dependencies = signal.deps;
if (dependencies === null) return;
for (var i = start_index; i < dependencies.length; i++) {
remove_reaction(signal, dependencies[i]);
}
}
/**
* @param {Effect} effect
* @returns {void}
*/
function update_effect(effect) {
var flags = effect.f;
if ((flags & DESTROYED) !== 0) {
return;
}
set_signal_status(effect, CLEAN);
var previous_effect = active_effect;
var previous_component_context = component_context;
active_effect = effect;
if (DEV) {
var previous_component_fn = dev_current_component_function;
dev_current_component_function = effect.component_function;
}
try {
if ((flags & BLOCK_EFFECT) !== 0) {
destroy_block_effect_children(effect);
} else {
destroy_effect_children(effect);
}
destroy_effect_deriveds(effect);
execute_effect_teardown(effect);
var teardown = update_reaction(effect);
effect.teardown = typeof teardown === 'function' ? teardown : null;
effect.version = current_version;
if (DEV) {
dev_effect_stack.push(effect);
}
} catch (error) {
handle_error(/** @type {Error} */ (error), effect, previous_component_context);
} finally {
active_effect = previous_effect;
if (DEV) {
dev_current_component_function = previous_component_fn;
}
}
}
function infinite_loop_guard() {
if (flush_count > 1000) {
flush_count = 0;
if (DEV) {
try {
effect_update_depth_exceeded();
} catch (error) {
// stack is garbage, ignore. Instead add a console.error message.
define_property(error, 'stack', {
value: ''
});
// eslint-disable-next-line no-console
console.error(
'Last ten effects were: ',
dev_effect_stack.slice(-10).map((d) => d.fn)
);
dev_effect_stack = [];
throw error;
}
} else {
effect_update_depth_exceeded();
}
}
flush_count++;
}
/**
* @param {Array<Effect>} root_effects
* @returns {void}
*/
function flush_queued_root_effects(root_effects) {
var length = root_effects.length;
if (length === 0) {
return;
}
infinite_loop_guard();
var previously_flushing_effect = is_flushing_effect;
is_flushing_effect = true;
try {
for (var i = 0; i < length; i++) {
var effect = root_effects[i];
if ((effect.f & CLEAN) === 0) {
effect.f ^= CLEAN;
}
/** @type {Effect[]} */
var collected_effects = [];
process_effects(effect, collected_effects);
flush_queued_effects(collected_effects);
}
} finally {
is_flushing_effect = previously_flushing_effect;
}
}
/**
* @param {Array<Effect>} effects
* @returns {void}
*/
function flush_queued_effects(effects) {
var length = effects.length;
if (length === 0) return;
for (var i = 0; i < length; i++) {
var effect = effects[i];
if ((effect.f & (DESTROYED | INERT)) === 0 && check_dirtiness(effect)) {
update_effect(effect);
// Effects with no dependencies or teardown do not get added to the effect tree.
// Deferred effects (e.g. `$effect(...)`) _are_ added to the tree because we
// don't know if we need to keep them until they are executed. Doing the check
// here (rather than in `update_effect`) allows us to skip the work for
// immediate effects.
if (effect.deps === null && effect.first === null && effect.nodes_start === null) {
if (effect.teardown === null) {
// remove this effect from the graph
unlink_effect(effect);
} else {
// keep the effect in the graph, but free up some memory
effect.fn = null;
}
}
}
}
}
function process_deferred() {
is_micro_task_queued = false;
if (flush_count > 1001) {
return;
}
const previous_queued_root_effects = queued_root_effects;
queued_root_effects = [];
flush_queued_root_effects(previous_queued_root_effects);
if (!is_micro_task_queued) {
flush_count = 0;
if (DEV) {
dev_effect_stack = [];
}
}
}
/**
* @param {Effect} signal
* @returns {void}
*/
function schedule_effect(signal) {
{
if (!is_micro_task_queued) {
is_micro_task_queued = true;
queueMicrotask(process_deferred);
}
}
var effect = signal;
while (effect.parent !== null) {
effect = effect.parent;
var flags = effect.f;
if ((flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) {
if ((flags & CLEAN) === 0) return;
effect.f ^= CLEAN;
}
}
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 {Effect} effect
* @param {Effect[]} collected_effects
* @returns {void}
*/
function process_effects(effect, collected_effects) {
var current_effect = effect.first;
var effects = [];
main_loop: while (current_effect !== null) {
var flags = current_effect.f;
var is_branch = (flags & BRANCH_EFFECT) !== 0;
var is_skippable_branch = is_branch && (flags & CLEAN) !== 0;
if (!is_skippable_branch && (flags & INERT) === 0) {
if ((flags & RENDER_EFFECT) !== 0) {
if (is_branch) {
current_effect.f ^= CLEAN;
} else if (check_dirtiness(current_effect)) {
update_effect(current_effect);
}
var child = current_effect.first;
if (child !== null) {
current_effect = child;
continue;
}
} else if ((flags & EFFECT) !== 0) {
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;
}
// We might be dealing with many effects here, far more than can be spread into
// an array push call (callstack overflow). So let's deal with each effect in a loop.
for (var i = 0; i < effects.length; i++) {
child = effects[i];
collected_effects.push(child);
process_effects(child, collected_effects);
}
}
/**
* @template V
* @param {Value<V>} signal
* @returns {V}
*/
function get(signal) {
var flags = signal.f;
var is_derived = (flags & DERIVED) !== 0;
// If the derived is destroyed, just execute it again without retaining
// its memoisation properties as the derived is stale
if (is_derived && (flags & DESTROYED) !== 0) {
var value = execute_derived(/** @type {Derived} */ (signal));
// Ensure the derived remains destroyed
destroy_derived(/** @type {Derived} */ (signal));
return value;
}
// Register the dependency on the current reaction signal.
if (active_reaction !== null) {
if (derived_sources !== null && derived_sources.includes(signal)) {
state_unsafe_local_read();
}
var deps = active_reaction.deps;
// If the signal is accessing the same dependencies in the same
// order as it did last time, increment `skipped_deps`
// rather than updating `new_deps`, which creates GC cost
if (new_deps === null && deps !== null && deps[skipped_deps] === signal) {
skipped_deps++;
} else if (new_deps === null) {
new_deps = [signal];
} else {
new_deps.push(signal);
}
if (
untracked_writes !== null &&
active_effect !== null &&
(active_effect.f & CLEAN) !== 0 &&
(active_effect.f & BRANCH_EFFECT) === 0 &&
untracked_writes.includes(signal)
) {
set_signal_status(active_effect, DIRTY);
schedule_effect(active_effect);
}
} else if (is_derived && /** @type {Derived} */ (signal).deps === null) {
var derived = /** @type {Derived} */ (signal);
var parent = derived.parent;
var target = derived;
while (parent !== null) {
// Attach the derived to the nearest parent effect, if there are deriveds
// in between then we also need to attach them too
if ((parent.f & DERIVED) !== 0) {
var parent_derived = /** @type {Derived} */ (parent);
target = parent_derived;
parent = parent_derived.parent;
} else {
var parent_effect = /** @type {Effect} */ (parent);
if (!parent_effect.deriveds?.includes(target)) {
(parent_effect.deriveds ??= []).push(target);
}
break;
}
}
}
if (is_derived) {
derived = /** @type {Derived} */ (signal);
if (check_dirtiness(derived)) {
update_derived(derived);
}
}
return signal.v;
}
const STATUS_MASK = ~(DIRTY | MAYBE_DIRTY | CLEAN);
/**
* @param {Signal} signal
* @param {number} status
* @returns {void}
*/
function set_signal_status(signal, status) {
signal.f = (signal.f & STATUS_MASK) | status;
}
/**
* @param {Record<string, unknown>} props
* @param {any} runes
* @param {Function} [fn]
* @returns {void}
*/
function push(props, runes = false, fn) {
component_context = {
p: component_context,
c: null,
e: null,
m: false,
s: props,
x: null,
l: null
};
if (DEV) {
// component function
component_context.function = fn;
dev_current_component_function = fn;
}
}
/**
* @template {Record<string, any>} T
* @param {T} [component]
* @returns {T}
*/
function pop(component) {
const context_stack_item = component_context;
if (context_stack_item !== null) {
if (component !== undefined) {
context_stack_item.x = component;
}
const component_effects = context_stack_item.e;
if (component_effects !== null) {
var previous_effect = active_effect;
var previous_reaction = active_reaction;
context_stack_item.e = null;
try {
for (var i = 0; i < component_effects.length; i++) {
var component_effect = component_effects[i];
set_active_effect(component_effect.effect);
set_active_reaction(component_effect.reaction);
effect(component_effect.fn);
}
} finally {
set_active_effect(previous_effect);
set_active_reaction(previous_reaction);
}
}
component_context = context_stack_item.p;
if (DEV) {
dev_current_component_function = context_stack_item.p?.function ?? null;
}
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} */ ({});
}
if (DEV) {
/**
* @param {string} rune
*/
function throw_rune_error(rune) {
if (!(rune in globalThis)) {
// TODO if people start adjusting the "this can contain runes" config through v-p-s more, adjust this message
/** @type {any} */
let value; // let's hope noone modifies this global, but belts and braces
Object.defineProperty(globalThis, rune, {
configurable: true,
// eslint-disable-next-line getter-return
get: () => {
if (value !== undefined) {
return value;
}
rune_outside_svelte(rune);
},
set: (v) => {
value = v;
}
});
}
}
throw_rune_error('$state');
throw_rune_error('$effect');
throw_rune_error('$derived');
throw_rune_error('$inspect');
throw_rune_error('$props');
throw_rune_error('$bindable');
}
/** @import { ProxyMetadata, ProxyStateObject, Source } from '#client' */
/**
* @template T
* @param {T} value
* @param {ProxyMetadata | null} [parent]
* @param {Source<T>} [prev] dev mode only
* @returns {T}
*/
function proxy(value, parent = null, prev) {
// if non-proxyable, or is already a proxy, return `value`
if (typeof value !== 'object' || value === null || STATE_SYMBOL in value) {
return value;
}
const prototype = get_prototype_of(value);
if (prototype !== object_prototype && prototype !== array_prototype) {
return value;
}
/** @type {Map<any, Source<any>>} */
var sources = new Map();
var is_proxied_array = is_array(value);
var version = source(0);
if (is_proxied_array) {
// We need to create the length source eagerly to ensure that
// mutations to the array are properly synced with our proxy
sources.set('length', source(/** @type {any[]} */ (value).length));
}
/** @type {ProxyMetadata} */
var metadata;
if (DEV) {
metadata = {
parent,
owners: null
};
if (prev) {
// Reuse owners from previous state; necessary because reassignment is not guaranteed to have correct component context.
// If no previous proxy exists we play it safe and assume ownerless state
// @ts-expect-error
const prev_owners = prev.v?.[STATE_SYMBOL_METADATA]?.owners;
metadata.owners = prev_owners ? new Set(prev_owners) : null;
} else {
metadata.owners =
parent === null
? component_context !== null
? new Set([component_context.function])
: null
: new Set();
}
}
return new Proxy(/** @type {any} */ (value), {
defineProperty(_, prop, descriptor) {
if (
!('value' in descriptor) ||
descriptor.configurable === false ||
descriptor.enumerable === false ||
descriptor.writable === false
) {
// we disallow non-basic descriptors, because unless they are applied to the
// target object — which we avoid, so that state can be forked — we will run
// afoul of the various invariants
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor#invariants
state_descriptors_fixed();
}
var s = sources.get(prop);
if (s === undefined) {
s = source(descriptor.value);
sources.set(prop, s);
} else {
set(s, proxy(descriptor.value, metadata));
}
return true;
},
deleteProperty(target, prop) {
var s = sources.get(prop);
if (s === undefined) {
if (prop in target) {
sources.set(prop, source(UNINITIALIZED));
}
} else {
// When working with arrays, we need to also ensure we update the length when removing
// an indexed property
if (is_proxied_array && typeof prop === 'string') {
var ls = /** @type {Source<number>} */ (sources.get('length'));
var n = Number(prop);
if (Number.isInteger(n) && n < ls.v) {
set(ls, n);
}
}
set(s, UNINITIALIZED);
update_version(version);
}
return true;
},
get(target, prop, receiver) {
if (DEV && prop === STATE_SYMBOL_METADATA) {
return metadata;
}
if (prop === STATE_SYMBOL) {
return value;
}
var s = sources.get(prop);
var exists = prop in target;
// create a source, but only if it's an own property and not a prototype property
if (s === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
s = source(proxy(exists ? target[prop] : UNINITIALIZED, metadata));
sources.set(prop, s);
}
if (s !== undefined) {
var v = get(s);
// In case of something like `foo = bar.map(...)`, foo would have ownership
// of the array itself, while the individual items would have ownership
// of the component that created bar. That means if we later do `foo[0].baz = 42`,
// we could get a false-positive ownership violation, since the two proxies
// are not connected to each other via the parent metadata relationship.
// For this reason, we need to widen the ownership of the children
// upon access when we detect they are not connected.
if (DEV) {
/** @type {ProxyMetadata | undefined} */
var prop_metadata = v?.[STATE_SYMBOL_METADATA];
if (prop_metadata && prop_metadata?.parent !== metadata) {
widen_ownership(metadata, prop_metadata);
}
}
return v === UNINITIALIZED ? undefined : v;
}
return Reflect.get(target, prop, receiver);
},
getOwnPropertyDescriptor(target, prop) {
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
if (descriptor && 'value' in descriptor) {
var s = sources.get(prop);
if (s) descriptor.value = get(s);
} else if (descriptor === undefined) {
var source = sources.get(prop);
var value = source?.v;
if (source !== undefined && value !== UNINITIALIZED) {
return {
enumerable: true,
configurable: true,
value,
writable: true
};
}
}
return descriptor;
},
has(target, prop) {
if (DEV && prop === STATE_SYMBOL_METADATA) {
return true;
}
if (prop === STATE_SYMBOL) {
return true;
}
var s = sources.get(prop);
var has = (s !== undefined && s.v !== UNINITIALIZED) || Reflect.has(target, prop);
if (
s !== undefined ||
(active_effect !== null && (!has || get_descriptor(target, prop)?.writable))
) {
if (s === undefined) {
s = source(has ? proxy(target[prop], metadata) : UNINITIALIZED);
sources.set(prop, s);
}
var value = get(s);
if (value === UNINITIALIZED) {
return false;
}
}
return has;
},
set(target, prop, value, receiver) {
var s = sources.get(prop);
var has = prop in target;
// variable.length = value -> clear all signals with index >= value
if (is_proxied_array && prop === 'length') {
for (var i = value; i < /** @type {Source<number>} */ (s).v; i += 1) {
var other_s = sources.get(i + '');
if (other_s !== undefined) {
set(other_s, UNINITIALIZED);
} else if (i in target) {
// If the item exists in the original, we need to create a uninitialized source,
// else a later read of the property would result in a source being created with
// the value of the original item at that index.
other_s = source(UNINITIALIZED);
sources.set(i + '', other_s);
}
}
}
// 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) {
if (!has || get_descriptor(target, prop)?.writable) {
s = source(undefined);
set(s, proxy(value, metadata));
sources.set(prop, s);
}
} else {
has = s.v !== UNINITIALIZED;
set(s, proxy(value, metadata));
}
if (DEV) {
/** @type {ProxyMetadata | undefined} */
var prop_metadata = value?.[STATE_SYMBOL_METADATA];
if (prop_metadata && prop_metadata?.parent !== metadata) {
widen_ownership(metadata, prop_metadata);
}
check_ownership(metadata);
}
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
// Set the new value before updating any signals so that any listeners get the new value
if (descriptor?.set) {
descriptor.set.call(receiver, value);
}
if (!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_proxied_array && typeof prop === 'string') {
var ls = /** @type {Source<number>} */ (sources.get('length'));
var n = Number(prop);
if (Number.isInteger(n) && n >= ls.v) {
set(ls, n + 1);
}
}
update_version(version);
}
return true;
},
ownKeys(target) {
get(version);
var own_keys = Reflect.ownKeys(target).filter((key) => {
var source = sources.get(key);
return source === undefined || source.v !== UNINITIALIZED;
});
for (var [key, source] of sources) {
if (source.v !== UNINITIALIZED && !(key in target)) {
own_keys.push(key);
}
}
return own_keys;
},
setPrototypeOf() {
state_prototype_fixed();
}
});
}
/**
* @param {Source<number>} signal
* @param {1 | -1} [d]
*/
function update_version(signal, d = 1) {
set(signal, signal.v + d);
}
/**
* @param {any} value
*/
function get_proxied_value(value) {
if (value !== null && typeof value === 'object' && STATE_SYMBOL in value) {
return value[STATE_SYMBOL];
}
return value;
}
/**
* @param {any} a
* @param {any} b
* @param {boolean} equal
* @returns {boolean}
*/
function strict_equals(a, b, equal = true) {
// try-catch needed because this tries to read properties of `a` and `b`,
// which could be disallowed for example in a secure context
try {
if ((a === b) !== (get_proxied_value(a) === get_proxied_value(b))) {
state_proxy_equality_mismatch(equal ? '===' : '!==');
}
} catch {}
return (a === b) === equal;
}
/** @import { TemplateNode } from '#client' */
/** @type {() => Node | null} */
var first_child_getter;
/** @type {() => Node | null} */
var next_sibling_getter;
/**
* @param {string} value
* @returns {Text}
*/
function create_text(value = '') {
return document.createTextNode(value);
}
/**
* @template {Node} N
* @param {N} node
* @returns {Node | null}
*/
/*@__NO_SIDE_EFFECTS__*/
function get_first_child(node) {
return first_child_getter.call(node);
}
/**
* @template {Node} N
* @param {N} node
* @returns {Node | null}
*/
/*@__NO_SIDE_EFFECTS__*/
function get_next_sibling(node) {
return next_sibling_getter.call(node);
}
/**
* Don't mark this as side-effect-free, hydration needs to walk all nodes
* @template {Node} N
* @param {N} node
* @param {boolean} is_text
* @returns {Node | null}
*/
function child(node, is_text) {
{
return get_first_child(node);
}
}
/**
* Don't mark this as side-effect-free, hydration needs to walk all nodes
* @param {DocumentFragment | TemplateNode[]} fragment
* @param {boolean} is_text
* @returns {Node | null}
*/
function first_child(fragment, is_text) {
{
// when not hydrating, `fragment` is a `DocumentFragment` (the result of calling `open_frag`)
var first = /** @type {DocumentFragment} */ (get_first_child(/** @type {Node} */ (fragment)));
// TODO prevent user comments with the empty string when preserveComments is true
if (first instanceof Comment && first.data === '') return get_next_sibling(first);
return first;
}
}
/**
* Don't mark this as side-effect-free, hydration needs to walk all nodes
* @param {TemplateNode} node
* @param {number} count
* @param {boolean} is_text
* @returns {Node | null}
*/
function sibling(node, count = 1, is_text = false) {
let next_sibling = node;
while (count--) {
next_sibling = /** @type {TemplateNode} */ (get_next_sibling(next_sibling));
}
{
return next_sibling;
}
}
/** @import { TemplateNode } from '#client' */
/**
* 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;
/** @import { SourceLocation } from '#shared' */
/**
* @param {any} fn
* @param {string} filename
* @param {SourceLocation[]} locations
* @returns {any}
*/
function add_locations(fn, filename, locations) {
return (/** @type {any[]} */ ...args) => {
const dom = fn(...args);
var node = dom.nodeType === 11 ? dom.firstChild : dom;
assign_locations(node, filename, locations);
return dom;
};
}
/**
* @param {Element} element
* @param {string} filename
* @param {SourceLocation} location
*/
function assign_location(element, filename, location) {
// @ts-expect-error
element.__svelte_meta = {
loc: { file: filename, line: location[0], column: location[1] }
};
if (location[2]) {
assign_locations(element.firstChild, filename, location[2]);
}
}
/**
* @param {Node | null} node
* @param {string} filename
* @param {SourceLocation[]} locations
*/
function assign_locations(node, filename, locations) {
var i = 0;
while (node && i < locations.length) {
if (node.nodeType === 1) {
assign_location(/** @type {Element} */ (node), filename, locations[i++]);
}
node = node.nextSibling;
}
}
/** @param {string} html */
function create_fragment_from_html(html) {
var elem = document.createElement('template');
elem.innerHTML = html;
return elem.content;
}
/** @import { Effect, TemplateNode } from '#client' */
/**
* @param {TemplateNode} start
* @param {TemplateNode | null} end
*/
function assign_nodes(start, end) {
var effect = /** @type {Effect} */ (active_effect);
if (effect.nodes_start === null) {
effect.nodes_start = start;
effect.nodes_end = end;
}
}
/**
* @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;
/**
* Whether or not the first item is a text/element node. If not, we need to
* create an additional comment node to act as `effect.nodes.start`
*/
var has_start = !content.startsWith('<!>');
return () => {
if (node === undefined) {
node = create_fragment_from_html(has_start ? content : '<!>' + content);
if (!is_fragment) node = /** @type {Node} */ (get_first_child(node));
}
var clone = /** @type {TemplateNode} */ (
use_import_node ? document.importNode(node, true) : node.cloneNode(true)
);
if (is_fragment) {
var start = /** @type {TemplateNode} */ (get_first_child(clone));
var end = /** @type {TemplateNode} */ (clone.lastChild);
assign_nodes(start, end);
} else {
assign_nodes(clone, clone);
}
return clone;
};
}
function comment() {
var frag = document.createDocumentFragment();
var start = document.createComment('');
var anchor = create_text();
frag.append(start, anchor);
assign_nodes(start, anchor);
return frag;
}
/**
* 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 {DocumentFragment | Element} dom
*/
function append(anchor, dom) {
if (anchor === null) {
// edge case — void `<svelte:element>` with content
return;
}
anchor.before(/** @type {Node} */ (dom));
}
/** @import { ComponentContext, Effect, TemplateNode } from '#client' */
/** @import { Component, ComponentType, SvelteComponent, MountOptions } from '../../index.js' */
/**
* @param {Element} text
* @param {string} value
* @returns {void}
*/
function set_text(text, value) {
// For objects, we apply string coercion (which might make things like $state array references in the template reactive) before diffing
var str = value == null ? '' : typeof value === 'object' ? value + '' : value;
// @ts-expect-error
if (str !== (text.__t ??= text.nodeValue)) {
// @ts-expect-error
text.__t = str;
text.nodeValue = str == null ? '' : str + '';
}
}
/** @param {Function & { [FILENAME]: string }} target */
function check_target(target) {
if (target) {
component_api_invalid_new(target[FILENAME] ?? 'a component', target.name);
}
}
function legacy_api() {
const component = component_context?.function;
/** @param {string} method */
function error(method) {
// @ts-expect-error
const parent = get_component()?.[FILENAME] ?? 'Something';
component_api_changed(parent, method, component[FILENAME]);
}
return {
$destroy: () => error('$destroy()'),
$on: () => error('$on(...)'),
$set: () => error('$set(...)')
};
}
/** @import { Effect, TemplateNode } from '#client' */
/**
* @param {TemplateNode} node
* @param {() => boolean} get_condition
* @param {(anchor: Node) => void} consequent_fn
* @param {null | ((anchor: Node) => void)} [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(node, get_condition, consequent_fn, alternate_fn = null, elseif = false) {
var anchor = node;
/** @type {Effect | null} */
var consequent_effect = null;
/** @type {Effect | null} */
var alternate_effect = null;
/** @type {boolean | null} */
var condition = null;
var flags = elseif ? EFFECT_TRANSPARENT : 0;
block(() => {
if (condition === (condition = !!get_condition())) return;
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;
});
}
}
}, flags);
}
/**
* @param {HTMLElement} dom
* @param {string} value
* @returns {void}
*/
function set_class(dom, value) {
// @ts-expect-error need to add __className to patched prototype
var prev_class_name = dom.__className;
var next_class_name = to_class(value);
if (
prev_class_name !== next_class_name ||
(hydrating)
) {
// Removing the attribute when the value is only an empty string causes
// peformance issues vs simply making the className an empty string. So
// we should only remove the class if the the value is nullish.
if (value == null) {
dom.removeAttribute('class');
} else {
dom.className = next_class_name;
}
// @ts-expect-error need to add __className to patched prototype
dom.__className = next_class_name;
}
}
/**
* @template V
* @param {V} value
* @returns {string | V}
*/
function to_class(value) {
return value == null ? '' : value;
}
/** @import { Source } from './types.js' */
/**
* 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 runes = !legacy_mode_flag;
var bindable = (flags & PROPS_IS_BINDABLE) !== 0;
var prop_value;
{
prop_value = /** @type {V} */ (props[key]);
}
// Can be the case when someone does `mount(Component, props)` with `let props = $state({...})`
// or `createClassComponent(Component, props)`
var is_entry_props = STATE_SYMBOL in props || LEGACY_PROPS in props;
var setter =
get_descriptor(props, key)?.set ??
(is_entry_props && bindable && key in props ? (v) => (props[key] = v) : undefined);
var fallback_value = /** @type {V} */ (fallback);
var fallback_dirty = true;
var get_fallback = () => {
if (fallback_dirty) {
fallback_dirty = false;
{
fallback_value = /** @type {V} */ (fallback);
}
}
return fallback_value;
};
if (prop_value === undefined && fallback !== undefined) {
if (setter && runes) {
props_invalid_value(key);
}
prop_value = get_fallback();
if (setter) setter(prop_value);
}
/** @type {() => V} */
var getter;
{
getter = () => {
var value = /** @type {V} */ (props[key]);
if (value === undefined) return get_fallback();
fallback_dirty = true;
return value;
};
}
// easy mode — prop is never written to
{
return getter;
}
}
/**
* @param {Record<string, any>} $$props
* @param {string[]} bindable
* @param {string[]} exports
* @param {Function & { [FILENAME]: string }} component
*/
function validate_prop_bindings($$props, bindable, exports, component) {
for (const key in $$props) {
var setter = get_descriptor($$props, key)?.set;
var name = component.name;
if (setter) {
if (exports.includes(key)) {
bind_invalid_export(component[FILENAME], key, name);
}
if (!bindable.includes(key)) {
bind_not_bindable(key, component[FILENAME], name);
}
}
}
}
const CLASS_PART_SEPARATOR = '-';
const createClassGroupUtils = config => {
const classMap = createClassMap(config);
const {
conflictingClassGroups,
conflictingClassGroupModifiers
} = config;
const getClassGroupId = className => {
const classParts = className.split(CLASS_PART_SEPARATOR);
// Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and remove it from classParts.
if (classParts[0] === '' && classParts.length !== 1) {
classParts.shift();
}
return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className);
};
const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {
const conflicts = conflictingClassGroups[classGroupId] || [];
if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]];
}
return conflicts;
};
return {
getClassGroupId,
getConflictingClassGroupIds
};
};
const getGroupRecursive = (classParts, classPartObject) => {
if (classParts.length === 0) {
return classPartObject.classGroupId;
}
const currentClassPart = classParts[0];
const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);
const classGroupFromNextClassPart = nextClassPartObject ? getGroupRecursive(classParts.slice(1), nextClassPartObject) : undefined;
if (classGroupFromNextClassPart) {
return classGroupFromNextClassPart;
}
if (classPartObject.validators.length === 0) {
return undefined;
}
const classRest = classParts.join(CLASS_PART_SEPARATOR);
return classPartObject.validators.find(({
validator
}) => validator(classRest))?.classGroupId;
};
const arbitraryPropertyRegex = /^\[(.+)\]$/;
const getGroupIdForArbitraryProperty = className => {
if (arbitraryPropertyRegex.test(className)) {
const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(':'));
if (property) {
// I use two dots here because one dot is used as prefix for class groups in plugins
return 'arbitrary..' + property;
}
}
};
/**
* Exported for testing only
*/
const createClassMap = config => {
const {
theme,
prefix
} = config;
const classMap = {
nextPart: new Map(),
validators: []
};
const prefixedClassGroupEntries = getPrefixedClassGroupEntries(Object.entries(config.classGroups), prefix);
prefixedClassGroupEntries.forEach(([classGroupId, classGroup]) => {
processClassesRecursively(classGroup, classMap, classGroupId, theme);
});
return classMap;
};
const processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {
classGroup.forEach(classDefinition => {
if (typeof classDefinition === 'string') {
const classPartObjectToEdit = classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition);
classPartObjectToEdit.classGroupId = classGroupId;
return;
}
if (typeof classDefinition === 'function') {
if (isThemeGetter(classDefinition)) {
processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);
return;
}
classPartObject.validators.push({
validator: classDefinition,
classGroupId
});
return;
}
Object.entries(classDefinition).forEach(([key, classGroup]) => {
processClassesRecursively(classGroup, getPart(classPartObject, key), classGroupId, theme);
});
});
};
const getPart = (classPartObject, path) => {
let currentClassPartObject = classPartObject;
path.split(CLASS_PART_SEPARATOR).forEach(pathPart => {
if (!currentClassPartObject.nextPart.has(pathPart)) {
currentClassPartObject.nextPart.set(pathPart, {
nextPart: new Map(),
validators: []
});
}
currentClassPartObject = currentClassPartObject.nextPart.get(pathPart);
});
return currentClassPartObject;
};
const isThemeGetter = func => func.isThemeGetter;
const getPrefixedClassGroupEntries = (classGroupEntries, prefix) => {
if (!prefix) {
return classGroupEntries;
}
return classGroupEntries.map(([classGroupId, classGroup]) => {
const prefixedClassGroup = classGroup.map(classDefinition => {
if (typeof classDefinition === 'string') {
return prefix + classDefinition;
}
if (typeof classDefinition === 'object') {
return Object.fromEntries(Object.entries(classDefinition).map(([key, value]) => [prefix + key, value]));
}
return classDefinition;
});
return [classGroupId, prefixedClassGroup];
});
};
// LRU cache inspired from hashlru (https://github.com/dominictarr/hashlru/blob/v1.0.4/index.js) but object replaced with Map to improve performance
const createLruCache = maxCacheSize => {
if (maxCacheSize < 1) {
return {
get: () => undefined,
set: () => {}
};
}
let cacheSize = 0;
let cache = new Map();
let previousCache = new Map();
const update = (key, value) => {
cache.set(key, value);
cacheSize++;
if (cacheSize > maxCacheSize) {
cacheSize = 0;
previousCache = cache;
cache = new Map();
}
};
return {
get(key) {
let value = cache.get(key);
if (value !== undefined) {
return value;
}
if ((value = previousCache.get(key)) !== undefined) {
update(key, value);
return value;
}
},
set(key, value) {
if (cache.has(key)) {
cache.set(key, value);
} else {
update(key, value);
}
}
};
};
const IMPORTANT_MODIFIER = '!';
const createParseClassName = config => {
const {
separator,
experimentalParseClassName
} = config;
const isSeparatorSingleCharacter = separator.length === 1;
const firstSeparatorCharacter = separator[0];
const separatorLength = separator.length;
// parseClassName inspired by https://github.com/tailwindlabs/tailwindcss/blob/v3.2.2/src/util/splitAtTopLevelOnly.js
const parseClassName = className => {
const modifiers = [];
let bracketDepth = 0;
let modifierStart = 0;
let postfixModifierPosition;
for (let index = 0; index < className.length; index++) {
let currentCharacter = className[index];
if (bracketDepth === 0) {
if (currentCharacter === firstSeparatorCharacter && (isSeparatorSingleCharacter || className.slice(index, index + separatorLength) === separator)) {
modifiers.push(className.slice(modifierStart, index));
modifierStart = index + separatorLength;
continue;
}
if (currentCharacter === '/') {
postfixModifierPosition = index;
continue;
}
}
if (currentCharacter === '[') {
bracketDepth++;
} else if (currentCharacter === ']') {
bracketDepth--;
}
}
const baseClassNameWithImportantModifier = modifiers.length === 0 ? className : className.substring(modifierStart);
const hasImportantModifier = baseClassNameWithImportantModifier.startsWith(IMPORTANT_MODIFIER);
const baseClassName = hasImportantModifier ? baseClassNameWithImportantModifier.substring(1) : baseClassNameWithImportantModifier;
const maybePostfixModifierPosition = postfixModifierPosition && postfixModifierPosition > modifierStart ? postfixModifierPosition - modifierStart : undefined;
return {
modifiers,
hasImportantModifier,
baseClassName,
maybePostfixModifierPosition
};
};
if (experimentalParseClassName) {
return className => experimentalParseClassName({
className,
parseClassName
});
}
return parseClassName;
};
/**
* Sorts modifiers according to following schema:
* - Predefined modifiers are sorted alphabetically
* - When an arbitrary variant appears, it must be preserved which modifiers are before and after it
*/
const sortModifiers = modifiers => {
if (modifiers.length <= 1) {
return modifiers;
}
const sortedModifiers = [];
let unsortedModifiers = [];
modifiers.forEach(modifier => {
const isArbitraryVariant = modifier[0] === '[';
if (isArbitraryVariant) {
sortedModifiers.push(...unsortedModifiers.sort(), modifier);
unsortedModifiers = [];
} else {
unsortedModifiers.push(modifier);
}
});
sortedModifiers.push(...unsortedModifiers.sort());
return sortedModifiers;
};
const createConfigUtils = config => ({
cache: createLruCache(config.cacheSize),
parseClassName: createParseClassName(config),
...createClassGroupUtils(config)
});
const SPLIT_CLASSES_REGEX = /\s+/;
const mergeClassList = (classList, configUtils) => {
const {
parseClassName,
getClassGroupId,
getConflictingClassGroupIds
} = configUtils;
/**
* Set of classGroupIds in following format:
* `{importantModifier}{variantModifiers}{classGroupId}`
* @example 'float'
* @example 'hover:focus:bg-color'
* @example 'md:!pr'
*/
const classGroupsInConflict = [];
const classNames = classList.trim().split(SPLIT_CLASSES_REGEX);
let result = '';
for (let index = classNames.length - 1; index >= 0; index -= 1) {
const originalClassName = classNames[index];
const {
modifiers,
hasImportantModifier,
baseClassName,
maybePostfixModifierPosition
} = parseClassName(originalClassName);
let hasPostfixModifier = Boolean(maybePostfixModifierPosition);
let classGroupId = getClassGroupId(hasPostfixModifier ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName);
if (!classGroupId) {
if (!hasPostfixModifier) {
// Not a Tailwind class
result = originalClassName + (result.length > 0 ? ' ' + result : result);
continue;
}
classGroupId = getClassGroupId(baseClassName);
if (!classGroupId) {
// Not a Tailwind class
result = originalClassName + (result.length > 0 ? ' ' + result : result);
continue;
}
hasPostfixModifier = false;
}
const variantModifier = sortModifiers(modifiers).join(':');
const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier;
const classId = modifierId + classGroupId;
if (classGroupsInConflict.includes(classId)) {
// Tailwind class omitted due to conflict
continue;
}
classGroupsInConflict.push(classId);
const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier);
for (let i = 0; i < conflictGroups.length; ++i) {
const group = conflictGroups[i];
classGroupsInConflict.push(modifierId + group);
}
// Tailwind class not in conflict
result = originalClassName + (result.length > 0 ? ' ' + result : result);
}
return result;
};
/**
* The code in this file is copied from https://github.com/lukeed/clsx and modified to suit the needs of tailwind-merge better.
*
* Specifically:
* - Runtime code from https://github.com/lukeed/clsx/blob/v1.2.1/src/index.js
* - TypeScript types from https://github.com/lukeed/clsx/blob/v1.2.1/clsx.d.ts
*
* Original code has MIT license: Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
*/
function twJoin() {
let index = 0;
let argument;
let resolvedValue;
let string = '';
while (index < arguments.length) {
if (argument = arguments[index++]) {
if (resolvedValue = toValue(argument)) {
string && (string += ' ');
string += resolvedValue;
}
}
}
return string;
}
const toValue = mix => {
if (typeof mix === 'string') {
return mix;
}
let resolvedValue;
let string = '';
for (let k = 0; k < mix.length; k++) {
if (mix[k]) {
if (resolvedValue = toValue(mix[k])) {
string && (string += ' ');
string += resolvedValue;
}
}
}
return string;
};
function createTailwindMerge(createConfigFirst, ...createConfigRest) {
let configUtils;
let cacheGet;
let cacheSet;
let functionToCall = initTailwindMerge;
function initTailwindMerge(classList) {
const config = createConfigRest.reduce((previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), createConfigFirst());
configUtils = createConfigUtils(config);
cacheGet = configUtils.cache.get;
cacheSet = configUtils.cache.set;
functionToCall = tailwindMerge;
return tailwindMerge(classList);
}
function tailwindMerge(classList) {
const cachedResult = cacheGet(classList);
if (cachedResult) {
return cachedResult;
}
const result = mergeClassList(classList, configUtils);
cacheSet(classList, result);
return result;
}
return function callTailwindMerge() {
return functionToCall(twJoin.apply(null, arguments));
};
}
const fromTheme = key => {
const themeGetter = theme => theme[key] || [];
themeGetter.isThemeGetter = true;
return themeGetter;
};
const arbitraryValueRegex = /^\[(?:([a-z-]+):)?(.+)\]$/i;
const fractionRegex = /^\d+\/\d+$/;
const stringLengths = /*#__PURE__*/new Set(['px', 'full', 'screen']);
const tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/;
const lengthUnitRegex = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/;
const colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/;
// Shadow always begins with x and y offset separated by underscore optionally prepended by inset
const shadowRegex = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/;
const imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/;
const isLength = value => isNumber(value) || stringLengths.has(value) || fractionRegex.test(value);
const isArbitraryLength = value => getIsArbitraryValue(value, 'length', isLengthOnly);
const isNumber = value => Boolean(value) && !Number.isNaN(Number(value));
const isArbitraryNumber = value => getIsArbitraryValue(value, 'number', isNumber);
const isInteger = value => Boolean(value) && Number.isInteger(Number(value));
const isPercent = value => value.endsWith('%') && isNumber(value.slice(0, -1));
const isArbitraryValue = value => arbitraryValueRegex.test(value);
const isTshirtSize = value => tshirtUnitRegex.test(value);
const sizeLabels = /*#__PURE__*/new Set(['length', 'size', 'percentage']);
const isArbitrarySize = value => getIsArbitraryValue(value, sizeLabels, isNever);
const isArbitraryPosition = value => getIsArbitraryValue(value, 'position', isNever);
const imageLabels = /*#__PURE__*/new Set(['image', 'url']);
const isArbitraryImage = value => getIsArbitraryValue(value, imageLabels, isImage);
const isArbitraryShadow = value => getIsArbitraryValue(value, '', isShadow);
const isAny = () => true;
const getIsArbitraryValue = (value, label, testValue) => {
const result = arbitraryValueRegex.exec(value);
if (result) {
if (result[1]) {
return typeof label === 'string' ? result[1] === label : label.has(result[1]);
}
return testValue(result[2]);
}
return false;
};
const isLengthOnly = value =>
// `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths.
// For example, `hsl(0 0% 0%)` would be classified as a length without this check.
// I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough.
lengthUnitRegex.test(value) && !colorFunctionRegex.test(value);
const isNever = () => false;
const isShadow = value => shadowRegex.test(value);
const isImage = value => imageRegex.test(value);
const getDefaultConfig = () => {
const colors = fromTheme('colors');
const spacing = fromTheme('spacing');
const blur = fromTheme('blur');
const brightness = fromTheme('brightness');
const borderColor = fromTheme('borderColor');
const borderRadius = fromTheme('borderRadius');
const borderSpacing = fromTheme('borderSpacing');
const borderWidth = fromTheme('borderWidth');
const contrast = fromTheme('contrast');
const grayscale = fromTheme('grayscale');
const hueRotate = fromTheme('hueRotate');
const invert = fromTheme('invert');
const gap = fromTheme('gap');
const gradientColorStops = fromTheme('gradientColorStops');
const gradientColorStopPositions = fromTheme('gradientColorStopPositions');
const inset = fromTheme('inset');
const margin = fromTheme('margin');
const opacity = fromTheme('opacity');
const padding = fromTheme('padding');
const saturate = fromTheme('saturate');
const scale = fromTheme('scale');
const sepia = fromTheme('sepia');
const skew = fromTheme('skew');
const space = fromTheme('space');
const translate = fromTheme('translate');
const getOverscroll = () => ['auto', 'contain', 'none'];
const getOverflow = () => ['auto', 'hidden', 'clip', 'visible', 'scroll'];
const getSpacingWithAutoAndArbitrary = () => ['auto', isArbitraryValue, spacing];
const getSpacingWithArbitrary = () => [isArbitraryValue, spacing];
const getLengthWithEmptyAndArbitrary = () => ['', isLength, isArbitraryLength];
const getNumberWithAutoAndArbitrary = () => ['auto', isNumber, isArbitraryValue];
const getPositions = () => ['bottom', 'center', 'left', 'left-bottom', 'left-top', 'right', 'right-bottom', 'right-top', 'top'];
const getLineStyles = () => ['solid', 'dashed', 'dotted', 'double', 'none'];
const getBlendModes = () => ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'];
const getAlign = () => ['start', 'end', 'center', 'between', 'around', 'evenly', 'stretch'];
const getZeroAndEmpty = () => ['', '0', isArbitraryValue];
const getBreaks = () => ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column'];
const getNumberAndArbitrary = () => [isNumber, isArbitraryValue];
return {
cacheSize: 500,
separator: ':',
theme: {
colors: [isAny],
spacing: [isLength, isArbitraryLength],
blur: ['none', '', isTshirtSize, isArbitraryValue],
brightness: getNumberAndArbitrary(),
borderColor: [colors],
borderRadius: ['none', '', 'full', isTshirtSize, isArbitraryValue],
borderSpacing: getSpacingWithArbitrary(),
borderWidth: getLengthWithEmptyAndArbitrary(),
contrast: getNumberAndArbitrary(),
grayscale: getZeroAndEmpty(),
hueRotate: getNumberAndArbitrary(),
invert: getZeroAndEmpty(),
gap: getSpacingWithArbitrary(),
gradientColorStops: [colors],
gradientColorStopPositions: [isPercent, isArbitraryLength],
inset: getSpacingWithAutoAndArbitrary(),
margin: getSpacingWithAutoAndArbitrary(),
opacity: getNumberAndArbitrary(),
padding: getSpacingWithArbitrary(),
saturate: getNumberAndArbitrary(),
scale: getNumberAndArbitrary(),
sepia: getZeroAndEmpty(),
skew: getNumberAndArbitrary(),
space: getSpacingWithArbitrary(),
translate: getSpacingWithArbitrary()
},
classGroups: {
// Layout
/**
* Aspect Ratio
* @see https://tailwindcss.com/docs/aspect-ratio
*/
aspect: [{
aspect: ['auto', 'square', 'video', isArbitraryValue]
}],
/**
* Container
* @see https://tailwindcss.com/docs/container
*/
container: ['container'],
/**
* Columns
* @see https://tailwindcss.com/docs/columns
*/
columns: [{
columns: [isTshirtSize]
}],
/**
* Break After
* @see https://tailwindcss.com/docs/break-after
*/
'break-after': [{
'break-after': getBreaks()
}],
/**
* Break Before
* @see https://tailwindcss.com/docs/break-before
*/
'break-before': [{
'break-before': getBreaks()
}],
/**
* Break Inside
* @see https://tailwindcss.com/docs/break-inside
*/
'break-inside': [{
'break-inside': ['auto', 'avoid', 'avoid-page', 'avoid-column']
}],
/**
* Box Decoration Break
* @see https://tailwindcss.com/docs/box-decoration-break
*/
'box-decoration': [{
'box-decoration': ['slice', 'clone']
}],
/**
* Box Sizing
* @see https://tailwindcss.com/docs/box-sizing
*/
box: [{
box: ['border', 'content']
}],
/**
* Display
* @see https://tailwindcss.com/docs/display
*/
display: ['block', 'inline-block', 'inline', 'flex', 'inline-flex', 'table', 'inline-table', 'table-caption', 'table-cell', 'table-column', 'table-column-group', 'table-footer-group', 'table-header-group', 'table-row-group', 'table-row', 'flow-root', 'grid', 'inline-grid', 'contents', 'list-item', 'hidden'],
/**
* Floats
* @see https://tailwindcss.com/docs/float
*/
float: [{
float: ['right', 'left', 'none', 'start', 'end']
}],
/**
* Clear
* @see https://tailwindcss.com/docs/clear
*/
clear: [{
clear: ['left', 'right', 'both', 'none', 'start', 'end']
}],
/**
* Isolation
* @see https://tailwindcss.com/docs/isolation
*/
isolation: ['isolate', 'isolation-auto'],
/**
* Object Fit
* @see https://tailwindcss.com/docs/object-fit
*/
'object-fit': [{
object: ['contain', 'cover', 'fill', 'none', 'scale-down']
}],
/**
* Object Position
* @see https://tailwindcss.com/docs/object-position
*/
'object-position': [{
object: [...getPositions(), isArbitraryValue]
}],
/**
* Overflow
* @see https://tailwindcss.com/docs/overflow
*/
overflow: [{
overflow: getOverflow()
}],
/**
* Overflow X
* @see https://tailwindcss.com/docs/overflow
*/
'overflow-x': [{
'overflow-x': getOverflow()
}],
/**
* Overflow Y
* @see https://tailwindcss.com/docs/overflow
*/
'overflow-y': [{
'overflow-y': getOverflow()
}],
/**
* Overscroll Behavior
* @see https://tailwindcss.com/docs/overscroll-behavior
*/
overscroll: [{
overscroll: getOverscroll()
}],
/**
* Overscroll Behavior X
* @see https://tailwindcss.com/docs/overscroll-behavior
*/
'overscroll-x': [{
'overscroll-x': getOverscroll()
}],
/**
* Overscroll Behavior Y
* @see https://tailwindcss.com/docs/overscroll-behavior
*/
'overscroll-y': [{
'overscroll-y': getOverscroll()
}],
/**
* Position
* @see https://tailwindcss.com/docs/position
*/
position: ['static', 'fixed', 'absolute', 'relative', 'sticky'],
/**
* Top / Right / Bottom / Left
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
inset: [{
inset: [inset]
}],
/**
* Right / Left
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
'inset-x': [{
'inset-x': [inset]
}],
/**
* Top / Bottom
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
'inset-y': [{
'inset-y': [inset]
}],
/**
* Start
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
start: [{
start: [inset]
}],
/**
* End
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
end: [{
end: [inset]
}],
/**
* Top
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
top: [{
top: [inset]
}],
/**
* Right
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
right: [{
right: [inset]
}],
/**
* Bottom
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
bottom: [{
bottom: [inset]
}],
/**
* Left
* @see https://tailwindcss.com/docs/top-right-bottom-left
*/
left: [{
left: [inset]
}],
/**
* Visibility
* @see https://tailwindcss.com/docs/visibility
*/
visibility: ['visible', 'invisible', 'collapse'],
/**
* Z-Index
* @see https://tailwindcss.com/docs/z-index
*/
z: [{
z: ['auto', isInteger, isArbitraryValue]
}],
// Flexbox and Grid
/**
* Flex Basis
* @see https://tailwindcss.com/docs/flex-basis
*/
basis: [{
basis: getSpacingWithAutoAndArbitrary()
}],
/**
* Flex Direction
* @see https://tailwindcss.com/docs/flex-direction
*/
'flex-direction': [{
flex: ['row', 'row-reverse', 'col', 'col-reverse']
}],
/**
* Flex Wrap
* @see https://tailwindcss.com/docs/flex-wrap
*/
'flex-wrap': [{
flex: ['wrap', 'wrap-reverse', 'nowrap']
}],
/**
* Flex
* @see https://tailwindcss.com/docs/flex
*/
flex: [{
flex: ['1', 'auto', 'initial', 'none', isArbitraryValue]
}],
/**
* Flex Grow
* @see https://tailwindcss.com/docs/flex-grow
*/
grow: [{
grow: getZeroAndEmpty()
}],
/**
* Flex Shrink
* @see https://tailwindcss.com/docs/flex-shrink
*/
shrink: [{
shrink: getZeroAndEmpty()
}],
/**
* Order
* @see https://tailwindcss.com/docs/order
*/
order: [{
order: ['first', 'last', 'none', isInteger, isArbitraryValue]
}],
/**
* Grid Template Columns
* @see https://tailwindcss.com/docs/grid-template-columns
*/
'grid-cols': [{
'grid-cols': [isAny]
}],
/**
* Grid Column Start / End
* @see https://tailwindcss.com/docs/grid-column
*/
'col-start-end': [{
col: ['auto', {
span: ['full', isInteger, isArbitraryValue]
}, isArbitraryValue]
}],
/**
* Grid Column Start
* @see https://tailwindcss.com/docs/grid-column
*/
'col-start': [{
'col-start': getNumberWithAutoAndArbitrary()
}],
/**
* Grid Column End
* @see https://tailwindcss.com/docs/grid-column
*/
'col-end': [{
'col-end': getNumberWithAutoAndArbitrary()
}],
/**
* Grid Template Rows
* @see https://tailwindcss.com/docs/grid-template-rows
*/
'grid-rows': [{
'grid-rows': [isAny]
}],
/**
* Grid Row Start / End
* @see https://tailwindcss.com/docs/grid-row
*/
'row-start-end': [{
row: ['auto', {
span: [isInteger, isArbitraryValue]
}, isArbitraryValue]
}],
/**
* Grid Row Start
* @see https://tailwindcss.com/docs/grid-row
*/
'row-start': [{
'row-start': getNumberWithAutoAndArbitrary()
}],
/**
* Grid Row End
* @see https://tailwindcss.com/docs/grid-row
*/
'row-end': [{
'row-end': getNumberWithAutoAndArbitrary()
}],
/**
* Grid Auto Flow
* @see https://tailwindcss.com/docs/grid-auto-flow
*/
'grid-flow': [{
'grid-flow': ['row', 'col', 'dense', 'row-dense', 'col-dense']
}],
/**
* Grid Auto Columns
* @see https://tailwindcss.com/docs/grid-auto-columns
*/
'auto-cols': [{
'auto-cols': ['auto', 'min', 'max', 'fr', isArbitraryValue]
}],
/**
* Grid Auto Rows
* @see https://tailwindcss.com/docs/grid-auto-rows
*/
'auto-rows': [{
'auto-rows': ['auto', 'min', 'max', 'fr', isArbitraryValue]
}],
/**
* Gap
* @see https://tailwindcss.com/docs/gap
*/
gap: [{
gap: [gap]
}],
/**
* Gap X
* @see https://tailwindcss.com/docs/gap
*/
'gap-x': [{
'gap-x': [gap]
}],
/**
* Gap Y
* @see https://tailwindcss.com/docs/gap
*/
'gap-y': [{
'gap-y': [gap]
}],
/**
* Justify Content
* @see https://tailwindcss.com/docs/justify-content
*/
'justify-content': [{
justify: ['normal', ...getAlign()]
}],
/**
* Justify Items
* @see https://tailwindcss.com/docs/justify-items
*/
'justify-items': [{
'justify-items': ['start', 'end', 'center', 'stretch']
}],
/**
* Justify Self
* @see https://tailwindcss.com/docs/justify-self
*/
'justify-self': [{
'justify-self': ['auto', 'start', 'end', 'center', 'stretch']
}],
/**
* Align Content
* @see https://tailwindcss.com/docs/align-content
*/
'align-content': [{
content: ['normal', ...getAlign(), 'baseline']
}],
/**
* Align Items
* @see https://tailwindcss.com/docs/align-items
*/
'align-items': [{
items: ['start', 'end', 'center', 'baseline', 'stretch']
}],
/**
* Align Self
* @see https://tailwindcss.com/docs/align-self
*/
'align-self': [{
self: ['auto', 'start', 'end', 'center', 'stretch', 'baseline']
}],
/**
* Place Content
* @see https://tailwindcss.com/docs/place-content
*/
'place-content': [{
'place-content': [...getAlign(), 'baseline']
}],
/**
* Place Items
* @see https://tailwindcss.com/docs/place-items
*/
'place-items': [{
'place-items': ['start', 'end', 'center', 'baseline', 'stretch']
}],
/**
* Place Self
* @see https://tailwindcss.com/docs/place-self
*/
'place-self': [{
'place-self': ['auto', 'start', 'end', 'center', 'stretch']
}],
// Spacing
/**
* Padding
* @see https://tailwindcss.com/docs/padding
*/
p: [{
p: [padding]
}],
/**
* Padding X
* @see https://tailwindcss.com/docs/padding
*/
px: [{
px: [padding]
}],
/**
* Padding Y
* @see https://tailwindcss.com/docs/padding
*/
py: [{
py: [padding]
}],
/**
* Padding Start
* @see https://tailwindcss.com/docs/padding
*/
ps: [{
ps: [padding]
}],
/**
* Padding End
* @see https://tailwindcss.com/docs/padding
*/
pe: [{
pe: [padding]
}],
/**
* Padding Top
* @see https://tailwindcss.com/docs/padding
*/
pt: [{
pt: [padding]
}],
/**
* Padding Right
* @see https://tailwindcss.com/docs/padding
*/
pr: [{
pr: [padding]
}],
/**
* Padding Bottom
* @see https://tailwindcss.com/docs/padding
*/
pb: [{
pb: [padding]
}],
/**
* Padding Left
* @see https://tailwindcss.com/docs/padding
*/
pl: [{
pl: [padding]
}],
/**
* Margin
* @see https://tailwindcss.com/docs/margin
*/
m: [{
m: [margin]
}],
/**
* Margin X
* @see https://tailwindcss.com/docs/margin
*/
mx: [{
mx: [margin]
}],
/**
* Margin Y
* @see https://tailwindcss.com/docs/margin
*/
my: [{
my: [margin]
}],
/**
* Margin Start
* @see https://tailwindcss.com/docs/margin
*/
ms: [{
ms: [margin]
}],
/**
* Margin End
* @see https://tailwindcss.com/docs/margin
*/
me: [{
me: [margin]
}],
/**
* Margin Top
* @see https://tailwindcss.com/docs/margin
*/
mt: [{
mt: [margin]
}],
/**
* Margin Right
* @see https://tailwindcss.com/docs/margin
*/
mr: [{
mr: [margin]
}],
/**
* Margin Bottom
* @see https://tailwindcss.com/docs/margin
*/
mb: [{
mb: [margin]
}],
/**
* Margin Left
* @see https://tailwindcss.com/docs/margin
*/
ml: [{
ml: [margin]
}],
/**
* Space Between X
* @see https://tailwindcss.com/docs/space
*/
'space-x': [{
'space-x': [space]
}],
/**
* Space Between X Reverse
* @see https://tailwindcss.com/docs/space
*/
'space-x-reverse': ['space-x-reverse'],
/**
* Space Between Y
* @see https://tailwindcss.com/docs/space
*/
'space-y': [{
'space-y': [space]
}],
/**
* Space Between Y Reverse
* @see https://tailwindcss.com/docs/space
*/
'space-y-reverse': ['space-y-reverse'],
// Sizing
/**
* Width
* @see https://tailwindcss.com/docs/width
*/
w: [{
w: ['auto', 'min', 'max', 'fit', 'svw', 'lvw', 'dvw', isArbitraryValue, spacing]
}],
/**
* Min-Width
* @see https://tailwindcss.com/docs/min-width
*/
'min-w': [{
'min-w': [isArbitraryValue, spacing, 'min', 'max', 'fit']
}],
/**
* Max-Width
* @see https://tailwindcss.com/docs/max-width
*/
'max-w': [{
'max-w': [isArbitraryValue, spacing, 'none', 'full', 'min', 'max', 'fit', 'prose', {
screen: [isTshirtSize]
}, isTshirtSize]
}],
/**
* Height
* @see https://tailwindcss.com/docs/height
*/
h: [{
h: [isArbitraryValue, spacing, 'auto', 'min', 'max', 'fit', 'svh', 'lvh', 'dvh']
}],
/**
* Min-Height
* @see https://tailwindcss.com/docs/min-height
*/
'min-h': [{
'min-h': [isArbitraryValue, spacing, 'min', 'max', 'fit', 'svh', 'lvh', 'dvh']
}],
/**
* Max-Height
* @see https://tailwindcss.com/docs/max-height
*/
'max-h': [{
'max-h': [isArbitraryValue, spacing, 'min', 'max', 'fit', 'svh', 'lvh', 'dvh']
}],
/**
* Size
* @see https://tailwindcss.com/docs/size
*/
size: [{
size: [isArbitraryValue, spacing, 'auto', 'min', 'max', 'fit']
}],
// Typography
/**
* Font Size
* @see https://tailwindcss.com/docs/font-size
*/
'font-size': [{
text: ['base', isTshirtSize, isArbitraryLength]
}],
/**
* Font Smoothing
* @see https://tailwindcss.com/docs/font-smoothing
*/
'font-smoothing': ['antialiased', 'subpixel-antialiased'],
/**
* Font Style
* @see https://tailwindcss.com/docs/font-style
*/
'font-style': ['italic', 'not-italic'],
/**
* Font Weight
* @see https://tailwindcss.com/docs/font-weight
*/
'font-weight': [{
font: ['thin', 'extralight', 'light', 'normal', 'medium', 'semibold', 'bold', 'extrabold', 'black', isArbitraryNumber]
}],
/**
* Font Family
* @see https://tailwindcss.com/docs/font-family
*/
'font-family': [{
font: [isAny]
}],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-normal': ['normal-nums'],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-ordinal': ['ordinal'],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-slashed-zero': ['slashed-zero'],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-figure': ['lining-nums', 'oldstyle-nums'],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-spacing': ['proportional-nums', 'tabular-nums'],
/**
* Font Variant Numeric
* @see https://tailwindcss.com/docs/font-variant-numeric
*/
'fvn-fraction': ['diagonal-fractions', 'stacked-fractions'],
/**
* Letter Spacing
* @see https://tailwindcss.com/docs/letter-spacing
*/
tracking: [{
tracking: ['tighter', 'tight', 'normal', 'wide', 'wider', 'widest', isArbitraryValue]
}],
/**
* Line Clamp
* @see https://tailwindcss.com/docs/line-clamp
*/
'line-clamp': [{
'line-clamp': ['none', isNumber, isArbitraryNumber]
}],
/**
* Line Height
* @see https://tailwindcss.com/docs/line-height
*/
leading: [{
leading: ['none', 'tight', 'snug', 'normal', 'relaxed', 'loose', isLength, isArbitraryValue]
}],
/**
* List Style Image
* @see https://tailwindcss.com/docs/list-style-image
*/
'list-image': [{
'list-image': ['none', isArbitraryValue]
}],
/**
* List Style Type
* @see https://tailwindcss.com/docs/list-style-type
*/
'list-style-type': [{
list: ['none', 'disc', 'decimal', isArbitraryValue]
}],
/**
* List Style Position
* @see https://tailwindcss.com/docs/list-style-position
*/
'list-style-position': [{
list: ['inside', 'outside']
}],
/**
* Placeholder Color
* @deprecated since Tailwind CSS v3.0.0
* @see https://tailwindcss.com/docs/placeholder-color
*/
'placeholder-color': [{
placeholder: [colors]
}],
/**
* Placeholder Opacity
* @see https://tailwindcss.com/docs/placeholder-opacity
*/
'placeholder-opacity': [{
'placeholder-opacity': [opacity]
}],
/**
* Text Alignment
* @see https://tailwindcss.com/docs/text-align
*/
'text-alignment': [{
text: ['left', 'center', 'right', 'justify', 'start', 'end']
}],
/**
* Text Color
* @see https://tailwindcss.com/docs/text-color
*/
'text-color': [{
text: [colors]
}],
/**
* Text Opacity
* @see https://tailwindcss.com/docs/text-opacity
*/
'text-opacity': [{
'text-opacity': [opacity]
}],
/**
* Text Decoration
* @see https://tailwindcss.com/docs/text-decoration
*/
'text-decoration': ['underline', 'overline', 'line-through', 'no-underline'],
/**
* Text Decoration Style
* @see https://tailwindcss.com/docs/text-decoration-style
*/
'text-decoration-style': [{
decoration: [...getLineStyles(), 'wavy']
}],
/**
* Text Decoration Thickness
* @see https://tailwindcss.com/docs/text-decoration-thickness
*/
'text-decoration-thickness': [{
decoration: ['auto', 'from-font', isLength, isArbitraryLength]
}],
/**
* Text Underline Offset
* @see https://tailwindcss.com/docs/text-underline-offset
*/
'underline-offset': [{
'underline-offset': ['auto', isLength, isArbitraryValue]
}],
/**
* Text Decoration Color
* @see https://tailwindcss.com/docs/text-decoration-color
*/
'text-decoration-color': [{
decoration: [colors]
}],
/**
* Text Transform
* @see https://tailwindcss.com/docs/text-transform
*/
'text-transform': ['uppercase', 'lowercase', 'capitalize', 'normal-case'],
/**
* Text Overflow
* @see https://tailwindcss.com/docs/text-overflow
*/
'text-overflow': ['truncate', 'text-ellipsis', 'text-clip'],
/**
* Text Wrap
* @see https://tailwindcss.com/docs/text-wrap
*/
'text-wrap': [{
text: ['wrap', 'nowrap', 'balance', 'pretty']
}],
/**
* Text Indent
* @see https://tailwindcss.com/docs/text-indent
*/
indent: [{
indent: getSpacingWithArbitrary()
}],
/**
* Vertical Alignment
* @see https://tailwindcss.com/docs/vertical-align
*/
'vertical-align': [{
align: ['baseline', 'top', 'middle', 'bottom', 'text-top', 'text-bottom', 'sub', 'super', isArbitraryValue]
}],
/**
* Whitespace
* @see https://tailwindcss.com/docs/whitespace
*/
whitespace: [{
whitespace: ['normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'break-spaces']
}],
/**
* Word Break
* @see https://tailwindcss.com/docs/word-break
*/
break: [{
break: ['normal', 'words', 'all', 'keep']
}],
/**
* Hyphens
* @see https://tailwindcss.com/docs/hyphens
*/
hyphens: [{
hyphens: ['none', 'manual', 'auto']
}],
/**
* Content
* @see https://tailwindcss.com/docs/content
*/
content: [{
content: ['none', isArbitraryValue]
}],
// Backgrounds
/**
* Background Attachment
* @see https://tailwindcss.com/docs/background-attachment
*/
'bg-attachment': [{
bg: ['fixed', 'local', 'scroll']
}],
/**
* Background Clip
* @see https://tailwindcss.com/docs/background-clip
*/
'bg-clip': [{
'bg-clip': ['border', 'padding', 'content', 'text']
}],
/**
* Background Opacity
* @deprecated since Tailwind CSS v3.0.0
* @see https://tailwindcss.com/docs/background-opacity
*/
'bg-opacity': [{
'bg-opacity': [opacity]
}],
/**
* Background Origin
* @see https://tailwindcss.com/docs/background-origin
*/
'bg-origin': [{
'bg-origin': ['border', 'padding', 'content']
}],
/**
* Background Position
* @see https://tailwindcss.com/docs/background-position
*/
'bg-position': [{
bg: [...getPositions(), isArbitraryPosition]
}],
/**
* Background Repeat
* @see https://tailwindcss.com/docs/background-repeat
*/
'bg-repeat': [{
bg: ['no-repeat', {
repeat: ['', 'x', 'y', 'round', 'space']
}]
}],
/**
* Background Size
* @see https://tailwindcss.com/docs/background-size
*/
'bg-size': [{
bg: ['auto', 'cover', 'contain', isArbitrarySize]
}],
/**
* Background Image
* @see https://tailwindcss.com/docs/background-image
*/
'bg-image': [{
bg: ['none', {
'gradient-to': ['t', 'tr', 'r', 'br', 'b', 'bl', 'l', 'tl']
}, isArbitraryImage]
}],
/**
* Background Color
* @see https://tailwindcss.com/docs/background-color
*/
'bg-color': [{
bg: [colors]
}],
/**
* Gradient Color Stops From Position
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-from-pos': [{
from: [gradientColorStopPositions]
}],
/**
* Gradient Color Stops Via Position
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-via-pos': [{
via: [gradientColorStopPositions]
}],
/**
* Gradient Color Stops To Position
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-to-pos': [{
to: [gradientColorStopPositions]
}],
/**
* Gradient Color Stops From
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-from': [{
from: [gradientColorStops]
}],
/**
* Gradient Color Stops Via
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-via': [{
via: [gradientColorStops]
}],
/**
* Gradient Color Stops To
* @see https://tailwindcss.com/docs/gradient-color-stops
*/
'gradient-to': [{
to: [gradientColorStops]
}],
// Borders
/**
* Border Radius
* @see https://tailwindcss.com/docs/border-radius
*/
rounded: [{
rounded: [borderRadius]
}],
/**
* Border Radius Start
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-s': [{
'rounded-s': [borderRadius]
}],
/**
* Border Radius End
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-e': [{
'rounded-e': [borderRadius]
}],
/**
* Border Radius Top
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-t': [{
'rounded-t': [borderRadius]
}],
/**
* Border Radius Right
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-r': [{
'rounded-r': [borderRadius]
}],
/**
* Border Radius Bottom
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-b': [{
'rounded-b': [borderRadius]
}],
/**
* Border Radius Left
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-l': [{
'rounded-l': [borderRadius]
}],
/**
* Border Radius Start Start
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-ss': [{
'rounded-ss': [borderRadius]
}],
/**
* Border Radius Start End
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-se': [{
'rounded-se': [borderRadius]
}],
/**
* Border Radius End End
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-ee': [{
'rounded-ee': [borderRadius]
}],
/**
* Border Radius End Start
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-es': [{
'rounded-es': [borderRadius]
}],
/**
* Border Radius Top Left
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-tl': [{
'rounded-tl': [borderRadius]
}],
/**
* Border Radius Top Right
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-tr': [{
'rounded-tr': [borderRadius]
}],
/**
* Border Radius Bottom Right
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-br': [{
'rounded-br': [borderRadius]
}],
/**
* Border Radius Bottom Left
* @see https://tailwindcss.com/docs/border-radius
*/
'rounded-bl': [{
'rounded-bl': [borderRadius]
}],
/**
* Border Width
* @see https://tailwindcss.com/docs/border-width
*/
'border-w': [{
border: [borderWidth]
}],
/**
* Border Width X
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-x': [{
'border-x': [borderWidth]
}],
/**
* Border Width Y
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-y': [{
'border-y': [borderWidth]
}],
/**
* Border Width Start
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-s': [{
'border-s': [borderWidth]
}],
/**
* Border Width End
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-e': [{
'border-e': [borderWidth]
}],
/**
* Border Width Top
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-t': [{
'border-t': [borderWidth]
}],
/**
* Border Width Right
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-r': [{
'border-r': [borderWidth]
}],
/**
* Border Width Bottom
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-b': [{
'border-b': [borderWidth]
}],
/**
* Border Width Left
* @see https://tailwindcss.com/docs/border-width
*/
'border-w-l': [{
'border-l': [borderWidth]
}],
/**
* Border Opacity
* @see https://tailwindcss.com/docs/border-opacity
*/
'border-opacity': [{
'border-opacity': [opacity]
}],
/**
* Border Style
* @see https://tailwindcss.com/docs/border-style
*/
'border-style': [{
border: [...getLineStyles(), 'hidden']
}],
/**
* Divide Width X
* @see https://tailwindcss.com/docs/divide-width
*/
'divide-x': [{
'divide-x': [borderWidth]
}],
/**
* Divide Width X Reverse
* @see https://tailwindcss.com/docs/divide-width
*/
'divide-x-reverse': ['divide-x-reverse'],
/**
* Divide Width Y
* @see https://tailwindcss.com/docs/divide-width
*/
'divide-y': [{
'divide-y': [borderWidth]
}],
/**
* Divide Width Y Reverse
* @see https://tailwindcss.com/docs/divide-width
*/
'divide-y-reverse': ['divide-y-reverse'],
/**
* Divide Opacity
* @see https://tailwindcss.com/docs/divide-opacity
*/
'divide-opacity': [{
'divide-opacity': [opacity]
}],
/**
* Divide Style
* @see https://tailwindcss.com/docs/divide-style
*/
'divide-style': [{
divide: getLineStyles()
}],
/**
* Border Color
* @see https://tailwindcss.com/docs/border-color
*/
'border-color': [{
border: [borderColor]
}],
/**
* Border Color X
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-x': [{
'border-x': [borderColor]
}],
/**
* Border Color Y
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-y': [{
'border-y': [borderColor]
}],
/**
* Border Color S
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-s': [{
'border-s': [borderColor]
}],
/**
* Border Color E
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-e': [{
'border-e': [borderColor]
}],
/**
* Border Color Top
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-t': [{
'border-t': [borderColor]
}],
/**
* Border Color Right
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-r': [{
'border-r': [borderColor]
}],
/**
* Border Color Bottom
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-b': [{
'border-b': [borderColor]
}],
/**
* Border Color Left
* @see https://tailwindcss.com/docs/border-color
*/
'border-color-l': [{
'border-l': [borderColor]
}],
/**
* Divide Color
* @see https://tailwindcss.com/docs/divide-color
*/
'divide-color': [{
divide: [borderColor]
}],
/**
* Outline Style
* @see https://tailwindcss.com/docs/outline-style
*/
'outline-style': [{
outline: ['', ...getLineStyles()]
}],
/**
* Outline Offset
* @see https://tailwindcss.com/docs/outline-offset
*/
'outline-offset': [{
'outline-offset': [isLength, isArbitraryValue]
}],
/**
* Outline Width
* @see https://tailwindcss.com/docs/outline-width
*/
'outline-w': [{
outline: [isLength, isArbitraryLength]
}],
/**
* Outline Color
* @see https://tailwindcss.com/docs/outline-color
*/
'outline-color': [{
outline: [colors]
}],
/**
* Ring Width
* @see https://tailwindcss.com/docs/ring-width
*/
'ring-w': [{
ring: getLengthWithEmptyAndArbitrary()
}],
/**
* Ring Width Inset
* @see https://tailwindcss.com/docs/ring-width
*/
'ring-w-inset': ['ring-inset'],
/**
* Ring Color
* @see https://tailwindcss.com/docs/ring-color
*/
'ring-color': [{
ring: [colors]
}],
/**
* Ring Opacity
* @see https://tailwindcss.com/docs/ring-opacity
*/
'ring-opacity': [{
'ring-opacity': [opacity]
}],
/**
* Ring Offset Width
* @see https://tailwindcss.com/docs/ring-offset-width
*/
'ring-offset-w': [{
'ring-offset': [isLength, isArbitraryLength]
}],
/**
* Ring Offset Color
* @see https://tailwindcss.com/docs/ring-offset-color
*/
'ring-offset-color': [{
'ring-offset': [colors]
}],
// Effects
/**
* Box Shadow
* @see https://tailwindcss.com/docs/box-shadow
*/
shadow: [{
shadow: ['', 'inner', 'none', isTshirtSize, isArbitraryShadow]
}],
/**
* Box Shadow Color
* @see https://tailwindcss.com/docs/box-shadow-color
*/
'shadow-color': [{
shadow: [isAny]
}],
/**
* Opacity
* @see https://tailwindcss.com/docs/opacity
*/
opacity: [{
opacity: [opacity]
}],
/**
* Mix Blend Mode
* @see https://tailwindcss.com/docs/mix-blend-mode
*/
'mix-blend': [{
'mix-blend': [...getBlendModes(), 'plus-lighter', 'plus-darker']
}],
/**
* Background Blend Mode
* @see https://tailwindcss.com/docs/background-blend-mode
*/
'bg-blend': [{
'bg-blend': getBlendModes()
}],
// Filters
/**
* Filter
* @deprecated since Tailwind CSS v3.0.0
* @see https://tailwindcss.com/docs/filter
*/
filter: [{
filter: ['', 'none']
}],
/**
* Blur
* @see https://tailwindcss.com/docs/blur
*/
blur: [{
blur: [blur]
}],
/**
* Brightness
* @see https://tailwindcss.com/docs/brightness
*/
brightness: [{
brightness: [brightness]
}],
/**
* Contrast
* @see https://tailwindcss.com/docs/contrast
*/
contrast: [{
contrast: [contrast]
}],
/**
* Drop Shadow
* @see https://tailwindcss.com/docs/drop-shadow
*/
'drop-shadow': [{
'drop-shadow': ['', 'none', isTshirtSize, isArbitraryValue]
}],
/**
* Grayscale
* @see https://tailwindcss.com/docs/grayscale
*/
grayscale: [{
grayscale: [grayscale]
}],
/**
* Hue Rotate
* @see https://tailwindcss.com/docs/hue-rotate
*/
'hue-rotate': [{
'hue-rotate': [hueRotate]
}],
/**
* Invert
* @see https://tailwindcss.com/docs/invert
*/
invert: [{
invert: [invert]
}],
/**
* Saturate
* @see https://tailwindcss.com/docs/saturate
*/
saturate: [{
saturate: [saturate]
}],
/**
* Sepia
* @see https://tailwindcss.com/docs/sepia
*/
sepia: [{
sepia: [sepia]
}],
/**
* Backdrop Filter
* @deprecated since Tailwind CSS v3.0.0
* @see https://tailwindcss.com/docs/backdrop-filter
*/
'backdrop-filter': [{
'backdrop-filter': ['', 'none']
}],
/**
* Backdrop Blur
* @see https://tailwindcss.com/docs/backdrop-blur
*/
'backdrop-blur': [{
'backdrop-blur': [blur]
}],
/**
* Backdrop Brightness
* @see https://tailwindcss.com/docs/backdrop-brightness
*/
'backdrop-brightness': [{
'backdrop-brightness': [brightness]
}],
/**
* Backdrop Contrast
* @see https://tailwindcss.com/docs/backdrop-contrast
*/
'backdrop-contrast': [{
'backdrop-contrast': [contrast]
}],
/**
* Backdrop Grayscale
* @see https://tailwindcss.com/docs/backdrop-grayscale
*/
'backdrop-grayscale': [{
'backdrop-grayscale': [grayscale]
}],
/**
* Backdrop Hue Rotate
* @see https://tailwindcss.com/docs/backdrop-hue-rotate
*/
'backdrop-hue-rotate': [{
'backdrop-hue-rotate': [hueRotate]
}],
/**
* Backdrop Invert
* @see https://tailwindcss.com/docs/backdrop-invert
*/
'backdrop-invert': [{
'backdrop-invert': [invert]
}],
/**
* Backdrop Opacity
* @see https://tailwindcss.com/docs/backdrop-opacity
*/
'backdrop-opacity': [{
'backdrop-opacity': [opacity]
}],
/**
* Backdrop Saturate
* @see https://tailwindcss.com/docs/backdrop-saturate
*/
'backdrop-saturate': [{
'backdrop-saturate': [saturate]
}],
/**
* Backdrop Sepia
* @see https://tailwindcss.com/docs/backdrop-sepia
*/
'backdrop-sepia': [{
'backdrop-sepia': [sepia]
}],
// Tables
/**
* Border Collapse
* @see https://tailwindcss.com/docs/border-collapse
*/
'border-collapse': [{
border: ['collapse', 'separate']
}],
/**
* Border Spacing
* @see https://tailwindcss.com/docs/border-spacing
*/
'border-spacing': [{
'border-spacing': [borderSpacing]
}],
/**
* Border Spacing X
* @see https://tailwindcss.com/docs/border-spacing
*/
'border-spacing-x': [{
'border-spacing-x': [borderSpacing]
}],
/**
* Border Spacing Y
* @see https://tailwindcss.com/docs/border-spacing
*/
'border-spacing-y': [{
'border-spacing-y': [borderSpacing]
}],
/**
* Table Layout
* @see https://tailwindcss.com/docs/table-layout
*/
'table-layout': [{
table: ['auto', 'fixed']
}],
/**
* Caption Side
* @see https://tailwindcss.com/docs/caption-side
*/
caption: [{
caption: ['top', 'bottom']
}],
// Transitions and Animation
/**
* Tranisition Property
* @see https://tailwindcss.com/docs/transition-property
*/
transition: [{
transition: ['none', 'all', '', 'colors', 'opacity', 'shadow', 'transform', isArbitraryValue]
}],
/**
* Transition Duration
* @see https://tailwindcss.com/docs/transition-duration
*/
duration: [{
duration: getNumberAndArbitrary()
}],
/**
* Transition Timing Function
* @see https://tailwindcss.com/docs/transition-timing-function
*/
ease: [{
ease: ['linear', 'in', 'out', 'in-out', isArbitraryValue]
}],
/**
* Transition Delay
* @see https://tailwindcss.com/docs/transition-delay
*/
delay: [{
delay: getNumberAndArbitrary()
}],
/**
* Animation
* @see https://tailwindcss.com/docs/animation
*/
animate: [{
animate: ['none', 'spin', 'ping', 'pulse', 'bounce', isArbitraryValue]
}],
// Transforms
/**
* Transform
* @see https://tailwindcss.com/docs/transform
*/
transform: [{
transform: ['', 'gpu', 'none']
}],
/**
* Scale
* @see https://tailwindcss.com/docs/scale
*/
scale: [{
scale: [scale]
}],
/**
* Scale X
* @see https://tailwindcss.com/docs/scale
*/
'scale-x': [{
'scale-x': [scale]
}],
/**
* Scale Y
* @see https://tailwindcss.com/docs/scale
*/
'scale-y': [{
'scale-y': [scale]
}],
/**
* Rotate
* @see https://tailwindcss.com/docs/rotate
*/
rotate: [{
rotate: [isInteger, isArbitraryValue]
}],
/**
* Translate X
* @see https://tailwindcss.com/docs/translate
*/
'translate-x': [{
'translate-x': [translate]
}],
/**
* Translate Y
* @see https://tailwindcss.com/docs/translate
*/
'translate-y': [{
'translate-y': [translate]
}],
/**
* Skew X
* @see https://tailwindcss.com/docs/skew
*/
'skew-x': [{
'skew-x': [skew]
}],
/**
* Skew Y
* @see https://tailwindcss.com/docs/skew
*/
'skew-y': [{
'skew-y': [skew]
}],
/**
* Transform Origin
* @see https://tailwindcss.com/docs/transform-origin
*/
'transform-origin': [{
origin: ['center', 'top', 'top-right', 'right', 'bottom-right', 'bottom', 'bottom-left', 'left', 'top-left', isArbitraryValue]
}],
// Interactivity
/**
* Accent Color
* @see https://tailwindcss.com/docs/accent-color
*/
accent: [{
accent: ['auto', colors]
}],
/**
* Appearance
* @see https://tailwindcss.com/docs/appearance
*/
appearance: [{
appearance: ['none', 'auto']
}],
/**
* Cursor
* @see https://tailwindcss.com/docs/cursor
*/
cursor: [{
cursor: ['auto', 'default', 'pointer', 'wait', 'text', 'move', 'help', 'not-allowed', 'none', 'context-menu', 'progress', 'cell', 'crosshair', 'vertical-text', 'alias', 'copy', 'no-drop', 'grab', 'grabbing', 'all-scroll', 'col-resize', 'row-resize', 'n-resize', 'e-resize', 's-resize', 'w-resize', 'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize', 'zoom-in', 'zoom-out', isArbitraryValue]
}],
/**
* Caret Color
* @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities
*/
'caret-color': [{
caret: [colors]
}],
/**
* Pointer Events
* @see https://tailwindcss.com/docs/pointer-events
*/
'pointer-events': [{
'pointer-events': ['none', 'auto']
}],
/**
* Resize
* @see https://tailwindcss.com/docs/resize
*/
resize: [{
resize: ['none', 'y', 'x', '']
}],
/**
* Scroll Behavior
* @see https://tailwindcss.com/docs/scroll-behavior
*/
'scroll-behavior': [{
scroll: ['auto', 'smooth']
}],
/**
* Scroll Margin
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-m': [{
'scroll-m': getSpacingWithArbitrary()
}],
/**
* Scroll Margin X
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-mx': [{
'scroll-mx': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Y
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-my': [{
'scroll-my': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Start
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-ms': [{
'scroll-ms': getSpacingWithArbitrary()
}],
/**
* Scroll Margin End
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-me': [{
'scroll-me': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Top
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-mt': [{
'scroll-mt': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Right
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-mr': [{
'scroll-mr': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Bottom
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-mb': [{
'scroll-mb': getSpacingWithArbitrary()
}],
/**
* Scroll Margin Left
* @see https://tailwindcss.com/docs/scroll-margin
*/
'scroll-ml': [{
'scroll-ml': getSpacingWithArbitrary()
}],
/**
* Scroll Padding
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-p': [{
'scroll-p': getSpacingWithArbitrary()
}],
/**
* Scroll Padding X
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-px': [{
'scroll-px': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Y
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-py': [{
'scroll-py': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Start
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-ps': [{
'scroll-ps': getSpacingWithArbitrary()
}],
/**
* Scroll Padding End
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-pe': [{
'scroll-pe': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Top
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-pt': [{
'scroll-pt': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Right
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-pr': [{
'scroll-pr': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Bottom
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-pb': [{
'scroll-pb': getSpacingWithArbitrary()
}],
/**
* Scroll Padding Left
* @see https://tailwindcss.com/docs/scroll-padding
*/
'scroll-pl': [{
'scroll-pl': getSpacingWithArbitrary()
}],
/**
* Scroll Snap Align
* @see https://tailwindcss.com/docs/scroll-snap-align
*/
'snap-align': [{
snap: ['start', 'end', 'center', 'align-none']
}],
/**
* Scroll Snap Stop
* @see https://tailwindcss.com/docs/scroll-snap-stop
*/
'snap-stop': [{
snap: ['normal', 'always']
}],
/**
* Scroll Snap Type
* @see https://tailwindcss.com/docs/scroll-snap-type
*/
'snap-type': [{
snap: ['none', 'x', 'y', 'both']
}],
/**
* Scroll Snap Type Strictness
* @see https://tailwindcss.com/docs/scroll-snap-type
*/
'snap-strictness': [{
snap: ['mandatory', 'proximity']
}],
/**
* Touch Action
* @see https://tailwindcss.com/docs/touch-action
*/
touch: [{
touch: ['auto', 'none', 'manipulation']
}],
/**
* Touch Action X
* @see https://tailwindcss.com/docs/touch-action
*/
'touch-x': [{
'touch-pan': ['x', 'left', 'right']
}],
/**
* Touch Action Y
* @see https://tailwindcss.com/docs/touch-action
*/
'touch-y': [{
'touch-pan': ['y', 'up', 'down']
}],
/**
* Touch Action Pinch Zoom
* @see https://tailwindcss.com/docs/touch-action
*/
'touch-pz': ['touch-pinch-zoom'],
/**
* User Select
* @see https://tailwindcss.com/docs/user-select
*/
select: [{
select: ['none', 'text', 'all', 'auto']
}],
/**
* Will Change
* @see https://tailwindcss.com/docs/will-change
*/
'will-change': [{
'will-change': ['auto', 'scroll', 'contents', 'transform', isArbitraryValue]
}],
// SVG
/**
* Fill
* @see https://tailwindcss.com/docs/fill
*/
fill: [{
fill: [colors, 'none']
}],
/**
* Stroke Width
* @see https://tailwindcss.com/docs/stroke-width
*/
'stroke-w': [{
stroke: [isLength, isArbitraryLength, isArbitraryNumber]
}],
/**
* Stroke
* @see https://tailwindcss.com/docs/stroke
*/
stroke: [{
stroke: [colors, 'none']
}],
// Accessibility
/**
* Screen Readers
* @see https://tailwindcss.com/docs/screen-readers
*/
sr: ['sr-only', 'not-sr-only'],
/**
* Forced Color Adjust
* @see https://tailwindcss.com/docs/forced-color-adjust
*/
'forced-color-adjust': [{
'forced-color-adjust': ['auto', 'none']
}]
},
conflictingClassGroups: {
overflow: ['overflow-x', 'overflow-y'],
overscroll: ['overscroll-x', 'overscroll-y'],
inset: ['inset-x', 'inset-y', 'start', 'end', 'top', 'right', 'bottom', 'left'],
'inset-x': ['right', 'left'],
'inset-y': ['top', 'bottom'],
flex: ['basis', 'grow', 'shrink'],
gap: ['gap-x', 'gap-y'],
p: ['px', 'py', 'ps', 'pe', 'pt', 'pr', 'pb', 'pl'],
px: ['pr', 'pl'],
py: ['pt', 'pb'],
m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'],
mx: ['mr', 'ml'],
my: ['mt', 'mb'],
size: ['w', 'h'],
'font-size': ['leading'],
'fvn-normal': ['fvn-ordinal', 'fvn-slashed-zero', 'fvn-figure', 'fvn-spacing', 'fvn-fraction'],
'fvn-ordinal': ['fvn-normal'],
'fvn-slashed-zero': ['fvn-normal'],
'fvn-figure': ['fvn-normal'],
'fvn-spacing': ['fvn-normal'],
'fvn-fraction': ['fvn-normal'],
'line-clamp': ['display', 'overflow'],
rounded: ['rounded-s', 'rounded-e', 'rounded-t', 'rounded-r', 'rounded-b', 'rounded-l', 'rounded-ss', 'rounded-se', 'rounded-ee', 'rounded-es', 'rounded-tl', 'rounded-tr', 'rounded-br', 'rounded-bl'],
'rounded-s': ['rounded-ss', 'rounded-es'],
'rounded-e': ['rounded-se', 'rounded-ee'],
'rounded-t': ['rounded-tl', 'rounded-tr'],
'rounded-r': ['rounded-tr', 'rounded-br'],
'rounded-b': ['rounded-br', 'rounded-bl'],
'rounded-l': ['rounded-tl', 'rounded-bl'],
'border-spacing': ['border-spacing-x', 'border-spacing-y'],
'border-w': ['border-w-s', 'border-w-e', 'border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'],
'border-w-x': ['border-w-r', 'border-w-l'],
'border-w-y': ['border-w-t', 'border-w-b'],
'border-color': ['border-color-s', 'border-color-e', 'border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'],
'border-color-x': ['border-color-r', 'border-color-l'],
'border-color-y': ['border-color-t', 'border-color-b'],
'scroll-m': ['scroll-mx', 'scroll-my', 'scroll-ms', 'scroll-me', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'],
'scroll-mx': ['scroll-mr', 'scroll-ml'],
'scroll-my': ['scroll-mt', 'scroll-mb'],
'scroll-p': ['scroll-px', 'scroll-py', 'scroll-ps', 'scroll-pe', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'],
'scroll-px': ['scroll-pr', 'scroll-pl'],
'scroll-py': ['scroll-pt', 'scroll-pb'],
touch: ['touch-x', 'touch-y', 'touch-pz'],
'touch-x': ['touch'],
'touch-y': ['touch'],
'touch-pz': ['touch']
},
conflictingClassGroupModifiers: {
'font-size': ['leading']
}
};
};
const twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig);
/**
* Detects if Tailwind CSS is being used in the project
* by checking for common Tailwind-specific classes in the document
*/
function detectTailwind() {
var _a;
if (typeof window === "undefined")
return true; // Skip check on server-side
// Check if any element has common Tailwind utility classes
const tailwindClasses = [
"sm:",
"md:",
"lg:",
"xl:",
"2xl:",
"flex",
"grid",
"container",
"px-",
"py-",
"mx-",
"my-",
"bg-",
"text-",
"border-",
];
// Get all style sheets
const styleSheets = Array.from(document.styleSheets);
try {
// Look through all stylesheets for Tailwind-specific patterns
for (const sheet of styleSheets) {
try {
// Skip external stylesheets
if (!((_a = sheet.href) === null || _a === void 0 ? void 0 : _a.includes(window.location.origin)))
continue;
const rules = Array.from(sheet.cssRules);
for (const rule of rules) {
const ruleText = rule.cssText;
// Check for Tailwind's utility class patterns
if (tailwindClasses.some((cls) => ruleText.includes(cls))) {
return true;
}
// Check for Tailwind's layer markers
if (ruleText.includes("@tailwind") ||
ruleText.includes("@layer") ||
ruleText.includes("@apply")) {
return true;
}
}
// eslint-disable-next-line
}
catch (e) {
// Skip CORS errors for external stylesheets
continue;
}
}
// Fallback: Check DOM for common Tailwind classes
const allElements = Array.from(document.getElementsByTagName("*"));
for (const element of allElements) {
if (tailwindClasses.some((cls) => Array.from(element.classList).some((className) => className.includes(cls.replace(":", "-"))))) {
return true;
}
}
return false;
}
catch (_b) {
// If there's any error in detection, assume Tailwind is present
console.warn("Error detecting Tailwind CSS");
return true;
}
}
mark_module_start();
TailwindScreenSize$1[FILENAME] = "src/svelte/TailwindScreenSize.svelte";
var root_2 = add_locations(template(`<div class="fixed bottom-5 left-5 text-xs text-red-500">Tailwind CSS not detected</div>`), TailwindScreenSize$1[FILENAME], [[242, 2]]);
var root_1 = add_locations(template(`<!> <div><span> </span> <div></div> <span> </span></div>`, 1), TailwindScreenSize$1[FILENAME], [
[
244,
1,
[[245, 2], [246, 2], [247, 2]]
]
]);
function TailwindScreenSize$1($$anchor, $$props) {
check_target(new.target);
push($$props, true, TailwindScreenSize$1);
validate_prop_bindings($$props, [], [], TailwindScreenSize$1);
// Props
const className = prop($$props, "className", 3, ''),
position = prop($$props, "position", 3, /** @type {Position} */ 'bottom-right'),
theme = prop($$props, "theme", 3, /** @type {Theme} */ 'dark'),
show = prop($$props, "show", 3, /** @type {boolean | undefined} */ undefined),
containerClassName = prop($$props, "containerClassName", 3, ''),
textClassName = prop($$props, "textClassName", 3, ''),
dividerClassName = prop($$props, "dividerClassName", 3, ''),
breakpointClassName = prop($$props, "breakpointClassName", 3, ''),
breakpoints = prop($$props, "breakpoints", 3, /** @type {Breakpoint[] | undefined} */ undefined);
prop($$props, "showDefaultBreakpoints", 3, true);
const hideNoTailwindCSSWarning = prop($$props, "hideNoTailwindCSSWarning", 3, false);
// State
let currentBreakpoint = state('');
let width = state(0);
let isTailwindDetected = state(false);
let mounted = state(false);
const positionClasses = {
'top-left': 'top-5 left-5',
'top-right': 'top-5 right-5',
'bottom-left': 'bottom-5 left-5',
'bottom-right': 'bottom-5 right-5',
'top-center': 'top-5 left-1/2 -translate-x-1/2',
'bottom-center': 'bottom-5 left-1/2 -translate-x-1/2'
};
const themeClasses = {
dark: {
container: 'bg-gray-900/90 text-white',
text: 'text-white',
divider: 'bg-gray-700',
breakpoint: 'text-gray-400'
},
light: {
container: 'bg-white/90 text-gray-900',
text: 'text-gray-900',
divider: 'bg-gray-200',
breakpoint: 'text-gray-600'
},
glass: {
container: 'bg-white/30 backdrop-blur-lg text-gray-900',
text: 'text-gray-900',
divider: 'bg-gray-300/50',
breakpoint: 'text-gray-600'
},
minimal: {
container: 'bg-white/10 text-gray-800',
text: 'text-gray-800',
divider: 'bg-gray-300',
breakpoint: 'text-gray-500'
},
slate: {
container: 'bg-slate-100/90 text-slate-900',
text: 'text-slate-900',
divider: 'bg-slate-300',
breakpoint: 'text-slate-600'
},
gray: {
container: 'bg-gray-100/90 text-gray-900',
text: 'text-gray-900',
divider: 'bg-gray-300',
breakpoint: 'text-gray-600'
},
zinc: {
container: 'bg-zinc-100/90 text-zinc-900',
text: 'text-zinc-900',
divider: 'bg-zinc-300',
breakpoint: 'text-zinc-600'
},
neutral: {
container: 'bg-neutral-100/90 text-neutral-900',
text: 'text-neutral-900',
divider: 'bg-neutral-300',
breakpoint: 'text-neutral-600'
},
stone: {
container: 'bg-stone-100/90 text-stone-900',
text: 'text-stone-900',
divider: 'bg-stone-300',
breakpoint: 'text-stone-600'
},
red: {
container: 'bg-red-100/90 text-red-900',
text: 'text-red-900',
divider: 'bg-red-300',
breakpoint: 'text-red-600'
},
orange: {
container: 'bg-orange-100/90 text-orange-900',
text: 'text-orange-900',
divider: 'bg-orange-300',
breakpoint: 'text-orange-600'
},
amber: {
container: 'bg-amber-100/90 text-amber-900',
text: 'text-amber-900',
divider: 'bg-amber-300',
breakpoint: 'text-amber-600'
},
yellow: {
container: 'bg-yellow-100/90 text-yellow-900',
text: 'text-yellow-900',
divider: 'bg-yellow-300',
breakpoint: 'text-yellow-600'
},
lime: {
container: 'bg-lime-100/90 text-lime-900',
text: 'text-lime-900',
divider: 'bg-lime-300',
breakpoint: 'text-lime-600'
},
green: {
container: 'bg-green-100/90 text-green-900',
text: 'text-green-900',
divider: 'bg-green-300',
breakpoint: 'text-green-600'
},
emerald: {
container: 'bg-emerald-100/90 text-emerald-900',
text: 'text-emerald-900',
divider: 'bg-emerald-300',
breakpoint: 'text-emerald-600'
},
teal: {
container: 'bg-teal-100/90 text-teal-900',
text: 'text-teal-900',
divider: 'bg-teal-300',
breakpoint: 'text-teal-600'
},
cyan: {
container: 'bg-cyan-100/90 text-cyan-900',
text: 'text-cyan-900',
divider: 'bg-cyan-300',
breakpoint: 'text-cyan-600'
},
sky: {
container: 'bg-sky-100/90 text-sky-900',
text: 'text-sky-900',
divider: 'bg-sky-300',
breakpoint: 'text-sky-600'
},
blue: {
container: 'bg-blue-100/90 text-blue-900',
text: 'text-blue-900',
divider: 'bg-blue-300',
breakpoint: 'text-blue-600'
},
indigo: {
container: 'bg-indigo-100/90 text-indigo-900',
text: 'text-indigo-900',
divider: 'bg-indigo-300',
breakpoint: 'text-indigo-600'
},
violet: {
container: 'bg-violet-100/90 text-violet-900',
text: 'text-violet-900',
divider: 'bg-violet-300',
breakpoint: 'text-violet-600'
},
purple: {
container: 'bg-purple-100/90 text-purple-900',
text: 'text-purple-900',
divider: 'bg-purple-300',
breakpoint: 'text-purple-600'
},
fuchsia: {
container: 'bg-fuchsia-100/90 text-fuchsia-900',
text: 'text-fuchsia-900',
divider: 'bg-fuchsia-300',
breakpoint: 'text-fuchsia-600'
},
pink: {
container: 'bg-pink-100/90 text-pink-900',
text: 'text-pink-900',
divider: 'bg-pink-300',
breakpoint: 'text-pink-600'
},
rose: {
container: 'bg-rose-100/90 text-rose-900',
text: 'text-rose-900',
divider: 'bg-rose-300',
breakpoint: 'text-rose-600'
}
};
const defaultBreakpoints = [
{ screenTitle: 'XS', minWidth: 0 },
{ screenTitle: 'SM', minWidth: 640 },
{ screenTitle: 'MD', minWidth: 768 },
{ screenTitle: 'LG', minWidth: 1024 },
{ screenTitle: 'XL', minWidth: 1280 },
{ screenTitle: '2XL', minWidth: 1536 }
];
const baseClasses = {
container: 'fixed flex items-center gap-2 rounded-full px-2.5 py-1 font-mono text-xs font-medium transition-all duration-200',
divider: 'h-4 w-px'
};
function isDevelopment() {
return strict_equals(process.env.NODE_ENV, 'development');
}
function getCurrentBreakpoint(width, breakpointList) {
var _a;
const sortedBreakpoints = [...breakpointList].sort((a, b) => b.minWidth - a.minWidth);
return (strict_equals(_a = sortedBreakpoints.find((breakpoint) => width >= breakpoint.minWidth), null) || strict_equals(_a, void 0) ? void 0 : _a.screenTitle) || '';
}
function handleResize() {
set(width, proxy(window.innerWidth, null, width));
set(currentBreakpoint, proxy(getCurrentBreakpoint(get(width), breakpoints() || defaultBreakpoints), null, currentBreakpoint));
}
// Derived values
// $: shouldShow = show ?? isDevelopment();
const shouldShow = derived(() => strict_equals(show(), null, false) && strict_equals(show(), void 0, false) ? show() : isDevelopment());
// $: containerClassNames = twMerge(
// baseClasses.container,
// themeClasses[theme].container,
// positionClasses[position],
// containerClassName,
// className
// );
const containerClassNames = derived(() => twMerge(baseClasses.container, themeClasses[theme()].container, positionClasses[position()], containerClassName(), className()));
// $: textClassNames = twMerge(themeClasses[theme].text, textClassName);
const textClassNames = derived(() => twMerge(themeClasses[theme()].text, textClassName()));
// $: dividerClassNames = twMerge(
// baseClasses.divider,
// themeClasses[theme].divider,
// dividerClassName
// );
const dividerClassNames = derived(() => twMerge(baseClasses.divider, themeClasses[theme()].divider, dividerClassName()));
// $: breakpointClassNames = twMerge(
// themeClasses[theme].breakpoint,
// breakpointClassName
// );
const breakpointClassNames = derived(() => twMerge(themeClasses[theme()].breakpoint, breakpointClassName()));
// $: breakpointClassNames = twMerge(themeClasses[theme].breakpoint, breakpointClassName);
// Lifecycle
svelte.onMount(() => {
set(mounted, true);
set(isTailwindDetected, proxy(detectTailwind(), null, isTailwindDetected));
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
});
var fragment = comment();
var node = first_child(fragment);
if_block(node, () => get(mounted) && get(shouldShow), ($$anchor) => {
var fragment_1 = root_1();
var node_1 = first_child(fragment_1);
if_block(node_1, () => !get(isTailwindDetected) && !hideNoTailwindCSSWarning(), ($$anchor) => {
var div = root_2();
append($$anchor, div);
});
var div_1 = sibling(node_1, 2);
var span = child(div_1);
var text = child(span);
var div_2 = sibling(span, 2);
var span_1 = sibling(div_2, 2);
var text_1 = child(span_1);
template_effect(() => {
set_class(div_1, get(containerClassNames));
set_class(span, get(textClassNames));
set_text(text, `${get(width) ?? ""}px`);
set_class(div_2, get(dividerClassNames));
set_class(span_1, get(breakpointClassNames));
set_text(text_1, get(currentBreakpoint));
});
append($$anchor, fragment_1);
});
append($$anchor, fragment);
return pop({ ...legacy_api() });
}
mark_module_end(TailwindScreenSize$1);
const TailwindScreenSize = TailwindScreenSize$1;
exports.TailwindScreenSize = TailwindScreenSize;
//# sourceMappingURL=index.js.map