fix(primitives): component fixes and test cleanup
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 4.7 KiB |
@@ -43,7 +43,7 @@ function load(nextSrc: string | undefined) {
|
||||
setStatus('error');
|
||||
return;
|
||||
}
|
||||
if (typeof globalThis.window === 'undefined') {
|
||||
if (globalThis.window === undefined) {
|
||||
setStatus('loading');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ export interface ComboboxRootProps<T extends AcceptableValue = AcceptableValue>
|
||||
modelValue?: T | T[];
|
||||
/** Uncontrolled initial value. */
|
||||
defaultValue?: T | T[];
|
||||
/** Controlled open state. Use `v-model:open`. */
|
||||
open?: boolean;
|
||||
/** Uncontrolled default open state. */
|
||||
defaultOpen?: boolean;
|
||||
/** Allow selecting multiple values. */
|
||||
@@ -77,6 +75,7 @@ const config = useConfig();
|
||||
const direction = computed(() => dir ?? config.dir.value);
|
||||
|
||||
const localOpen = ref<boolean>(defaultOpen);
|
||||
/** Controlled open state. Use `v-model:open`. */
|
||||
const open = defineModel<boolean>('open', {
|
||||
default: undefined,
|
||||
get: v => v ?? localOpen.value,
|
||||
|
||||
@@ -138,7 +138,7 @@ const filteredItems = computed<Map<string, number>>(() => {
|
||||
|
||||
function escapeAttr(v: string): string {
|
||||
if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(v);
|
||||
return v.replace(/["\\]/g, '\\$&');
|
||||
return v.replaceAll(/["\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
function getSelectableItems(): string[] {
|
||||
|
||||
Vendored
+2
-6
@@ -5,13 +5,9 @@ declare global {
|
||||
}
|
||||
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomProps {
|
||||
[key: `data${string}`]: unknown;
|
||||
}
|
||||
type ComponentCustomProps = Record<`data${string}`, unknown>;
|
||||
}
|
||||
|
||||
declare module 'vue' {
|
||||
interface HTMLAttributes {
|
||||
[key: `data-${string}`]: unknown;
|
||||
}
|
||||
type HTMLAttributes = Record<`data-${string}`, unknown>;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ const { openDelay = 700, closeDelay = 300, defaultOpen = false } = defineProps<H
|
||||
const openModel = defineModel<boolean | undefined>('open', { default: undefined });
|
||||
const uncontrolled = ref(defaultOpen);
|
||||
|
||||
// `open` intentionally shares the model name: it's a local read-only computed that
|
||||
// resolves the controlled model against the uncontrolled fallback. Safe in script-setup.
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const open = computed(() => openModel.value ?? uncontrolled.value);
|
||||
|
||||
function setOpen(value: boolean) {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
// This component takes no props of its own (it renders a fixed wrapper + RovingFocusGroup
|
||||
// and forwards $attrs). The empty interface is the intentional public prop contract.
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface NavigationMenuListProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { Direction } from '../config-provider';
|
||||
import type { Orientation } from '../roving-focus';
|
||||
|
||||
export interface NavigationMenuRootProps {
|
||||
/** Controlled active item value. Use `v-model`. */
|
||||
modelValue?: string;
|
||||
/** Uncontrolled initial value. */
|
||||
defaultValue?: string;
|
||||
/** Reading direction. Falls back to `ConfigProvider`. */
|
||||
@@ -72,6 +70,7 @@ const config = useConfig();
|
||||
const dirRef = computed<Direction>(() => dir ?? config.dir.value);
|
||||
|
||||
const localValue = ref<string>(defaultValue ?? '');
|
||||
/** Controlled active item value. Use `v-model`. */
|
||||
const modelValue = defineModel<string | undefined>({
|
||||
default: undefined,
|
||||
get: v => v ?? localValue.value,
|
||||
@@ -212,7 +211,7 @@ provideNavigationMenuContext({
|
||||
<Primitive
|
||||
:ref="forwardRef"
|
||||
as="nav"
|
||||
:aria-label="$attrs['aria-label'] as string | undefined ?? 'Main'"
|
||||
:aria-label="($attrs['aria-label'] ?? 'Main') as string"
|
||||
:data-orientation="orientation"
|
||||
:dir="dirRef"
|
||||
data-primitives-navigation-menu
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
import type { Orientation } from '../roving-focus';
|
||||
|
||||
export interface NavigationMenuSubProps {
|
||||
/** Controlled active value of the submenu. Use `v-model`. */
|
||||
modelValue?: string;
|
||||
/** Uncontrolled initial value. */
|
||||
defaultValue?: string;
|
||||
/** Submenu orientation. @default 'horizontal' */
|
||||
@@ -36,6 +34,7 @@ defineSlots<{
|
||||
}>();
|
||||
|
||||
const localValue = ref<string>(defaultValue ?? '');
|
||||
/** Controlled active value of the submenu. Use `v-model`. */
|
||||
const modelValue = defineModel<string | undefined>({
|
||||
default: undefined,
|
||||
get: v => v ?? localValue.value,
|
||||
|
||||
@@ -102,7 +102,7 @@ function onPaste(e: ClipboardEvent): void {
|
||||
return;
|
||||
e.preventDefault();
|
||||
const chars = ctx.type.value === 'number'
|
||||
? data.replace(NON_DIGIT_G, '').split('')
|
||||
? data.replaceAll(NON_DIGIT_G, '').split('')
|
||||
: data.split('');
|
||||
let idx = props.index;
|
||||
for (const ch of chars) {
|
||||
|
||||
@@ -17,7 +17,7 @@ const { forwardRef } = useForwardExpose();
|
||||
|
||||
function onClick(): void {
|
||||
if (item.disabled.value) return;
|
||||
const idx = ctx.modelValue.value.findIndex(v => v === item.value.value);
|
||||
const idx = ctx.modelValue.value.indexOf(item.value.value);
|
||||
if (idx !== -1) ctx.onRemoveValue(idx);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -120,8 +120,8 @@ describe('TagsInput', () => {
|
||||
|
||||
it('delete trigger removes its tag', async () => {
|
||||
const w = createTagsInput({ defaultValue: ['a', 'b'] });
|
||||
const deleteBtns = w.findAll('button').filter(b => b.text() === '×');
|
||||
await deleteBtns[0]!.trigger('click');
|
||||
const deleteBtn = w.findAll('button').find(b => b.text() === '×');
|
||||
await deleteBtn!.trigger('click');
|
||||
await nextTick();
|
||||
const items = w.findAllComponents(TagsInputItem as Component);
|
||||
expect(items).toHaveLength(1);
|
||||
|
||||
Reference in New Issue
Block a user