/**
 * @license Angular v21.1.4
 * (c) 2010-2026 Google LLC. https://angular.dev/
 * License: MIT
 */

import { SIGNAL, consumerMarkDirty, REACTIVE_NODE, consumerDestroy, isInNotificationPhase, consumerPollProducersForChange, consumerBeforeComputation, consumerAfterComputation } from './_effect-chunk.mjs';
export { BASE_EFFECT_NODE, SIGNAL_NODE, createComputed, createSignal, defaultEquals, finalizeConsumerAfterComputation, getActiveConsumer, isReactive, producerAccessed, producerIncrementEpoch, producerMarkClean, producerNotifyConsumers, producerUpdateValueVersion, producerUpdatesAllowed, resetConsumerBeforeComputation, runEffect, runPostProducerCreatedFn, runPostSignalSetFn, setActiveConsumer, setPostProducerCreatedFn, setPostSignalSetFn, setThrowInvalidWriteToSignalError, signalGetFn, signalSetFn, signalUpdateFn, untracked } from './_effect-chunk.mjs';
export { createLinkedSignal, linkedSignalSetFn, linkedSignalUpdateFn } from './_linked_signal-chunk.mjs';
export { setAlternateWeakRefImpl } from './_weak_ref-chunk.mjs';

const formatter = {
  header: (sig, config) => {
    if (!isSignal(sig) || config?.ngSkipFormatting) return null;
    let value;
    try {
      value = sig();
    } catch (e) {
      return ['span', `Signal(⚠️ Error)${e.message ? `: ${e.message}` : ''}`];
    }
    const kind = 'computation' in sig[SIGNAL] ? 'Computed' : 'Signal';
    const isPrimitive = value === null || !Array.isArray(value) && typeof value !== 'object';
    return ['span', {}, ['span', {}, `${kind}(`], (() => {
      if (isSignal(value)) {
        return formatter.header(value, config);
      } else if (isPrimitive && value !== undefined && typeof value !== 'function') {
        return ['object', {
          object: value
        }];
      } else {
        return prettifyPreview(value);
      }
    })(), ['span', {}, `)`]];
  },
  hasBody: (sig, config) => {
    if (!isSignal(sig)) return false;
    try {
      sig();
    } catch {
      return false;
    }
    return !config?.ngSkipFormatting;
  },
  body: (sig, config) => {
    const color = 'var(--sys-color-primary)';
    return ['div', {
      style: `background: #FFFFFF10; padding-left: 4px; padding-top: 2px; padding-bottom: 2px;`
    }, ['div', {
      style: `color: ${color}`
    }, 'Signal value: '], ['div', {
      style: `padding-left: .5rem;`
    }, ['object', {
      object: sig(),
      config
    }]], ['div', {
      style: `color: ${color}`
    }, 'Signal function: '], ['div', {
      style: `padding-left: .5rem;`
    }, ['object', {
      object: sig,
      config: {
        ...config,
        ngSkipFormatting: true
      }
    }]]];
  }
};
function prettifyPreview(value) {
  if (value === null) return 'null';
  if (Array.isArray(value)) return `Array(${value.length})`;
  if (value instanceof Element) return `<${value.tagName.toLowerCase()}>`;
  if (value instanceof URL) return `URL`;
  switch (typeof value) {
    case 'undefined':
      {
        return 'undefined';
      }
    case 'function':
      {
        if ('prototype' in value) {
          return 'class';
        } else {
          return '() => {…}';
        }
      }
    case 'object':
      {
        if (value.constructor.name === 'Object') {
          return '{…}';
        } else {
          return `${value.constructor.name} {}`;
        }
      }
    default:
      {
        return ['object', {
          object: value,
          config: {
            ngSkipFormatting: true
          }
        }];
      }
  }
}
function isSignal(value) {
  return value[SIGNAL] !== undefined;
}
function installDevToolsSignalFormatter() {
  globalThis.devtoolsFormatters ??= [];
  if (!globalThis.devtoolsFormatters.some(f => f === formatter)) {
    globalThis.devtoolsFormatters.push(formatter);
  }
}

function createWatch(fn, schedule, allowSignalWrites) {
  const node = Object.create(WATCH_NODE);
  if (allowSignalWrites) {
    node.consumerAllowSignalWrites = true;
  }
  node.fn = fn;
  node.schedule = schedule;
  const registerOnCleanup = cleanupFn => {
    node.cleanupFn = cleanupFn;
  };
  function isWatchNodeDestroyed(node) {
    return node.fn === null && node.schedule === null;
  }
  function destroyWatchNode(node) {
    if (!isWatchNodeDestroyed(node)) {
      consumerDestroy(node);
      node.cleanupFn();
      node.fn = null;
      node.schedule = null;
      node.cleanupFn = NOOP_CLEANUP_FN;
    }
  }
  const run = () => {
    if (node.fn === null) {
      return;
    }
    if (isInNotificationPhase()) {
      throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? 'Schedulers cannot synchronously execute watches while scheduling.' : '');
    }
    node.dirty = false;
    if (node.version > 0 && !consumerPollProducersForChange(node)) {
      return;
    }
    node.version++;
    const prevConsumer = consumerBeforeComputation(node);
    try {
      node.cleanupFn();
      node.cleanupFn = NOOP_CLEANUP_FN;
      node.fn(registerOnCleanup);
    } finally {
      consumerAfterComputation(node, prevConsumer);
    }
  };
  node.ref = {
    notify: () => consumerMarkDirty(node),
    run,
    cleanup: () => node.cleanupFn(),
    destroy: () => destroyWatchNode(node),
    [SIGNAL]: node
  };
  return node.ref;
}
const NOOP_CLEANUP_FN = () => {};
const WATCH_NODE = /* @__PURE__ */(() => {
  return {
    ...REACTIVE_NODE,
    consumerIsAlwaysLive: true,
    consumerAllowSignalWrites: false,
    consumerMarkedDirty: node => {
      if (node.schedule !== null) {
        node.schedule(node.ref);
      }
    },
    cleanupFn: NOOP_CLEANUP_FN
  };
})();

if (typeof ngDevMode === 'undefined' || ngDevMode) {
  installDevToolsSignalFormatter();
}

export { REACTIVE_NODE, SIGNAL, consumerAfterComputation, consumerBeforeComputation, consumerDestroy, consumerMarkDirty, consumerPollProducersForChange, createWatch, installDevToolsSignalFormatter, isInNotificationPhase };
//# sourceMappingURL=primitives-signals.mjs.map
