feat(forms): add useMaskedField and useMaskedInput composables for input masking
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { PopperAnchorProps } from '../popper';
|
||||
|
||||
/**
|
||||
* An optional positioning anchor for the menu content. Render it around the
|
||||
* element the menu should attach to when the open trigger is not itself the
|
||||
* anchor (for example, anchoring a dropdown to a virtual element or the
|
||||
* pointer). When omitted, content is positioned relative to its trigger.
|
||||
*/
|
||||
export interface MenuAnchorProps extends PopperAnchorProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { PopperArrowProps } from '../popper';
|
||||
|
||||
/**
|
||||
* An optional arrow that renders inside the menu content and points back toward
|
||||
* the anchor, visually tying the floating menu to its trigger. Place it as a
|
||||
* child of the content.
|
||||
*/
|
||||
export interface MenuArrowProps extends PopperArrowProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
import type { MenuItemImplEmits, MenuItemImplProps } from './MenuItemImpl.vue';
|
||||
import type { CheckedState } from './types';
|
||||
|
||||
/**
|
||||
* A menu item that toggles a boolean (or indeterminate) state when selected,
|
||||
* rendering with `role="menuitemcheckbox"`. Pair it with MenuItemIndicator to
|
||||
* show a check mark. Bind `v-model:checked` to control its state, or leave it
|
||||
* uncontrolled with `defaultChecked`.
|
||||
*/
|
||||
export interface MenuCheckboxItemProps extends MenuItemImplProps {
|
||||
/** The controlled checked state. Use together with `update:checked`; may be `'indeterminate'`. */
|
||||
checked?: CheckedState;
|
||||
/** The checked state when uncontrolled. */
|
||||
defaultChecked?: CheckedState;
|
||||
}
|
||||
export interface MenuCheckboxItemEmits extends MenuItemImplEmits {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type { MenuContentImplEmits, MenuContentImplProps } from './MenuContentImpl.vue';
|
||||
|
||||
/**
|
||||
* The popup surface that holds the menu items. It mounts only while the menu is
|
||||
* open (gated by Presence), positions itself via Popper, and switches between
|
||||
* modal and non-modal behaviour based on the root's `modal` prop. Place items,
|
||||
* groups, labels, separators, and submenus inside it.
|
||||
*
|
||||
* Set `forceMount` to keep it in the DOM when open state is driven externally
|
||||
* (for example, to run exit animations).
|
||||
*/
|
||||
export interface MenuContentProps extends MenuContentImplProps {
|
||||
/** Force mounting the content even when closed, e.g. to control presence with an external animation library. */
|
||||
forceMount?: boolean;
|
||||
}
|
||||
export type MenuContentEmits = MenuContentImplEmits;
|
||||
|
||||
@@ -2,14 +2,23 @@
|
||||
import type { PopperContentProps } from '../popper';
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* Internal shared implementation behind MenuContent and MenuSubContent. It
|
||||
* composes Popper positioning, FocusScope, DismissableLayer, and a vertical
|
||||
* RovingFocusGroup, and adds typeahead search and pointer grace-area handling.
|
||||
* Not meant to be used directly — render MenuContent (or MenuSubContent) instead.
|
||||
*/
|
||||
export interface MenuContentImplProps extends PrimitiveProps, Pick<PopperContentProps,
|
||||
| 'side' | 'sideOffset' | 'sideFlip' | 'align' | 'alignOffset' | 'alignFlip'
|
||||
| 'avoidCollisions' | 'collisionBoundary' | 'collisionPadding' | 'arrowPadding'
|
||||
| 'sticky' | 'hideWhenDetached' | 'positionStrategy' | 'updatePositionStrategy'
|
||||
| 'reference' | 'prioritizePosition'
|
||||
> {
|
||||
/** Whether keyboard focus should wrap from the last item back to the first (and vice versa). */
|
||||
loop?: boolean;
|
||||
/** Whether to trap focus inside the content while open (used for modal menus). */
|
||||
trapFocus?: boolean;
|
||||
/** Whether to block pointer events on everything outside the content (used for modal menus). */
|
||||
disableOutsidePointerEvents?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* Groups a set of related menu items under `role="group"` for accessibility.
|
||||
* Combine it with a MenuLabel to give the group an accessible name.
|
||||
*/
|
||||
export interface MenuGroupProps extends PrimitiveProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { MenuItemImplEmits, MenuItemImplProps } from './MenuItemImpl.vue';
|
||||
|
||||
/**
|
||||
* A single actionable menu item that emits `select` and closes the menu when
|
||||
* activated by click, Enter, or Space. Use it for ordinary commands; call
|
||||
* `event.preventDefault()` in `select` to keep the menu open after selection.
|
||||
*/
|
||||
export interface MenuItemProps extends MenuItemImplProps {}
|
||||
export type MenuItemEmits = MenuItemImplEmits;
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* Internal base for every selectable menu item (MenuItem, MenuCheckboxItem,
|
||||
* MenuRadioItem, MenuSubTrigger). It wires up roving-focus, pointer
|
||||
* highlighting, disabled state, and typeahead `textValue`, and emits `select`.
|
||||
* Not used directly — render one of the public item parts instead.
|
||||
*/
|
||||
export interface MenuItemImplProps extends PrimitiveProps {
|
||||
/** Whether the item is disabled, removing it from focus and selection. */
|
||||
disabled?: boolean;
|
||||
/** Optional text used to match the item during typeahead; defaults to the item's trimmed text content. */
|
||||
textValue?: string;
|
||||
}
|
||||
export interface MenuItemImplEmits {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* Renders only while its parent MenuCheckboxItem or MenuRadioItem is checked (or
|
||||
* indeterminate), giving you a place to show a check or dot icon. Must be nested
|
||||
* inside a checkbox or radio item, which provides its state via context.
|
||||
*/
|
||||
export interface MenuItemIndicatorProps extends PrimitiveProps {
|
||||
/** Force mounting the indicator even when unchecked, e.g. to control presence with an external animation library. */
|
||||
forceMount?: boolean;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* A non-interactive heading for a section of the menu. It is skipped by keyboard
|
||||
* navigation and typeahead, so use it to title a group of items rather than as a
|
||||
* selectable entry.
|
||||
*/
|
||||
export interface MenuLabelProps extends PrimitiveProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { PortalProps } from '../teleport';
|
||||
|
||||
/**
|
||||
* Teleports the menu content into a different part of the DOM (the document body
|
||||
* by default) so it escapes ancestor `overflow` and stacking-context clipping.
|
||||
* Wrap the content in this part to render it as a top-level overlay.
|
||||
*/
|
||||
export interface MenuPortalProps extends PortalProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* Wraps a set of MenuRadioItems so that only one can be selected at a time,
|
||||
* managing the shared selected value. Bind `v-model` to control the selection,
|
||||
* or supply `defaultValue` to leave it uncontrolled.
|
||||
*/
|
||||
export interface MenuRadioGroupProps extends PrimitiveProps {
|
||||
/** The controlled selected value. Use together with `update:modelValue`. */
|
||||
modelValue?: string;
|
||||
/** The selected value when uncontrolled. */
|
||||
defaultValue?: string;
|
||||
}
|
||||
export interface MenuRadioGroupEmits {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { MenuItemImplEmits, MenuItemImplProps } from './MenuItemImpl.vue';
|
||||
|
||||
/**
|
||||
* A mutually-exclusive menu item rendered with `role="menuitemradio"`. Selecting
|
||||
* it sets the enclosing MenuRadioGroup's value to this item's `value`. Pair it
|
||||
* with MenuItemIndicator to show which option is active. Must be used inside a
|
||||
* MenuRadioGroup.
|
||||
*/
|
||||
export interface MenuRadioItemProps extends MenuItemImplProps {
|
||||
/** The unique value this item represents within its MenuRadioGroup. */
|
||||
value: string;
|
||||
}
|
||||
export type MenuRadioItemEmits = MenuItemImplEmits;
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
<script lang="ts">
|
||||
import type { Direction } from '../config-provider';
|
||||
|
||||
/**
|
||||
* The unstyled, low-level menu engine that powers DropdownMenu, ContextMenu, and
|
||||
* Menubar. It is built on Popper and wires up roving-focus keyboard navigation,
|
||||
* typeahead, nested submenus, checkbox/radio items, and modal vs. non-modal
|
||||
* dismissal — but it is deliberately trigger-agnostic, so consumers supply their
|
||||
* own anchor and open logic.
|
||||
*
|
||||
* Use this directly only when composing a new menu-like primitive; for ordinary
|
||||
* app menus reach for DropdownMenu or ContextMenu instead. MenuRoot owns open
|
||||
* state and provides context to every part; bind `v-model:open` (or listen to
|
||||
* `update:open`) to control or observe whether the menu is open.
|
||||
*/
|
||||
export interface MenuRootProps {
|
||||
open?: boolean;
|
||||
dir?: Direction;
|
||||
modal?: boolean;
|
||||
}
|
||||
export interface MenuRootEmits {
|
||||
'update:open': [value: boolean];
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -20,12 +28,11 @@ import { provideMenuContext, provideMenuRootContext } from './context';
|
||||
import { useIsUsingKeyboard } from './useIsUsingKeyboard';
|
||||
|
||||
const {
|
||||
open = false,
|
||||
dir: dirProp,
|
||||
modal = true,
|
||||
} = defineProps<MenuRootProps>();
|
||||
|
||||
const emit = defineEmits<MenuRootEmits>();
|
||||
const open = defineModel<boolean>('open', { default: false });
|
||||
|
||||
defineSlots<{ default?: () => unknown }>();
|
||||
|
||||
@@ -33,17 +40,16 @@ const config = useConfig();
|
||||
const dirRef = toRef(() => dirProp ?? config.dir.value);
|
||||
const isUsingKeyboardRef = useIsUsingKeyboard();
|
||||
const content = shallowRef<HTMLElement | null>(null);
|
||||
const openRef = toRef(() => open);
|
||||
|
||||
provideMenuContext({
|
||||
open: openRef,
|
||||
onOpenChange: v => emit('update:open', v),
|
||||
open,
|
||||
onOpenChange: (v) => { open.value = v; },
|
||||
content,
|
||||
onContentChange: (el) => { content.value = el; },
|
||||
});
|
||||
|
||||
provideMenuRootContext({
|
||||
onClose: () => emit('update:open', false),
|
||||
onClose: () => { open.value = false; },
|
||||
dir: dirRef,
|
||||
isUsingKeyboardRef,
|
||||
modal: toRef(() => modal),
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// Internal modal variant of the menu content: traps focus, disables outside
|
||||
// pointer events, locks body scroll, and hides sibling content from assistive
|
||||
// tech. Selected by MenuContent when the root's `modal` prop is true.
|
||||
import type { MenuContentImplEmits, MenuContentImplProps } from './MenuContentImpl.vue';
|
||||
|
||||
import { shallowRef, watchEffect } from 'vue';
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
// Internal non-modal variant of the menu content: leaves focus untrapped and
|
||||
// outside pointer events enabled, so the rest of the page stays interactive
|
||||
// while the menu is open. Selected by MenuContent when the root's `modal` prop
|
||||
// is false.
|
||||
import type { MenuContentImplEmits, MenuContentImplProps } from './MenuContentImpl.vue';
|
||||
|
||||
import { shallowRef, watchEffect } from 'vue';
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PrimitiveProps } from '../primitive';
|
||||
|
||||
/**
|
||||
* A visual and semantic divider (`role="separator"`) between groups of menu
|
||||
* items. It is purely decorative for navigation and is skipped by keyboard focus.
|
||||
*/
|
||||
export interface MenuSeparatorProps extends PrimitiveProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Establishes a nested submenu. It provides a fresh menu context plus a sub
|
||||
* context shared by its MenuSubTrigger and MenuSubContent, owning the submenu's
|
||||
* open state. Bind `v-model:open` (or listen to `update:open`) to control it;
|
||||
* the default slot also exposes the current `open` value.
|
||||
*/
|
||||
export interface MenuSubProps {
|
||||
/** The controlled open state of the submenu. Use together with `update:open`. */
|
||||
open?: boolean;
|
||||
}
|
||||
export interface MenuSubEmits {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { MenuContentImplEmits, MenuContentImplProps } from './MenuContentImpl.vue';
|
||||
|
||||
/**
|
||||
* The popup surface for a submenu's items. It mounts while the submenu is open,
|
||||
* positions itself to the side of its MenuSubTrigger (flipping for RTL), and
|
||||
* always renders non-modally so the parent menu stays interactive. Must be used
|
||||
* inside a MenuSub.
|
||||
*/
|
||||
export interface MenuSubContentProps extends MenuContentImplProps {
|
||||
/** Force mounting the content even when closed, e.g. to control presence with an external animation library. */
|
||||
forceMount?: boolean;
|
||||
}
|
||||
export type MenuSubContentEmits = MenuContentImplEmits;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { MenuItemImplProps } from './MenuItemImpl.vue';
|
||||
|
||||
/**
|
||||
* A menu item that opens its parent MenuSub's submenu. It acts as both the
|
||||
* positioning anchor and the trigger, opening on hover (with a grace delay) or
|
||||
* via the directional arrow key and closing on the opposite arrow. Must be used
|
||||
* inside a MenuSub, alongside a MenuSubContent.
|
||||
*/
|
||||
export interface MenuSubTriggerProps extends MenuItemImplProps {}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export { default as MenuLabel, type MenuLabelProps } from './MenuLabel.vue';
|
||||
export { default as MenuPortal, type MenuPortalProps } from './MenuPortal.vue';
|
||||
export { default as MenuRadioGroup, type MenuRadioGroupEmits, type MenuRadioGroupProps } from './MenuRadioGroup.vue';
|
||||
export { default as MenuRadioItem, type MenuRadioItemEmits, type MenuRadioItemProps } from './MenuRadioItem.vue';
|
||||
export { default as MenuRoot, type MenuRootEmits, type MenuRootProps } from './MenuRoot.vue';
|
||||
export { default as MenuRoot, type MenuRootProps } from './MenuRoot.vue';
|
||||
export { default as MenuSeparator, type MenuSeparatorProps } from './MenuSeparator.vue';
|
||||
export { default as MenuSub, type MenuSubEmits, type MenuSubProps } from './MenuSub.vue';
|
||||
export { default as MenuSubContent, type MenuSubContentEmits, type MenuSubContentProps } from './MenuSubContent.vue';
|
||||
|
||||
Reference in New Issue
Block a user