component Accordion {
  outputs {
    change(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
    open(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    close(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
  }

  props {
    size: string = "default"
    color: string = "primary"
    variant: string = "default"
    class: string = ""

    id: string = "accordion"
    items: unknown[] = []
    defaultOpen: unknown[] = []
    multiple: boolean = false
    alwaysOpen: boolean = false
    disabled: boolean = false

    indicator: string = "plus"
    indicatorPosition: string = "start"
    showIndicator: boolean = true
    bordered: boolean = false
    separated: boolean = false
    flush: boolean = false
    contentItalic: boolean = false

}

  state openValues = defaultOpen

  functions {
    shared function itemValue(item, index) {
      return item.value !== undefined && item.value !== ""
        ? String(item.value)
        : String(index)
    }

    shared function nestedValue(parent, parentIndex, item, index) {
      return itemValue(parent, parentIndex) + "." + itemValue(item, index)
    }

    shared function isOpen(value) {
      return openValues.includes(value)
    }

    shared function allowsMultiple() {
      return multiple || alwaysOpen
    }

    // Named rather than computed: an output is resolved as a property name, so
    // output[eventName] would not reach a parent binding.
    client function dispatchAccordionEvent(sourceEvent, eventName, value, item, payload) {
      payload = {
        component: "Accordion",
        value: value,
        item: item,
        open: isOpen(value),
        openValues: openValues
      }

      if (eventName === "open") {
        output.open(payload)
      } else if (eventName === "close") {
        output.close(payload)
      } else {
        output.change(payload)
      }
    }

    client function toggleItem(sourceEvent, value, item, wasOpen) {
      if (disabled || item.disabled) {
        return
      }

      wasOpen = isOpen(value)

      if (wasOpen) {
        openValues = openValues.filter((entry) => entry !== value)
      } else if (allowsMultiple()) {
        openValues = openValues.concat([value])
      } else {
        openValues = [value]
      }

      dispatchAccordionEvent(
        sourceEvent,
        wasOpen ? "close" : "open",
        value,
        item
      )
      dispatchAccordionEvent(sourceEvent, "change", value, item)
    }

  }

  view {
    <div
      {...attrs}
      id="{id}"
      data-wrn-accordion
      data-variant="{variant}"
      data-indicator="{indicator}"
      data-multiple="{allowsMultiple() ? 'true' : 'false'}"
      class="wrn-component wrn-component--color-{color} wrn-component--size-{size} wrn-next--accordion wrn-next--accordion-{variant} {bordered ? 'wrn-next--accordion-bordered' : ''} {separated ? 'wrn-next--accordion-separated' : ''} {flush ? 'wrn-next--accordion-flush' : ''} {disabled ? 'wrn-next--disabled' : ''} {class}"
    >
      {#each items as item, index}
        <section
          class="wrn-next__accordion-item"
          data-open="{isOpen(itemValue(item, index)) ? 'true' : 'false'}"
          data-disabled="{disabled || item.disabled ? 'true' : 'false'}"
        >
          <h3 class="wrn-next__accordion-heading">
            <button
              type="button"
              id="{id}-trigger-{index}"
              aria-expanded="{isOpen(itemValue(item, index)) ? 'true' : 'false'}"
              aria-controls="{id}-panel-{index}"
              disabled="{disabled || item.disabled}"
              @click="toggleItem(event, itemValue(item, index), item)"
            >
              {#if showIndicator && indicatorPosition === "start"}
                <span class="wrn-next__accordion-indicator" aria-hidden="true">
                  {#if indicator === "chevron"}
                    <span class="icon-[lucide--chevron-down]"></span>
                  {:else}
                    <span>+</span>
                  {/if}
                </span>
              {/if}
              <span>{item.label || item.title}</span>
              {#if showIndicator && indicatorPosition === "end"}
                <span class="wrn-next__accordion-indicator" aria-hidden="true">
                  {#if indicator === "chevron"}
                    <span class="icon-[lucide--chevron-down]"></span>
                  {:else}
                    <span>+</span>
                  {/if}
                </span>
              {/if}
            </button>
          </h3>

          <div
            id="{id}-panel-{index}"
            class="wrn-next__accordion-panel"
            role="region"
            aria-labelledby="{id}-trigger-{index}"
            aria-hidden="{isOpen(itemValue(item, index)) ? 'false' : 'true'}"
          >
            <div>
              <div class="wrn-next__accordion-content {contentItalic ? 'wrn-next__accordion-content-italic' : ''}">
                {#if item.content}<p>{item.content}</p>{/if}

                {#if item.children && item.children.length > 0}
                  <div class="wrn-next__accordion-nested">
                    {#each item.children as child, childIndex}
                      <section
                        class="wrn-next__accordion-item"
                        data-open="{isOpen(nestedValue(item, index, child, childIndex)) ? 'true' : 'false'}"
                      >
                        <h4 class="wrn-next__accordion-heading">
                          <button
                            type="button"
                            id="{id}-trigger-{index}-{childIndex}"
                            aria-expanded="{isOpen(nestedValue(item, index, child, childIndex)) ? 'true' : 'false'}"
                            aria-controls="{id}-panel-{index}-{childIndex}"
                            disabled="{disabled || child.disabled}"
                            @click="toggleItem(event, nestedValue(item, index, child, childIndex), child)"
                          >
                            {#if showIndicator}
                              <span class="wrn-next__accordion-indicator" aria-hidden="true">
                                {#if indicator === "chevron"}
                                  <span class="icon-[lucide--chevron-down]"></span>
                                {:else}
                                  <span>+</span>
                                {/if}
                              </span>
                            {/if}
                            <span>{child.label || child.title}</span>
                          </button>
                        </h4>
                        <div
                          id="{id}-panel-{index}-{childIndex}"
                          class="wrn-next__accordion-panel"
                          role="region"
                          aria-labelledby="{id}-trigger-{index}-{childIndex}"
                          aria-hidden="{isOpen(nestedValue(item, index, child, childIndex)) ? 'false' : 'true'}"
                        >
                          <div>
                            <div class="wrn-next__accordion-content {contentItalic ? 'wrn-next__accordion-content-italic' : ''}">
                              <p>{child.content}</p>
                            </div>
                          </div>
                        </div>
                      </section>
                    {/each}
                  </div>
                {/if}
              </div>
            </div>
          </div>
        </section>
      {/each}
    </div>
  }

  style {
    .wrn-next--accordion {
      --wrn-accordion-accent: var(--wrn-component-color);
      display: grid;
      width: 100%;
      color: var(--wrn-color-text);
    }

    .wrn-next__accordion-item {
      min-width: 0;
    }

    .wrn-next__accordion-heading {
      margin: 0;
      font: inherit;
    }

    .wrn-next__accordion-heading > button {
      display: flex;
      width: 100%;
      align-items: center;
      gap: 0.75rem;
      padding: 0.85rem 0;
      border: 0;
      background: transparent;
      color: var(--wrn-color-text);
      font: inherit;
      font-size: 0.88rem;
      font-weight: 700;
      text-align: left;
      cursor: pointer;
    }

    .wrn-next__accordion-heading > button > span:not(.wrn-next__accordion-indicator) {
      min-width: 0;
      flex: 1;
    }

    .wrn-next__accordion-heading > button:focus-visible {
      border-radius: var(--wrn-radius-sm);
      outline: 2px solid var(--wrn-accordion-accent);
      outline-offset: 2px;
    }

    .wrn-next__accordion-heading > button:disabled {
      cursor: not-allowed;
      opacity: 0.5;
    }

    .wrn-next__accordion-indicator {
      display: inline-flex;
      width: 1rem;
      height: 1rem;
      flex: 0 0 1rem;
      align-items: center;
      justify-content: center;
      color: var(--wrn-color-muted);
      font-size: 1rem;
      font-weight: 500;
      line-height: 1;
      transition:
        color var(--wrn-motion-fast) var(--wrn-ease-standard),
        transform var(--wrn-motion-fast) var(--wrn-ease-standard);
    }

    .wrn-next__accordion-indicator > span {
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }

    .wrn-next__accordion-indicator > [class*="icon-["] {
      width: 0.95rem;
      height: 0.95rem;
    }

    .wrn-next__accordion-item[data-open="true"]
      > .wrn-next__accordion-heading
      .wrn-next__accordion-indicator {
      color: var(--wrn-accordion-accent);
      transform: rotate(45deg);
    }

    .wrn-next--accordion[data-indicator="chevron"]
      .wrn-next__accordion-item[data-open="true"]
      > .wrn-next__accordion-heading
      .wrn-next__accordion-indicator {
      transform: rotate(180deg);
    }

    .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-heading > button {
      color: var(--wrn-accordion-accent);
    }

    .wrn-next__accordion-panel {
      display: grid;
      grid-template-rows: 0fr;
      opacity: 0;
      transition:
        grid-template-rows var(--wrn-motion-base) var(--wrn-ease-standard),
        opacity var(--wrn-motion-fast) var(--wrn-ease-standard);
    }

    .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-panel {
      grid-template-rows: 1fr;
      opacity: 1;
    }

    .wrn-next__accordion-panel > div {
      overflow: hidden;
    }

    .wrn-next__accordion-content {
      padding: 0 0 1rem 1.75rem;
      color: var(--wrn-color-muted);
      font-size: 0.86rem;
      line-height: 1.65;
    }

    .wrn-next__accordion-content > p {
      color: inherit;
    }

    .wrn-next__accordion-content-italic > p::first-line {
      font-style: italic;
    }

    .wrn-next__accordion-nested {
      display: grid;
      margin-top: 0.5rem;
    }

    .wrn-next__accordion-nested .wrn-next__accordion-content {
      padding-left: 1.5rem;
    }

    .wrn-next--accordion-bordered {
      overflow: hidden;
      border: 1px solid var(--wrn-color-border);
      border-radius: var(--wrn-radius-md);
      background: var(--wrn-color-surface);
    }

    .wrn-next--accordion-bordered > .wrn-next__accordion-item + .wrn-next__accordion-item {
      border-top: 1px solid var(--wrn-color-border);
    }

    .wrn-next--accordion-bordered
      > .wrn-next__accordion-item
      > .wrn-next__accordion-heading
      > button {
      padding-inline: 1rem;
    }

    .wrn-next--accordion-bordered
      > .wrn-next__accordion-item
      > .wrn-next__accordion-panel
      .wrn-next__accordion-content {
      padding-inline: 1rem;
    }

    .wrn-next--accordion-separated {
      gap: 0.5rem;
    }

    .wrn-next--accordion-separated > .wrn-next__accordion-item {
      overflow: hidden;
      border: 1px solid transparent;
      border-radius: var(--wrn-radius-md);
      background: var(--wrn-color-surface-2);
    }

    .wrn-next--accordion-separated > .wrn-next__accordion-item[data-open="true"] {
      border-color: var(--wrn-color-border);
    }

    .wrn-next--accordion-separated
      > .wrn-next__accordion-item
      > .wrn-next__accordion-heading
      > button,
    .wrn-next--accordion-separated
      > .wrn-next__accordion-item
      > .wrn-next__accordion-panel
      .wrn-next__accordion-content {
      padding-inline: 1rem;
    }

    .wrn-next--accordion-flush {
      border-radius: 0;
      background: transparent;
      box-shadow: none;
    }

    @media (prefers-reduced-motion: reduce) {
    .wrn-next__accordion-panel,
      .wrn-next__accordion-indicator {
        transition: none;
      }
    }

    /* Shared component foundation. */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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