Bumps all 47 packages, the root manifest and the VS Code extension to 0.8.6, and rebuilds the editor compiler, language server and extension bundles that embed the version. The release carries the output delivery fix: camelCase outputs now reach parent bindings, and 18 components emit through output.* instead of hand-built CustomEvents. See the 0.8.6 migration entry for what changes for consumers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
209 lines
7.6 KiB
Plaintext
209 lines
7.6 KiB
Plaintext
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="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--accordion wire-next--accordion-{variant} {bordered ? 'wire-next--accordion-bordered' : ''} {separated ? 'wire-next--accordion-separated' : ''} {flush ? 'wire-next--accordion-flush' : ''} {disabled ? 'wire-next--disabled' : ''} {class}"
|
|
>
|
|
{#each items as item, index}
|
|
<section
|
|
class="wire-next__accordion-item"
|
|
data-open="{isOpen(itemValue(item, index)) ? 'true' : 'false'}"
|
|
data-disabled="{disabled || item.disabled ? 'true' : 'false'}"
|
|
>
|
|
<h3 class="wire-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="wire-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="wire-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="wire-next__accordion-panel"
|
|
role="region"
|
|
aria-labelledby="{id}-trigger-{index}"
|
|
aria-hidden="{isOpen(itemValue(item, index)) ? 'false' : 'true'}"
|
|
>
|
|
<div>
|
|
<div class="wire-next__accordion-content {contentItalic ? 'wire-next__accordion-content-italic' : ''}">
|
|
{#if item.content}<p>{item.content}</p>{/if}
|
|
|
|
{#if item.children && item.children.length > 0}
|
|
<div class="wire-next__accordion-nested">
|
|
{#each item.children as child, childIndex}
|
|
<section
|
|
class="wire-next__accordion-item"
|
|
data-open="{isOpen(nestedValue(item, index, child, childIndex)) ? 'true' : 'false'}"
|
|
>
|
|
<h4 class="wire-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="wire-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="wire-next__accordion-panel"
|
|
role="region"
|
|
aria-labelledby="{id}-trigger-{index}-{childIndex}"
|
|
aria-hidden="{isOpen(nestedValue(item, index, child, childIndex)) ? 'false' : 'true'}"
|
|
>
|
|
<div>
|
|
<div class="wire-next__accordion-content {contentItalic ? 'wire-next__accordion-content-italic' : ''}">
|
|
<p>{child.content}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{/each}
|
|
</div>
|
|
}
|
|
}
|