component Alert {
  outputs {
    dismiss(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    action(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
  }

  props {
    size: string = "default"
    color: string = "info"
    variant: string = "soft"
    class: string = ""
    radius: string = "md"
    shadow: string = "sm"

    title: string = "Alert"
    description: string = ""
    items: unknown[] = []
    actions: unknown[] = []

    showIcon: boolean = false
    icon: string = ""
    dismissible: boolean = false
    dismissLabel: string = "Dismiss alert"
    role: string = "alert"
    live: string = "polite"

    linkLabel: string = ""
    linkHref: string = ""
    actionLabel: string = ""
    actionHref: string = ""
    compact: boolean = false

  }

  state visible: boolean = true

  functions {
    // The output name has to be written out rather than computed: outputs are
    // resolved as named properties, so a dynamic key would not reach a parent
    // binding. Only two names exist here, so a branch is honest and cheap.
    client function dispatchAlertEvent(sourceEvent, eventName, action, payload) {
      payload = {
        component: "Alert",
        title: title,
        color: color,
        variant: variant,
        action: action
      }

      if (eventName === "dismiss") {
        output.dismiss(payload)
      } else {
        output.action(payload)
      }
    }

    client function dismissAlert(sourceEvent) {
      visible = false
      dispatchAlertEvent(sourceEvent, "dismiss", null)
    }

    client function selectAction(sourceEvent, action) {
      dispatchAlertEvent(sourceEvent, "action", action)
    }
  }

  view {
    <section
      {...attrs}
      data-wrn-alert
      data-color="{color}"
      data-variant="{variant}"
      data-radius="{radius}"
      data-shadow="{shadow}"
      data-show="visible"
      aria-hidden="{visible ? 'false' : 'true'}"
      role="{role}"
      aria-live="{live}"
      class="wire-component wire-component--color-{color} wire-component--size-{size} wire-next--alert wire-next--alert-{variant} {compact ? 'wire-next--alert-compact' : ''} {class}"
    >
      {#if showIcon}
        <span class="wire-next__alert-icon" aria-hidden="true">
          {#if icon}
            <span class="{icon}"></span>
          {:else if color === "success"}
            <span class="icon-[lucide--circle-check]"></span>
          {:else if color === "danger"}
            <span class="icon-[lucide--circle-x]"></span>
          {:else if color === "warning"}
            <span class="icon-[lucide--triangle-alert]"></span>
          {:else}
            <span class="icon-[lucide--info]"></span>
          {/if}
        </span>
      {/if}

      <div class="wire-next__alert-body">
        {#if title}<strong class="wire-next__alert-title">{title}</strong>{/if}
        {#if description}<p>{description}</p>{/if}

        {#if items.length > 0}
          <ul>
            {#each items as item}<li>{item.label || item}</li>{/each}
          </ul>
        {/if}

        {#if actions.length > 0 || actionLabel || linkLabel}
          <div class="wire-next__alert-actions">
            {#each actions as item}
              <a
                href="{item.href || '#'}"
                data-variant="{item.variant || 'link'}"
                @click="selectAction(event, item)"
              >{item.label}</a>
            {/each}
            {#if actionLabel}
              <a
                href="{actionHref || '#'}"
                data-variant="action"
                @click="selectAction(event, { label: actionLabel, href: actionHref })"
              >{actionLabel}</a>
            {/if}
            {#if linkLabel}
              <a
                href="{linkHref || '#'}"
                data-variant="link"
                @click="selectAction(event, { label: linkLabel, href: linkHref })"
              >{linkLabel}</a>
            {/if}
          </div>
        {/if}
      </div>

      {#if dismissible}
        <button
          type="button"
          class="wire-next__alert-dismiss"
          aria-label="{dismissLabel}"
          @click="dismissAlert(event)"
        >
          <span class="icon-[lucide--x]" aria-hidden="true"></span>
        </button>
      {/if}
    </section>
  }

  style {
    .wire-next--alert-soft {
      border-color: color-mix(in srgb, var(--wire-alert-color) 45%, var(--wire-color-border));
      background: var(--wire-alert-soft);
    }
    .wire-next--alert-soft .wire-next__alert-title,
    .wire-next--alert-soft .wire-next__alert-icon,
    .wire-next--alert-soft .wire-next__alert-actions a {
      color: var(--wire-alert-color);
    }
    .wire-next--alert-solid {
      border-color: var(--wire-alert-color);
      background: var(--wire-alert-color);
      color: white;
    }
    .wire-next--alert.wire-next--alert-solid
      :is(
        .wire-next__alert-title,
        .wire-next__alert-body > p,
        .wire-next__alert-body li,
        .wire-next__alert-actions a,
        .wire-next__alert-icon
      ) {
      color: currentColor;
    }
    .wire-next--alert-solid[data-color="light"] {
      color: #18181b;
    }
    .wire-next--alert-solid[data-color="warning"] {
      color: #18181b;
    }
    .wire-next--alert-bordered {
      border-color: var(--wire-alert-color);
      background: var(--wire-color-surface);
    }
    .wire-next--alert-bordered .wire-next__alert-title,
    .wire-next--alert-bordered .wire-next__alert-icon,
    .wire-next--alert-bordered .wire-next__alert-actions a {
      color: var(--wire-alert-color);
    }
    .wire-next--alert-accent {
      border-color: color-mix(in srgb, var(--wire-alert-color) 35%, var(--wire-color-border));
      border-left: 4px solid var(--wire-alert-color);
      background: var(--wire-alert-soft);
    }
    .wire-next--alert-accent .wire-next__alert-title,
    .wire-next--alert-accent .wire-next__alert-icon,
    .wire-next--alert-accent .wire-next__alert-actions a {
      color: var(--wire-alert-color);
    }

    .wire-next--alert {
      --wire-alert-color: var(--wire-component-color);
      --wire-alert-soft: color-mix(in srgb, var(--wire-alert-color) 16%, var(--wire-color-surface));
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      gap: 0.8rem;
      width: 100%;
      padding: 1rem;
      border: 1px solid transparent;
      border-radius: var(--wire-radius, 0.75rem);
      color: var(--wire-color-text);
    }

    .wire-next--alert[data-radius="none"] {
      border-radius: 0;
    }

    .wire-next--alert[data-radius="sm"] {
      border-radius: var(--wire-radius-sm, 0.375rem);
    }

    .wire-next--alert[data-radius="lg"] {
      border-radius: calc(var(--wire-radius, 0.75rem) * 1.35);
    }

    .wire-next--alert[data-radius="xl"] {
      border-radius: calc(var(--wire-radius, 0.75rem) * 1.75);
    }

    .wire-next--alert[data-shadow="none"] {
      box-shadow: none;
    }

    .wire-next--alert[data-shadow="sm"] {
      box-shadow: 0 6px 16px color-mix(in srgb, #000 14%, transparent);
    }

    .wire-next--alert[data-shadow="md"] {
      box-shadow:
        0 2px 6px color-mix(in srgb, #000 10%, transparent),
        0 12px 28px color-mix(in srgb, #000 18%, transparent);
    }

    .wire-next--alert[data-shadow="lg"] {
      box-shadow:
        0 4px 10px color-mix(in srgb, #000 12%, transparent),
        0 20px 48px color-mix(in srgb, #000 24%, transparent);
    }

    .wire-next--alert[data-color="secondary"] {
      --wire-alert-color: #737373;
    }

    .wire-next--alert[data-color="success"] {
      --wire-alert-color: #0f9f8f;
    }

    .wire-next--alert[data-color="danger"] {
      --wire-alert-color: #dc3545;
    }

    .wire-next--alert[data-color="warning"] {
      --wire-alert-color: #eab308;
    }

    .wire-next--alert[data-color="info"] {
      --wire-alert-color: #2563eb;
    }

    .wire-next--alert[data-color="dark"] {
      --wire-alert-color: #27272a;
    }

    .wire-next--alert[data-color="light"] {
      --wire-alert-color: #f4f4f5;
    }

    .wire-next--alert-compact {
      padding: 0.75rem 0.9rem;
    }

    .wire-next--alert-compact:not(:has(.wire-next__alert-icon)):not(:has(.wire-next__alert-dismiss)) {
      grid-template-columns: minmax(0, 1fr);
    }

    .wire-next--alert-compact .wire-next__alert-body {
      display: block;
    }

    .wire-next--alert-compact .wire-next__alert-title {
      margin-right: 0.25rem;
    }

    .wire-next--alert-compact .wire-next__alert-body > p {
      display: inline;
    }

    .wire-next__alert-icon {
      display: inline-grid;
      width: 1.25rem;
      height: 1.25rem;
      place-items: center;
      margin-top: 0.05rem;
      color: var(--wire-alert-color);
    }

    .wire-next__alert-icon > span {
      width: 1rem;
      height: 1rem;
    }

    .wire-next__alert-body {
      display: grid;
      min-width: 0;
      gap: 0.35rem;
    }

    .wire-next__alert-title {
      font-size: 0.88rem;
      line-height: 1.45;
    }

    .wire-next__alert-body > p,
    .wire-next__alert-body li {
      color: inherit;
      font-size: 0.8rem;
      line-height: 1.55;
    }

    .wire-next__alert-body > ul {
      display: grid;
      gap: 0.25rem;
      margin: 0.15rem 0 0;
      padding-left: 1.25rem;
    }

    .wire-next__alert-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem 1rem;
      margin-top: 0.35rem;
    }

    .wire-next__alert-actions a {
      color: var(--wire-alert-color);
      font-size: 0.78rem;
      font-weight: 700;
      text-decoration: none;
    }

    .wire-next__alert-actions a:hover {
      text-decoration: underline;
    }

    .wire-next__alert-actions a[data-variant="action"] {
      padding: 0.35rem 0.6rem;
      border-radius: var(--wire-radius-sm);
      background: var(--wire-alert-color);
      color: white;
      text-decoration: none;
    }

    .wire-next__alert-dismiss {
      display: inline-grid;
      width: 1.75rem;
      height: 1.75rem;
      place-items: center;
      padding: 0;
      border: 0;
      border-radius: var(--wire-radius-sm);
      background: transparent;
      color: currentColor;
      cursor: pointer;
    }

    .wire-next__alert-dismiss:hover {
      background: color-mix(in srgb, currentColor 10%, transparent);
    }

    .wire-next__alert-dismiss:focus-visible {
      outline: 2px solid currentColor;
      outline-offset: 2px;
    }

    @media (max-width: 36rem) {
    .wire-next--alert {
        grid-template-columns: auto minmax(0, 1fr);
      }
    .wire-next__alert-dismiss {
        grid-column: 2;
        grid-row: 1;
        justify-self: end;
      }
    }

    /* Shared component foundation. */

        .wire-component {
          --wire-component-color: var(--wire-color-primary);
          --wire-component-scale: 1;
          margin: 0;
          color: var(--wire-color-text);
          font-family: var(--wrn-font-sans, inherit);
        }

        .wire-component--color-primary {
          --wire-component-color: var(--wire-color-primary);
        }

        .wire-component--color-secondary {
          --wire-component-color: var(--wire-color-secondary);
        }

        .wire-component--color-success {
          --wire-component-color: var(--wire-color-success);
        }

        .wire-component--color-warning {
          --wire-component-color: var(--wire-color-warning);
        }

        .wire-component--color-danger {
          --wire-component-color: var(--wire-color-danger);
        }

        .wire-component--color-info {
          --wire-component-color: var(--wire-color-info);
        }

        .wire-component--size-xs {
          --wire-component-scale: 0.78;
        }

        .wire-component--size-sm {
          --wire-component-scale: 0.88;
        }

        .wire-component--size-default,
        .wire-component--size-md {
          --wire-component-scale: 1;
        }

        .wire-component--size-lg {
          --wire-component-scale: 1.14;
        }

        .wire-component--size-xl {
          --wire-component-scale: 1.28;
        }

        .wire-component:not(.wire-btn) {
          font-size: calc(1em * var(--wire-component-scale));
        }

        .wire-component :is(a, button, input, select, textarea):focus-visible {
          outline-color: var(--wire-component-color);
        }

        .wire-component p {
          margin: 0;
          color: var(--wire-color-muted);
          line-height: 1.6;
        }
  }
}
