mirror of https://github.com/sveltejs/svelte
feat: customizable select (#17429)
* feat: customizable select * fix: treat inner of options as separate templates * fix: add hydration comment * fix: clear with textContent * fix: mark rich content option as dynamic and allow optgroup * fix: allow select with rich content and rename * chore: revert tests * fix: recursively check rich options * chore: change name of template * fix: mark boundary as dynamic * chore: add snapshot tests * chore: include comprehensive hydration test * fix: consider `selectedelement` as ancestor of `option` elements * fix: make `:has` work with `selectedcontent` * chore: failing test for css * fix: also return parent for adjacent_only * fix: move hydration marker at the end * chore: apply suggestions from code review Co-authored-by: Rich Harris <rich.harris@vercel.com> * fix: treat text elements in select and optgroup as rich * fix hydration * colocate code * drop the element, it's cleaner * rename module * update test * Update .changeset/chubby-dingos-laugh.md * fix a11y warning that occurs when button only contains selectedcontent * remove unused parameter * last part is redundant * simplify * unnecessary, the constraints overlap * this is taken care of during analysis * simplify * tweak * tweak * tweak * fix/tweak * tweak --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>pull/17480/head
parent
3046004ec3
commit
645eb12258
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': minor
|
||||
---
|
||||
|
||||
feat: customizable `<select>` elements
|
||||
@ -0,0 +1,51 @@
|
||||
import { hydrating, reset, set_hydrate_node, set_hydrating } from '../hydration.js';
|
||||
import { create_comment } from '../operations.js';
|
||||
|
||||
/** @type {boolean | null} */
|
||||
let supported = null;
|
||||
|
||||
/**
|
||||
* Checks if the browser supports rich HTML content inside `<option>` elements.
|
||||
* Modern browsers preserve HTML elements inside options, while older browsers
|
||||
* strip them during parsing, leaving only text content.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function is_supported() {
|
||||
if (supported === null) {
|
||||
var select = document.createElement('select');
|
||||
select.innerHTML = '<option><span>t</span></option>';
|
||||
supported = /** @type {Element} */ (select.firstChild)?.firstChild?.nodeType === 1;
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles rich HTML content inside `<option>`, `<optgroup>`, or `<select>` elements with browser-specific branching.
|
||||
* Modern browsers preserve HTML inside options, while older browsers strip it to text only.
|
||||
*
|
||||
* @param {HTMLOptionElement | HTMLOptGroupElement | HTMLSelectElement} element The element to process
|
||||
* @param {() => void} rich_fn Function to process rich HTML content (modern browsers)
|
||||
*/
|
||||
export function customizable_select(element, rich_fn) {
|
||||
var was_hydrating = hydrating;
|
||||
|
||||
if (!is_supported()) {
|
||||
set_hydrating(false);
|
||||
element.textContent = '';
|
||||
element.append(create_comment(''));
|
||||
}
|
||||
|
||||
try {
|
||||
rich_fn();
|
||||
} finally {
|
||||
if (was_hydrating) {
|
||||
if (hydrating) {
|
||||
reset(element);
|
||||
} else {
|
||||
set_hydrating(true);
|
||||
set_hydrate_node(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
|
||||
select.svelte-xyz,
|
||||
.svelte-xyz::picker(select) {
|
||||
appearance: base-select;
|
||||
}
|
||||
selectedcontent.svelte-xyz b:where(.svelte-xyz){
|
||||
color: red;
|
||||
}
|
||||
e.svelte-xyz{
|
||||
selectedcontent:where(.svelte-xyz) &{
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
select.svelte-xyz > button:where(.svelte-xyz) > selectedcontent:where(.svelte-xyz) > b:where(.svelte-xyz) {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
select.svelte-xyz > button:where(.svelte-xyz) > selectedcontent:where(.svelte-xyz) i:where(.svelte-xyz) {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
selectedcontent.svelte-xyz:has(b:where(.svelte-xyz)){
|
||||
background-color: rebeccapurple;
|
||||
}
|
||||
|
||||
selectedcontent.svelte-xyz:has(i:where(.svelte-xyz)){
|
||||
background-color: rebeccapurple;
|
||||
}
|
||||
|
||||
option.svelte-xyz > b:where(.svelte-xyz){
|
||||
color: orange;
|
||||
}
|
||||
|
||||
option.svelte-xyz b:where(.svelte-xyz){
|
||||
color: #ff3e00;
|
||||
}
|
||||
|
||||
option.svelte-xyz > b:where(.svelte-xyz) > i:where(.svelte-xyz){
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
option.svelte-xyz i:where(.svelte-xyz){
|
||||
text-decoration: dashed;
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<select>
|
||||
<button aria-label="Selected value">
|
||||
<selectedcontent></selectedcontent>
|
||||
</button>
|
||||
<option>plain text</option>
|
||||
<option><b>rich <i>italic</i></b><e>content</e></option>
|
||||
</select>
|
||||
|
||||
<style>
|
||||
select,
|
||||
::picker(select) {
|
||||
appearance: base-select;
|
||||
}
|
||||
selectedcontent b{
|
||||
color: red;
|
||||
}
|
||||
e{
|
||||
selectedcontent &{
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
select > button > selectedcontent > b {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
select > button > selectedcontent i {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
selectedcontent:has(b){
|
||||
background-color: rebeccapurple;
|
||||
}
|
||||
|
||||
selectedcontent:has(i){
|
||||
background-color: rebeccapurple;
|
||||
}
|
||||
|
||||
option > b{
|
||||
color: orange;
|
||||
}
|
||||
|
||||
option b{
|
||||
color: #ff3e00;
|
||||
}
|
||||
|
||||
option > b > i{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
option i{
|
||||
text-decoration: dashed;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,31 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
// This test verifies that hydration works correctly for
|
||||
// optgroup elements with rich HTML content (non-option elements inside optgroup)
|
||||
snapshot(target) {
|
||||
const select = target.querySelector('select');
|
||||
|
||||
return {
|
||||
select
|
||||
};
|
||||
},
|
||||
|
||||
async test(assert, target) {
|
||||
const optgroup = target.querySelector('optgroup');
|
||||
const options = target.querySelectorAll('option');
|
||||
const button = target.querySelector('button');
|
||||
|
||||
// Check options content - the span inside optgroup gets stripped but text remains
|
||||
assert.equal(options[0]?.textContent, 'hello hello');
|
||||
assert.equal(options[1]?.textContent, 'Plain option');
|
||||
|
||||
// Update via button click
|
||||
flushSync(() => {
|
||||
button?.click();
|
||||
});
|
||||
|
||||
assert.equal(options[0]?.textContent, 'changed changed');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
<select><optgroup label="Fruits">hello <option value="a"><span>hello</span> hello</option><option value="b">Plain option</option></optgroup><optgroup label="Static Group"><option value="c">Another option</option></optgroup></select> <button></button>
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
let label = $state('hello');
|
||||
</script>
|
||||
|
||||
<select>
|
||||
<optgroup label="Fruits">
|
||||
<span class="group-header">{label}</span>
|
||||
<option value="a"><span>{label}</span> {label}</option>
|
||||
<option value="b">Plain option</option>
|
||||
</optgroup>
|
||||
<optgroup label="Static Group">
|
||||
<option value="c">Another option</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<button onclick={() => label = "changed"}></button>
|
||||
@ -0,0 +1,34 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
// This test verifies that hydration continues correctly after
|
||||
// an option element with rich HTML content
|
||||
snapshot(target) {
|
||||
const select = target.querySelector('select');
|
||||
const options = target.querySelectorAll('option');
|
||||
const p = target.querySelector('p');
|
||||
const button = target.querySelector('button');
|
||||
|
||||
return {
|
||||
select,
|
||||
option1: options[0],
|
||||
option2: options[1],
|
||||
p,
|
||||
button
|
||||
};
|
||||
},
|
||||
|
||||
async test(assert, target) {
|
||||
const option = target.querySelector('option');
|
||||
const button = target.querySelector('button');
|
||||
|
||||
assert.equal(option?.textContent, 'hello hello');
|
||||
|
||||
flushSync(() => {
|
||||
button?.click();
|
||||
});
|
||||
|
||||
assert.equal(option?.textContent, 'changed changed');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
<select><option value="a">hello hello</option><option value="b">Plain text</option></select> <button></button>
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
let label = $state('hello');
|
||||
let count = $state(42);
|
||||
</script>
|
||||
|
||||
<select>
|
||||
<!-- this would fail during hydration if rich_option handling is not correct -->
|
||||
<option value="a"><span>{label}</span> {label}</option>
|
||||
<option value="b">Plain text</option>
|
||||
</select>
|
||||
|
||||
<button onclick={() => label = "changed"}></button>
|
||||
@ -0,0 +1,39 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
// This test verifies that completely static select with rich option content
|
||||
// hydrates correctly and the content is preserved
|
||||
snapshot(target) {
|
||||
const select = target.querySelector('select');
|
||||
const options = target.querySelectorAll('option');
|
||||
|
||||
return {
|
||||
select,
|
||||
option1: options[0],
|
||||
option2: options[1],
|
||||
option3: options[2]
|
||||
};
|
||||
},
|
||||
|
||||
async test(assert, target) {
|
||||
const options = target.querySelectorAll('option');
|
||||
|
||||
// Verify the rich content is present in the options
|
||||
assert.equal(options[0]?.textContent, 'Bold Option');
|
||||
assert.equal(options[1]?.textContent, 'Italic Option');
|
||||
assert.equal(options[2]?.textContent, 'Plain Option');
|
||||
|
||||
// Check that the rich elements are actually there (on supporting browsers)
|
||||
const strong = options[0]?.querySelector('strong');
|
||||
const em = options[1]?.querySelector('em');
|
||||
|
||||
// These may or may not exist depending on browser support
|
||||
// but the text content should always be correct
|
||||
if (strong) {
|
||||
assert.equal(strong.textContent, 'Bold');
|
||||
}
|
||||
if (em) {
|
||||
assert.equal(em.textContent, 'Italic');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
<select><option value="a"><strong>Bold</strong> Option</option><option value="b"><em>Italic</em> Option</option><option value="c">Plain Option</option></select>
|
||||
@ -0,0 +1,5 @@
|
||||
<select>
|
||||
<option value="a"><strong>Bold</strong> Option</option>
|
||||
<option value="b"><em>Italic</em> Option</option>
|
||||
<option value="c">Plain Option</option>
|
||||
</select>
|
||||
@ -0,0 +1 @@
|
||||
<option>Option component</option>
|
||||
@ -0,0 +1,3 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({});
|
||||
@ -0,0 +1,173 @@
|
||||
<script>
|
||||
let items = [1, 2, 3];
|
||||
let show = true;
|
||||
let html = '<option>From HTML</option>';
|
||||
|
||||
import Option from './Option.svelte';
|
||||
</script>
|
||||
|
||||
<!-- select with rich option (has span inside) - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option><span>Rich</span></option>
|
||||
</select>
|
||||
|
||||
<!-- select with each containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- select with if containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#if show}
|
||||
<option>Visible</option>
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<!-- select with key containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#key items}
|
||||
<option>Keyed</option>
|
||||
{/key}
|
||||
</select>
|
||||
|
||||
<!-- select with snippet defined at top level and rendered - should NOT use customizable_select_element -->
|
||||
{#snippet opt()}
|
||||
<option>Snippet</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{@render opt()}
|
||||
</select>
|
||||
|
||||
<!-- select with const inside each (should be ignored) - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
{@const x = item * 2}
|
||||
<option>{x}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- optgroup with rich option - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
<option><strong>Bold</strong></option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- optgroup with each containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- option with rich content (span) - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option value="a"><em>Italic</em> text</option>
|
||||
</select>
|
||||
|
||||
<!-- nested: select > each > option with rich content - SHOULD use customizable_select_element on option -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<option><span>{item}</span></option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- nested: select > if > each > plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#if show}
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<!-- select with svelte:boundary containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
<svelte:boundary>
|
||||
<option>Boundary</option>
|
||||
</svelte:boundary>
|
||||
</select>
|
||||
|
||||
<!-- select with svelte:boundary containing rich options - SHOULD use customizable_select_element on option -->
|
||||
<select>
|
||||
<svelte:boundary>
|
||||
<option><span>Rich in boundary</span></option>
|
||||
</svelte:boundary>
|
||||
</select>
|
||||
|
||||
<!-- select with Component - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
<Option />
|
||||
</select>
|
||||
|
||||
<!-- select with @render snippet - SHOULD be treated as rich content -->
|
||||
{#snippet option_snippet()}
|
||||
<option>Rendered</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{@render option_snippet()}
|
||||
</select>
|
||||
|
||||
<!-- select with @html - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
{@html html}
|
||||
</select>
|
||||
|
||||
<!-- optgroup with Component - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
<Option />
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- optgroup with @render - SHOULD be treated as rich content -->
|
||||
{#snippet option_snippet2()}
|
||||
<option>Rendered in group</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
{@render option_snippet2()}
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- option with @html inside - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option>{@html '<strong>Bold HTML</strong>'}</option>
|
||||
</select>
|
||||
|
||||
<!-- each block inside select with Component - SHOULD be treated as rich -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<Option />
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- if block inside select with @render - SHOULD be treated as rich -->
|
||||
{#snippet conditional_option()}
|
||||
<option>Conditional</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{#if show}
|
||||
{@render conditional_option()}
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<!-- select with button/selectedcontent and static options - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<button><selectedcontent></selectedcontent></button>
|
||||
<option>cool</option>
|
||||
<option>cooler</option>
|
||||
<option>coolerone</option>
|
||||
</select>
|
||||
|
||||
<!-- select with button/selectedcontent and dynamic options - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<button><selectedcontent></selectedcontent></button>
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
</select>
|
||||
@ -0,0 +1,31 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
// Test that optgroup with rich HTML content (non-option elements) and dynamic expressions works correctly
|
||||
export default test({
|
||||
mode: ['client', 'hydrate'],
|
||||
test({ assert, target }) {
|
||||
const select = /** @type {HTMLSelectElement} */ (target.querySelector('select'));
|
||||
const optgroups = target.querySelectorAll('optgroup');
|
||||
const options = target.querySelectorAll('option');
|
||||
const button = /** @type {HTMLButtonElement} */ (target.querySelector('button'));
|
||||
|
||||
assert.ok(select);
|
||||
assert.equal(optgroups.length, 2);
|
||||
assert.equal(options.length, 4);
|
||||
|
||||
// Check initial option content (rich content inside optgroup)
|
||||
assert.equal(options[0]?.textContent, 'apple apple');
|
||||
assert.equal(options[1]?.textContent, 'banana');
|
||||
assert.equal(options[2]?.textContent, 'carrot carrot');
|
||||
assert.equal(options[3]?.textContent, 'Plain celery');
|
||||
|
||||
// Click button to change dynamic content
|
||||
button.click();
|
||||
flushSync();
|
||||
|
||||
// Check updated option content
|
||||
assert.equal(options[0]?.textContent, 'orange orange');
|
||||
assert.equal(options[2]?.textContent, 'broccoli broccoli');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,19 @@
|
||||
<script>
|
||||
let fruit = $state('apple');
|
||||
let vegetable = $state('carrot');
|
||||
</script>
|
||||
|
||||
<select>
|
||||
<optgroup label="Fruits">
|
||||
<span class="fruits-header">{fruit}</span>
|
||||
<option value="a"><span>{fruit}</span> {fruit}</option>
|
||||
<option value="b">banana</option>
|
||||
</optgroup>
|
||||
<optgroup label="Vegetables">
|
||||
<em class="veggies-header">{vegetable}</em>
|
||||
<option value="c"><em>{vegetable}</em> {vegetable}</option>
|
||||
<option value="d">Plain celery</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<button onclick={() => { fruit = 'orange'; vegetable = 'broccoli'; }}>Change</button>
|
||||
@ -0,0 +1,37 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
// Test that rich HTML content in <option> elements compiles without errors
|
||||
// and that the component functions correctly (on browsers that support it)
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
test({ assert, target }) {
|
||||
const select = /** @type {HTMLSelectElement} */ (target.querySelector('select'));
|
||||
const p = /** @type {HTMLParagraphElement} */ (target.querySelector('p'));
|
||||
const button = /** @type {HTMLButtonElement} */ (target.querySelector('button'));
|
||||
|
||||
assert.ok(select);
|
||||
assert.ok(p);
|
||||
assert.ok(button);
|
||||
assert.equal(select.value, 'a');
|
||||
assert.equal(p.textContent, 'Selected: a');
|
||||
|
||||
// Verify options exist
|
||||
assert.equal(select.options.length, 3);
|
||||
|
||||
// Change selection
|
||||
select.value = 'b';
|
||||
select.dispatchEvent(new Event('change'));
|
||||
flushSync();
|
||||
|
||||
assert.equal(p.textContent, 'Selected: b');
|
||||
|
||||
// Test reactivity of content within option (only works on browsers that support rich options)
|
||||
// On modern browsers, clicking the button should update the text inside the span
|
||||
button.click();
|
||||
flushSync();
|
||||
|
||||
// The option text content should be updated on browsers that support rich options
|
||||
// For this test, we just verify the component doesn't crash
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
let selected = $state('a');
|
||||
let label_a = $state('Option');
|
||||
let label_b = $state('Strong');
|
||||
</script>
|
||||
|
||||
<select bind:value={selected}>
|
||||
<option value="a"><span>{label_a}</span> A</option>
|
||||
<option value="b"><strong>{label_b}</strong> B</option>
|
||||
<option value="c">Plain C</option>
|
||||
</select>
|
||||
|
||||
<p>Selected: {selected}</p>
|
||||
|
||||
<button onclick={() => label_a = 'Changed'}>Change A</button>
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
let { text } = $props();
|
||||
</script>
|
||||
|
||||
<span>{text}</span>
|
||||
@ -0,0 +1,26 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
// Test that components can be used inside <option> elements.
|
||||
// This tests two scenarios:
|
||||
// 1. A component that wraps the entire <option> element
|
||||
// 2. A component used as content inside an <option> element
|
||||
//
|
||||
// In jsdom (which doesn't support rich options), the HTML content is stripped,
|
||||
// so we only verify the component doesn't crash and values work correctly.
|
||||
export default test({
|
||||
test({ assert, target }) {
|
||||
const option1 = target.querySelector('option');
|
||||
const button = target.querySelector('button');
|
||||
|
||||
assert.ok(option1);
|
||||
|
||||
assert.equal(option1?.textContent, 'bb');
|
||||
|
||||
flushSync(() => {
|
||||
button?.click();
|
||||
});
|
||||
|
||||
assert.equal(option1?.textContent, 'aa');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import Content from './Content.svelte';
|
||||
|
||||
let content = $state('b');
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Test 2: Option with component as content -->
|
||||
<select>
|
||||
<option value="x"><span>{content}</span><Content text={content} /></option>
|
||||
</select>
|
||||
|
||||
<button onclick={() => content = content === 'a' ? 'b' : 'a'}>
|
||||
Toggle Content
|
||||
</button>
|
||||
@ -0,0 +1 @@
|
||||
<option>Component Option</option>
|
||||
@ -0,0 +1,11 @@
|
||||
import 'svelte/internal/disclose-version';
|
||||
import 'svelte/internal/flags/legacy';
|
||||
import * as $ from 'svelte/internal/client';
|
||||
|
||||
var root = $.from_html(`<option>Component Option</option>`);
|
||||
|
||||
export default function Option($$anchor) {
|
||||
var option = root();
|
||||
|
||||
$.append($$anchor, option);
|
||||
}
|
||||
@ -0,0 +1,412 @@
|
||||
import 'svelte/internal/disclose-version';
|
||||
import 'svelte/internal/flags/legacy';
|
||||
import * as $ from 'svelte/internal/client';
|
||||
import Option from './Option.svelte';
|
||||
|
||||
const opt = ($$anchor) => {
|
||||
var option = root_1();
|
||||
|
||||
$.append($$anchor, option);
|
||||
};
|
||||
|
||||
const option_snippet = ($$anchor) => {
|
||||
var option_1 = root_2();
|
||||
|
||||
$.append($$anchor, option_1);
|
||||
};
|
||||
|
||||
const option_snippet2 = ($$anchor) => {
|
||||
var option_2 = root_3();
|
||||
|
||||
$.append($$anchor, option_2);
|
||||
};
|
||||
|
||||
const conditional_option = ($$anchor) => {
|
||||
var option_3 = root_4();
|
||||
|
||||
$.append($$anchor, option_3);
|
||||
};
|
||||
|
||||
var root_1 = $.from_html(`<option>Snippet</option>`);
|
||||
var root_2 = $.from_html(`<option>Rendered</option>`);
|
||||
var root_3 = $.from_html(`<option>Rendered in group</option>`);
|
||||
var root_4 = $.from_html(`<option>Conditional</option>`);
|
||||
var option_content = $.from_html(`<span>Rich</span>`, 1);
|
||||
var root_5 = $.from_html(`<option> </option>`);
|
||||
var root_6 = $.from_html(`<option>Visible</option>`);
|
||||
var root_7 = $.from_html(`<option>Keyed</option>`);
|
||||
var select_content = $.from_html(`<!>`, 1);
|
||||
var root_8 = $.from_html(`<option> </option>`);
|
||||
var option_content_1 = $.from_html(`<strong>Bold</strong>`, 1);
|
||||
var root_9 = $.from_html(`<option> </option>`);
|
||||
var option_content_2 = $.from_html(`<em>Italic</em> text`, 1);
|
||||
var option_content_3 = $.from_html(`<span> </span>`, 1);
|
||||
var root_10 = $.from_html(`<option><!></option>`);
|
||||
var root_12 = $.from_html(`<option> </option>`);
|
||||
var root_13 = $.from_html(`<option>Boundary</option>`);
|
||||
var option_content_4 = $.from_html(`<span>Rich in boundary</span>`, 1);
|
||||
var root_14 = $.from_html(`<option><!></option>`);
|
||||
var select_content_1 = $.from_html(`<!>`, 1);
|
||||
var select_content_2 = $.from_html(`<!>`, 1);
|
||||
var select_content_3 = $.from_html(`<!>`, 1);
|
||||
var optgroup_content = $.from_html(`<!>`, 1);
|
||||
var optgroup_content_1 = $.from_html(`<!>`, 1);
|
||||
var option_content_5 = $.from_html(`<!>`, 1);
|
||||
var select_content_4 = $.from_html(`<!>`, 1);
|
||||
var select_content_5 = $.from_html(`<!>`, 1);
|
||||
var root = $.from_html(`<select><option><!></option></select> <select></select> <select><!></select> <select><!></select> <select><!></select> <select></select> <select><optgroup label="Group"><option><!></option></optgroup></select> <select><optgroup label="Group"></optgroup></select> <select><option><!></option></select> <select></select> <select><!></select> <select><!></select> <select><!></select> <select><!></select> <select><!></select> <select><!></select> <select><optgroup label="Group"><!></optgroup></select> <select><optgroup label="Group"><!></optgroup></select> <select><option><!></option></select> <select><!></select> <select><!></select>`, 1);
|
||||
|
||||
export default function Select_with_rich_content($$anchor) {
|
||||
let items = [1, 2, 3];
|
||||
let show = true;
|
||||
let html = '<option>From HTML</option>';
|
||||
var fragment = root();
|
||||
var select = $.first_child(fragment);
|
||||
var option_4 = $.child(select);
|
||||
|
||||
$.customizable_select(option_4, () => {
|
||||
var anchor = $.child(option_4);
|
||||
var fragment_1 = option_content();
|
||||
|
||||
$.append(anchor, fragment_1);
|
||||
});
|
||||
|
||||
$.reset(select);
|
||||
|
||||
var select_1 = $.sibling(select, 2);
|
||||
|
||||
$.each(select_1, 5, () => items, $.index, ($$anchor, item) => {
|
||||
var option_5 = root_5();
|
||||
var text = $.child(option_5, true);
|
||||
|
||||
$.reset(option_5);
|
||||
|
||||
var option_5_value = {};
|
||||
|
||||
$.template_effect(() => {
|
||||
$.set_text(text, $.get(item));
|
||||
|
||||
if (option_5_value !== (option_5_value = $.get(item))) {
|
||||
option_5.__value = $.get(item);
|
||||
}
|
||||
});
|
||||
|
||||
$.append($$anchor, option_5);
|
||||
});
|
||||
|
||||
$.reset(select_1);
|
||||
|
||||
var select_2 = $.sibling(select_1, 2);
|
||||
var node = $.child(select_2);
|
||||
|
||||
{
|
||||
var consequent = ($$anchor) => {
|
||||
var option_6 = root_6();
|
||||
|
||||
$.append($$anchor, option_6);
|
||||
};
|
||||
|
||||
$.if(node, ($$render) => {
|
||||
if (show) $$render(consequent);
|
||||
});
|
||||
}
|
||||
|
||||
$.reset(select_2);
|
||||
|
||||
var select_3 = $.sibling(select_2, 2);
|
||||
var node_1 = $.child(select_3);
|
||||
|
||||
$.key(node_1, () => items, ($$anchor) => {
|
||||
var option_7 = root_7();
|
||||
|
||||
$.append($$anchor, option_7);
|
||||
});
|
||||
|
||||
$.reset(select_3);
|
||||
|
||||
var select_4 = $.sibling(select_3, 2);
|
||||
|
||||
$.customizable_select(select_4, () => {
|
||||
var anchor_1 = $.child(select_4);
|
||||
var fragment_2 = select_content();
|
||||
var node_2 = $.first_child(fragment_2);
|
||||
|
||||
opt(node_2);
|
||||
$.append(anchor_1, fragment_2);
|
||||
});
|
||||
|
||||
var select_5 = $.sibling(select_4, 2);
|
||||
|
||||
$.each(select_5, 5, () => items, $.index, ($$anchor, item) => {
|
||||
const x = $.derived_safe_equal(() => $.get(item) * 2);
|
||||
var option_8 = root_8();
|
||||
var text_1 = $.child(option_8, true);
|
||||
|
||||
$.reset(option_8);
|
||||
|
||||
var option_8_value = {};
|
||||
|
||||
$.template_effect(() => {
|
||||
$.set_text(text_1, $.get(x));
|
||||
|
||||
if (option_8_value !== (option_8_value = $.get(x))) {
|
||||
option_8.__value = $.get(x);
|
||||
}
|
||||
});
|
||||
|
||||
$.append($$anchor, option_8);
|
||||
});
|
||||
|
||||
$.reset(select_5);
|
||||
|
||||
var select_6 = $.sibling(select_5, 2);
|
||||
var optgroup = $.child(select_6);
|
||||
var option_9 = $.child(optgroup);
|
||||
|
||||
$.customizable_select(option_9, () => {
|
||||
var anchor_2 = $.child(option_9);
|
||||
var fragment_3 = option_content_1();
|
||||
|
||||
$.append(anchor_2, fragment_3);
|
||||
});
|
||||
|
||||
$.reset(optgroup);
|
||||
$.reset(select_6);
|
||||
|
||||
var select_7 = $.sibling(select_6, 2);
|
||||
var optgroup_1 = $.child(select_7);
|
||||
|
||||
$.each(optgroup_1, 5, () => items, $.index, ($$anchor, item) => {
|
||||
var option_10 = root_9();
|
||||
var text_2 = $.child(option_10, true);
|
||||
|
||||
$.reset(option_10);
|
||||
|
||||
var option_10_value = {};
|
||||
|
||||
$.template_effect(() => {
|
||||
$.set_text(text_2, $.get(item));
|
||||
|
||||
if (option_10_value !== (option_10_value = $.get(item))) {
|
||||
option_10.__value = $.get(item);
|
||||
}
|
||||
});
|
||||
|
||||
$.append($$anchor, option_10);
|
||||
});
|
||||
|
||||
$.reset(optgroup_1);
|
||||
$.reset(select_7);
|
||||
|
||||
var select_8 = $.sibling(select_7, 2);
|
||||
var option_11 = $.child(select_8);
|
||||
|
||||
$.customizable_select(option_11, () => {
|
||||
var anchor_3 = $.child(option_11);
|
||||
var fragment_4 = option_content_2();
|
||||
|
||||
$.next();
|
||||
$.append(anchor_3, fragment_4);
|
||||
});
|
||||
|
||||
option_11.value = option_11.__value = 'a';
|
||||
$.reset(select_8);
|
||||
|
||||
var select_9 = $.sibling(select_8, 2);
|
||||
|
||||
$.each(select_9, 5, () => items, $.index, ($$anchor, item) => {
|
||||
var option_12 = root_10();
|
||||
|
||||
$.customizable_select(option_12, () => {
|
||||
var anchor_4 = $.child(option_12);
|
||||
var fragment_5 = option_content_3();
|
||||
var span = $.first_child(fragment_5);
|
||||
var text_3 = $.child(span, true);
|
||||
|
||||
$.reset(span);
|
||||
$.template_effect(() => $.set_text(text_3, $.get(item)));
|
||||
$.append(anchor_4, fragment_5);
|
||||
});
|
||||
|
||||
$.append($$anchor, option_12);
|
||||
});
|
||||
|
||||
$.reset(select_9);
|
||||
|
||||
var select_10 = $.sibling(select_9, 2);
|
||||
var node_3 = $.child(select_10);
|
||||
|
||||
{
|
||||
var consequent_1 = ($$anchor) => {
|
||||
var fragment_6 = $.comment();
|
||||
var node_4 = $.first_child(fragment_6);
|
||||
|
||||
$.each(node_4, 1, () => items, $.index, ($$anchor, item) => {
|
||||
var option_13 = root_12();
|
||||
var text_4 = $.child(option_13, true);
|
||||
|
||||
$.reset(option_13);
|
||||
|
||||
var option_13_value = {};
|
||||
|
||||
$.template_effect(() => {
|
||||
$.set_text(text_4, $.get(item));
|
||||
|
||||
if (option_13_value !== (option_13_value = $.get(item))) {
|
||||
option_13.__value = $.get(item);
|
||||
}
|
||||
});
|
||||
|
||||
$.append($$anchor, option_13);
|
||||
});
|
||||
|
||||
$.append($$anchor, fragment_6);
|
||||
};
|
||||
|
||||
$.if(node_3, ($$render) => {
|
||||
if (show) $$render(consequent_1);
|
||||
});
|
||||
}
|
||||
|
||||
$.reset(select_10);
|
||||
|
||||
var select_11 = $.sibling(select_10, 2);
|
||||
var node_5 = $.child(select_11);
|
||||
|
||||
$.boundary(node_5, {}, ($$anchor) => {
|
||||
var option_14 = root_13();
|
||||
|
||||
$.append($$anchor, option_14);
|
||||
});
|
||||
|
||||
$.reset(select_11);
|
||||
|
||||
var select_12 = $.sibling(select_11, 2);
|
||||
var node_6 = $.child(select_12);
|
||||
|
||||
$.boundary(node_6, {}, ($$anchor) => {
|
||||
var option_15 = root_14();
|
||||
|
||||
$.customizable_select(option_15, () => {
|
||||
var anchor_5 = $.child(option_15);
|
||||
var fragment_7 = option_content_4();
|
||||
|
||||
$.append(anchor_5, fragment_7);
|
||||
});
|
||||
|
||||
$.append($$anchor, option_15);
|
||||
});
|
||||
|
||||
$.reset(select_12);
|
||||
|
||||
var select_13 = $.sibling(select_12, 2);
|
||||
|
||||
$.customizable_select(select_13, () => {
|
||||
var anchor_6 = $.child(select_13);
|
||||
var fragment_8 = select_content_1();
|
||||
var node_7 = $.first_child(fragment_8);
|
||||
|
||||
Option(node_7, {});
|
||||
$.append(anchor_6, fragment_8);
|
||||
});
|
||||
|
||||
var select_14 = $.sibling(select_13, 2);
|
||||
|
||||
$.customizable_select(select_14, () => {
|
||||
var anchor_7 = $.child(select_14);
|
||||
var fragment_9 = select_content_2();
|
||||
var node_8 = $.first_child(fragment_9);
|
||||
|
||||
option_snippet(node_8);
|
||||
$.append(anchor_7, fragment_9);
|
||||
});
|
||||
|
||||
var select_15 = $.sibling(select_14, 2);
|
||||
|
||||
$.customizable_select(select_15, () => {
|
||||
var anchor_8 = $.child(select_15);
|
||||
var fragment_10 = select_content_3();
|
||||
var node_9 = $.first_child(fragment_10);
|
||||
|
||||
$.html(node_9, () => html);
|
||||
$.append(anchor_8, fragment_10);
|
||||
});
|
||||
|
||||
var select_16 = $.sibling(select_15, 2);
|
||||
var optgroup_2 = $.child(select_16);
|
||||
|
||||
$.customizable_select(optgroup_2, () => {
|
||||
var anchor_9 = $.child(optgroup_2);
|
||||
var fragment_11 = optgroup_content();
|
||||
var node_10 = $.first_child(fragment_11);
|
||||
|
||||
Option(node_10, {});
|
||||
$.append(anchor_9, fragment_11);
|
||||
});
|
||||
|
||||
$.reset(select_16);
|
||||
|
||||
var select_17 = $.sibling(select_16, 2);
|
||||
var optgroup_3 = $.child(select_17);
|
||||
|
||||
$.customizable_select(optgroup_3, () => {
|
||||
var anchor_10 = $.child(optgroup_3);
|
||||
var fragment_12 = optgroup_content_1();
|
||||
var node_11 = $.first_child(fragment_12);
|
||||
|
||||
option_snippet2(node_11);
|
||||
$.append(anchor_10, fragment_12);
|
||||
});
|
||||
|
||||
$.reset(select_17);
|
||||
|
||||
var select_18 = $.sibling(select_17, 2);
|
||||
var option_16 = $.child(select_18);
|
||||
|
||||
$.customizable_select(option_16, () => {
|
||||
var anchor_11 = $.child(option_16);
|
||||
var fragment_13 = option_content_5();
|
||||
var node_12 = $.first_child(fragment_13);
|
||||
|
||||
$.html(node_12, () => '<strong>Bold HTML</strong>');
|
||||
$.append(anchor_11, fragment_13);
|
||||
});
|
||||
|
||||
$.reset(select_18);
|
||||
|
||||
var select_19 = $.sibling(select_18, 2);
|
||||
|
||||
$.customizable_select(select_19, () => {
|
||||
var anchor_12 = $.child(select_19);
|
||||
var fragment_14 = select_content_4();
|
||||
var node_13 = $.first_child(fragment_14);
|
||||
|
||||
$.each(node_13, 1, () => items, $.index, ($$anchor, item) => {
|
||||
Option($$anchor, {});
|
||||
});
|
||||
|
||||
$.append(anchor_12, fragment_14);
|
||||
});
|
||||
|
||||
var select_20 = $.sibling(select_19, 2);
|
||||
|
||||
$.customizable_select(select_20, () => {
|
||||
var anchor_13 = $.child(select_20);
|
||||
var fragment_16 = select_content_5();
|
||||
var node_14 = $.first_child(fragment_16);
|
||||
|
||||
{
|
||||
var consequent_2 = ($$anchor) => {
|
||||
conditional_option($$anchor);
|
||||
};
|
||||
|
||||
$.if(node_14, ($$render) => {
|
||||
if (show) $$render(consequent_2);
|
||||
});
|
||||
}
|
||||
|
||||
$.append(anchor_13, fragment_16);
|
||||
});
|
||||
|
||||
$.append($$anchor, fragment);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import * as $ from 'svelte/internal/server';
|
||||
|
||||
export default function Option($$renderer) {
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Component Option`);
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,233 @@
|
||||
import * as $ from 'svelte/internal/server';
|
||||
import Option from './Option.svelte';
|
||||
|
||||
function opt($$renderer) {
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Snippet`);
|
||||
});
|
||||
}
|
||||
|
||||
function option_snippet($$renderer) {
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Rendered`);
|
||||
});
|
||||
}
|
||||
|
||||
function option_snippet2($$renderer) {
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Rendered in group`);
|
||||
});
|
||||
}
|
||||
|
||||
function conditional_option($$renderer) {
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Conditional`);
|
||||
});
|
||||
}
|
||||
|
||||
export default function Select_with_rich_content($$renderer) {
|
||||
let items = [1, 2, 3];
|
||||
let show = true;
|
||||
let html = '<option>From HTML</option>';
|
||||
|
||||
$$renderer.push(`<select>`);
|
||||
|
||||
$$renderer.option(
|
||||
{},
|
||||
($$renderer) => {
|
||||
$$renderer.push(`<span>Rich</span>`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
|
||||
$$renderer.push(`</select> <select><!--[-->`);
|
||||
|
||||
const each_array = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let item = each_array[$$index];
|
||||
|
||||
$$renderer.option({}, item);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select>`);
|
||||
|
||||
if (show) {
|
||||
$$renderer.push('<!--[-->');
|
||||
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Visible`);
|
||||
});
|
||||
} else {
|
||||
$$renderer.push('<!--[!-->');
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select><!---->`);
|
||||
|
||||
{
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Keyed`);
|
||||
});
|
||||
}
|
||||
|
||||
$$renderer.push(`<!----></select> <select>`);
|
||||
opt($$renderer);
|
||||
$$renderer.push(`<!----><!></select> <select><!--[-->`);
|
||||
|
||||
const each_array_1 = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index_1 = 0, $$length = each_array_1.length; $$index_1 < $$length; $$index_1++) {
|
||||
let item = each_array_1[$$index_1];
|
||||
const x = item * 2;
|
||||
|
||||
$$renderer.option({}, x);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select><optgroup label="Group">`);
|
||||
|
||||
$$renderer.option(
|
||||
{},
|
||||
($$renderer) => {
|
||||
$$renderer.push(`<strong>Bold</strong>`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
|
||||
$$renderer.push(`</optgroup></select> <select><optgroup label="Group"><!--[-->`);
|
||||
|
||||
const each_array_2 = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index_2 = 0, $$length = each_array_2.length; $$index_2 < $$length; $$index_2++) {
|
||||
let item = each_array_2[$$index_2];
|
||||
|
||||
$$renderer.option({}, item);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></optgroup></select> <select>`);
|
||||
|
||||
$$renderer.option(
|
||||
{ value: 'a' },
|
||||
($$renderer) => {
|
||||
$$renderer.push(`<em>Italic</em> text`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
|
||||
$$renderer.push(`</select> <select><!--[-->`);
|
||||
|
||||
const each_array_3 = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index_3 = 0, $$length = each_array_3.length; $$index_3 < $$length; $$index_3++) {
|
||||
let item = each_array_3[$$index_3];
|
||||
|
||||
$$renderer.option(
|
||||
{},
|
||||
($$renderer) => {
|
||||
$$renderer.push(`<span>${$.escape(item)}</span>`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select>`);
|
||||
|
||||
if (show) {
|
||||
$$renderer.push('<!--[-->');
|
||||
$$renderer.push(`<!--[-->`);
|
||||
|
||||
const each_array_4 = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index_4 = 0, $$length = each_array_4.length; $$index_4 < $$length; $$index_4++) {
|
||||
let item = each_array_4[$$index_4];
|
||||
|
||||
$$renderer.option({}, item);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]-->`);
|
||||
} else {
|
||||
$$renderer.push('<!--[!-->');
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select><!--[-->`);
|
||||
|
||||
{
|
||||
$$renderer.option({}, ($$renderer) => {
|
||||
$$renderer.push(`Boundary`);
|
||||
});
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select><!--[-->`);
|
||||
|
||||
{
|
||||
$$renderer.option(
|
||||
{},
|
||||
($$renderer) => {
|
||||
$$renderer.push(`<span>Rich in boundary</span>`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--></select> <select>`);
|
||||
Option($$renderer, {});
|
||||
$$renderer.push(`<!----><!></select> <select>`);
|
||||
option_snippet($$renderer);
|
||||
$$renderer.push(`<!----><!></select> <select>${$.html(html)}<!></select> <select><optgroup label="Group">`);
|
||||
Option($$renderer, {});
|
||||
$$renderer.push(`<!----><!></optgroup></select> <select><optgroup label="Group">`);
|
||||
option_snippet2($$renderer);
|
||||
$$renderer.push(`<!----><!></optgroup></select> <select>`);
|
||||
|
||||
$$renderer.option(
|
||||
{},
|
||||
($$renderer) => {
|
||||
$$renderer.push(`${$.html('<strong>Bold HTML</strong>')}`);
|
||||
},
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
void 0,
|
||||
true
|
||||
);
|
||||
|
||||
$$renderer.push(`</select> <select><!--[-->`);
|
||||
|
||||
const each_array_5 = $.ensure_array_like(items);
|
||||
|
||||
for (let $$index_5 = 0, $$length = each_array_5.length; $$index_5 < $$length; $$index_5++) {
|
||||
let item = each_array_5[$$index_5];
|
||||
|
||||
Option($$renderer, {});
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--><!></select> <select>`);
|
||||
|
||||
if (show) {
|
||||
$$renderer.push('<!--[-->');
|
||||
conditional_option($$renderer);
|
||||
} else {
|
||||
$$renderer.push('<!--[!-->');
|
||||
}
|
||||
|
||||
$$renderer.push(`<!--]--><!></select>`);
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
<script>
|
||||
let items = [1, 2, 3];
|
||||
let show = true;
|
||||
let html = '<option>From HTML</option>';
|
||||
|
||||
import Option from './Option.svelte';
|
||||
</script>
|
||||
|
||||
<!-- select with rich option (has span inside) - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option><span>Rich</span></option>
|
||||
</select>
|
||||
|
||||
<!-- select with each containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- select with if containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#if show}
|
||||
<option>Visible</option>
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<!-- select with key containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#key items}
|
||||
<option>Keyed</option>
|
||||
{/key}
|
||||
</select>
|
||||
|
||||
<!-- select with snippet defined at top level and rendered - should NOT use customizable_select_element -->
|
||||
{#snippet opt()}
|
||||
<option>Snippet</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{@render opt()}
|
||||
</select>
|
||||
|
||||
<!-- select with const inside each (should be ignored) - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
{@const x = item * 2}
|
||||
<option>{x}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- optgroup with rich option - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
<option><strong>Bold</strong></option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- optgroup with each containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- option with rich content (span) - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option value="a"><em>Italic</em> text</option>
|
||||
</select>
|
||||
|
||||
<!-- nested: select > each > option with rich content - SHOULD use customizable_select_element on option -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<option><span>{item}</span></option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- nested: select > if > each > plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
{#if show}
|
||||
{#each items as item}
|
||||
<option>{item}</option>
|
||||
{/each}
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<!-- select with svelte:boundary containing plain options - should NOT use customizable_select_element -->
|
||||
<select>
|
||||
<svelte:boundary>
|
||||
<option>Boundary</option>
|
||||
</svelte:boundary>
|
||||
</select>
|
||||
|
||||
<!-- select with svelte:boundary containing rich options - SHOULD use customizable_select_element on option -->
|
||||
<select>
|
||||
<svelte:boundary>
|
||||
<option><span>Rich in boundary</span></option>
|
||||
</svelte:boundary>
|
||||
</select>
|
||||
|
||||
<!-- select with Component - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
<Option />
|
||||
</select>
|
||||
|
||||
<!-- select with @render snippet - SHOULD be treated as rich content -->
|
||||
{#snippet option_snippet()}
|
||||
<option>Rendered</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{@render option_snippet()}
|
||||
</select>
|
||||
|
||||
<!-- select with @html - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
{@html html}
|
||||
</select>
|
||||
|
||||
<!-- optgroup with Component - SHOULD be treated as rich content -->
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
<Option />
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- optgroup with @render - SHOULD be treated as rich content -->
|
||||
{#snippet option_snippet2()}
|
||||
<option>Rendered in group</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
<optgroup label="Group">
|
||||
{@render option_snippet2()}
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<!-- option with @html inside - SHOULD use customizable_select_element -->
|
||||
<select>
|
||||
<option>{@html '<strong>Bold HTML</strong>'}</option>
|
||||
</select>
|
||||
|
||||
<!-- each block inside select with Component - SHOULD be treated as rich -->
|
||||
<select>
|
||||
{#each items as item}
|
||||
<Option />
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<!-- if block inside select with @render - SHOULD be treated as rich -->
|
||||
{#snippet conditional_option()}
|
||||
<option>Conditional</option>
|
||||
{/snippet}
|
||||
<select>
|
||||
{#if show}
|
||||
{@render conditional_option()}
|
||||
{/if}
|
||||
</select>
|
||||
Loading…
Reference in new issue