mirror of https://github.com/sveltejs/svelte
parent
dba9b5fc0e
commit
7a22762908
@ -1,16 +1,23 @@
|
||||
import { check_rich_option_support } from '../operations.js';
|
||||
import { hydrating, set_hydrating } from '../hydration.js';
|
||||
import { check_rich_option_support, create_text } from '../operations.js';
|
||||
|
||||
/**
|
||||
* Handles rich HTML content inside `<option>` elements with browser-specific branching.
|
||||
* Modern browsers preserve HTML inside options, while older browsers strip it to text only.
|
||||
*
|
||||
* @param {HTMLOptionElement} option The `<option>` element to process
|
||||
* @param {() => void} rich_fn Function to process rich HTML content (modern browsers)
|
||||
* @param {() => void} text_fn Function to process text-only content (legacy browsers)
|
||||
*/
|
||||
export function rich_option(rich_fn, text_fn) {
|
||||
if (check_rich_option_support()) {
|
||||
export function rich_option(option, rich_fn) {
|
||||
var was_hydrating = hydrating;
|
||||
if (!check_rich_option_support()) {
|
||||
set_hydrating(false);
|
||||
option.innerText = '';
|
||||
option.append(create_text(''));
|
||||
}
|
||||
try {
|
||||
rich_fn();
|
||||
} else {
|
||||
text_fn();
|
||||
} finally {
|
||||
set_hydrating(was_hydrating);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
Loading…
Reference in new issue