@byyuurin/ui 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/ContextMenu.vue +65 -0
- package/dist/runtime/components/ContextMenu.vue.d.ts +138 -0
- package/dist/runtime/components/ContextMenuContent.vue +215 -0
- package/dist/runtime/components/ContextMenuContent.vue.d.ts +40 -0
- package/dist/runtime/components/DropdownMenu.vue.d.ts +2 -2
- package/dist/runtime/components/DropdownMenuContent.vue +3 -5
- package/dist/runtime/components/DropdownMenuContent.vue.d.ts +2 -7
- package/dist/runtime/components/NavigationMenu.vue +1 -1
- package/dist/runtime/components/NavigationMenu.vue.d.ts +4 -4
- package/dist/runtime/components/Stepper.vue +13 -11
- package/dist/runtime/components/Stepper.vue.d.ts +6 -1
- package/dist/runtime/components/Timeline.vue +17 -15
- package/dist/runtime/components/Timeline.vue.d.ts +5 -2
- package/dist/runtime/types/index.d.ts +1 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/vue/components/Link.vue +1 -1
- package/dist/runtime/vue/components/Link.vue.d.ts +1 -1
- package/dist/shared/{ui.DcEKQd0n.mjs → ui.Cakz_vv4.mjs} +120 -2
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +18 -15
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineNuxtModule, createResolver, addPlugin, addComponentsDir, addImportsDir, hasNuxtModule, installModule } from '@nuxt/kit';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
|
-
import { v as version, n as name, a as addTemplates } from './shared/ui.
|
|
3
|
+
import { v as version, n as name, a as addTemplates } from './shared/ui.Cakz_vv4.mjs';
|
|
4
4
|
import { d as defaultOptions, r as resolveColors, g as getDefaultUIConfig } from './shared/ui.DYMXCXO6.mjs';
|
|
5
5
|
import 'node:process';
|
|
6
6
|
import 'node:url';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import theme from "#build/ui/context-menu";
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { reactivePick } from "@vueuse/core";
|
|
7
|
+
import { ContextMenuRoot, ContextMenuTrigger, useForwardPropsEmits } from "reka-ui";
|
|
8
|
+
import { computed, toRef } from "vue";
|
|
9
|
+
import { useAppConfig } from "#imports";
|
|
10
|
+
import { omit, pick } from "../utils";
|
|
11
|
+
import { cv, merge } from "../utils/style";
|
|
12
|
+
import ContextMenuContent from "./ContextMenuContent.vue";
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
size: { type: null, required: false },
|
|
15
|
+
items: { type: null, required: false },
|
|
16
|
+
checkedIcon: { type: [String, Object], required: false },
|
|
17
|
+
loadingIcon: { type: [String, Object], required: false },
|
|
18
|
+
externalIcon: { type: [Boolean, String, Object], required: false, default: true },
|
|
19
|
+
content: { type: Object, required: false },
|
|
20
|
+
portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
|
|
21
|
+
labelKey: { type: null, required: false, default: "label" },
|
|
22
|
+
descriptionKey: { type: null, required: false, default: "description" },
|
|
23
|
+
disabled: { type: Boolean, required: false },
|
|
24
|
+
ui: { type: null, required: false },
|
|
25
|
+
class: { type: [Object, String, Number, Boolean, null, Array], required: false, skipCheck: true },
|
|
26
|
+
pressOpenDelay: { type: Number, required: false },
|
|
27
|
+
modal: { type: Boolean, required: false, default: true }
|
|
28
|
+
});
|
|
29
|
+
const emit = defineEmits(["update:open"]);
|
|
30
|
+
const slots = defineSlots();
|
|
31
|
+
const appConfig = useAppConfig();
|
|
32
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, "modal"), emit);
|
|
33
|
+
const contentProps = toRef(() => props.content);
|
|
34
|
+
const getProxySlots = () => omit(slots, ["default"]);
|
|
35
|
+
const ui = computed(() => {
|
|
36
|
+
const styler = cv(merge(theme, appConfig.ui.contextMenu));
|
|
37
|
+
return styler(pick(props, ["size"]));
|
|
38
|
+
});
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<ContextMenuRoot v-bind="rootProps">
|
|
43
|
+
<ContextMenuTrigger v-if="!!slots.default" as-child :disabled="props.disabled" :class="props.class">
|
|
44
|
+
<slot></slot>
|
|
45
|
+
</ContextMenuTrigger>
|
|
46
|
+
|
|
47
|
+
<ContextMenuContent
|
|
48
|
+
v-bind="contentProps"
|
|
49
|
+
:items="props.items"
|
|
50
|
+
:portal="props.portal"
|
|
51
|
+
:label-key="props.labelKey"
|
|
52
|
+
:description-key="props.descriptionKey"
|
|
53
|
+
:checked-icon="props.checkedIcon"
|
|
54
|
+
:loading-icon="props.loadingIcon"
|
|
55
|
+
:external-icon="props.externalIcon"
|
|
56
|
+
:ui="ui"
|
|
57
|
+
:ui-override="props.ui"
|
|
58
|
+
:class="ui.content({ class: [props.ui?.content, !slots.default && props.class] })"
|
|
59
|
+
>
|
|
60
|
+
<template v-for="(_, name) in getProxySlots()" #[name]="slotProps">
|
|
61
|
+
<slot :name="name" v-bind="slotProps"></slot>
|
|
62
|
+
</template>
|
|
63
|
+
</ContextMenuContent>
|
|
64
|
+
</ContextMenuRoot>
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { VariantProps } from '@byyuurin/ui-kit';
|
|
2
|
+
import type { ContextMenuContentEmits, ContextMenuContentProps, ContextMenuRootEmits, ContextMenuRootProps } from 'reka-ui';
|
|
3
|
+
import theme from '#build/ui/context-menu';
|
|
4
|
+
import type { AvatarProps, ComponentBaseProps, ComponentStyler, ComponentUIProps, IconProps, KbdProps, LinkProps } from '../types';
|
|
5
|
+
import type { ArrayOrNested, DynamicSlots, EmitsToProps, GetItemKeys, MergeTypes, NestedItem, StaticSlot } from '../types/utils';
|
|
6
|
+
type ThemeVariants = VariantProps<typeof theme>;
|
|
7
|
+
export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'>, ComponentBaseProps {
|
|
8
|
+
label?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
icon?: IconProps['name'];
|
|
11
|
+
color?: ThemeVariants['color'];
|
|
12
|
+
avatar?: AvatarProps;
|
|
13
|
+
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & ComponentBaseProps & Partial<EmitsToProps<ContextMenuContentEmits>>;
|
|
14
|
+
kbds?: KbdProps['value'][] | KbdProps[];
|
|
15
|
+
/**
|
|
16
|
+
* The item type.
|
|
17
|
+
* @default "link"
|
|
18
|
+
*/
|
|
19
|
+
type?: 'label' | 'separator' | 'link' | 'checkbox';
|
|
20
|
+
slot?: string;
|
|
21
|
+
loading?: boolean;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
checked?: boolean;
|
|
24
|
+
open?: boolean;
|
|
25
|
+
defaultOpen?: boolean;
|
|
26
|
+
children?: ArrayOrNested<ContextMenuItem>;
|
|
27
|
+
onSelect?: (e: Event) => void;
|
|
28
|
+
onUpdateChecked?: (checked: boolean) => void;
|
|
29
|
+
ui?: Pick<ComponentUIProps<typeof theme>, 'content' | 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemWrapper' | 'itemLabel' | 'itemDescription' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>;
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
}
|
|
32
|
+
export interface ContextMenuProps<T extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>> extends ComponentBaseProps, Omit<ContextMenuRootProps, 'dir'> {
|
|
33
|
+
/** @default "md" */
|
|
34
|
+
size?: ThemeVariants['size'];
|
|
35
|
+
items?: T;
|
|
36
|
+
/**
|
|
37
|
+
* The icon displayed when an item is checked.
|
|
38
|
+
* @default app.icons.check
|
|
39
|
+
*/
|
|
40
|
+
checkedIcon?: IconProps['name'];
|
|
41
|
+
/**
|
|
42
|
+
* The icon displayed when an item is loading.
|
|
43
|
+
* @default app.icons.loading
|
|
44
|
+
*/
|
|
45
|
+
loadingIcon?: IconProps['name'];
|
|
46
|
+
/**
|
|
47
|
+
* The icon displayed when the item is an external link.
|
|
48
|
+
*
|
|
49
|
+
* Set to `false` to hide the external icon.
|
|
50
|
+
* @default app.icons.external
|
|
51
|
+
*/
|
|
52
|
+
externalIcon?: boolean | IconProps['name'];
|
|
53
|
+
/** The content of the menu. */
|
|
54
|
+
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>;
|
|
55
|
+
/**
|
|
56
|
+
* Render the menu in a portal.
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
portal?: boolean | string | HTMLElement;
|
|
60
|
+
/**
|
|
61
|
+
* The key used to get the label from the item.
|
|
62
|
+
* @default "label"
|
|
63
|
+
*/
|
|
64
|
+
labelKey?: GetItemKeys<T>;
|
|
65
|
+
/**
|
|
66
|
+
* The key used to get the description from the item.
|
|
67
|
+
* @default "description"
|
|
68
|
+
*/
|
|
69
|
+
descriptionKey?: GetItemKeys<T>;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
ui?: ComponentUIProps<typeof theme>;
|
|
72
|
+
}
|
|
73
|
+
export interface ContextMenuEmits extends ContextMenuRootEmits {
|
|
74
|
+
}
|
|
75
|
+
export type ContextMenuSlots<A extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>, T extends NestedItem<A> = NestedItem<A>> = {
|
|
76
|
+
'default': StaticSlot;
|
|
77
|
+
'item': StaticSlot<{
|
|
78
|
+
item: T;
|
|
79
|
+
active?: boolean;
|
|
80
|
+
index: number;
|
|
81
|
+
ui: ComponentStyler<typeof theme>;
|
|
82
|
+
}>;
|
|
83
|
+
'item-leading': StaticSlot<{
|
|
84
|
+
item: T;
|
|
85
|
+
active?: boolean;
|
|
86
|
+
index: number;
|
|
87
|
+
ui: ComponentStyler<typeof theme>;
|
|
88
|
+
}>;
|
|
89
|
+
'item-label': StaticSlot<{
|
|
90
|
+
item: T;
|
|
91
|
+
active?: boolean;
|
|
92
|
+
index: number;
|
|
93
|
+
}>;
|
|
94
|
+
'item-description': StaticSlot<{
|
|
95
|
+
item: T;
|
|
96
|
+
active?: boolean;
|
|
97
|
+
index: number;
|
|
98
|
+
}>;
|
|
99
|
+
'item-trailing': StaticSlot<{
|
|
100
|
+
item: T;
|
|
101
|
+
active?: boolean;
|
|
102
|
+
index: number;
|
|
103
|
+
ui: ComponentStyler<typeof theme>;
|
|
104
|
+
}>;
|
|
105
|
+
'content-top': StaticSlot<{
|
|
106
|
+
sub: boolean;
|
|
107
|
+
}>;
|
|
108
|
+
'content-bottom': StaticSlot<{
|
|
109
|
+
sub: boolean;
|
|
110
|
+
}>;
|
|
111
|
+
} & DynamicSlots<MergeTypes<T>, 'label' | 'description', {
|
|
112
|
+
active?: boolean;
|
|
113
|
+
index: number;
|
|
114
|
+
}> & DynamicSlots<MergeTypes<T>, 'leading' | 'trailing', {
|
|
115
|
+
active?: boolean;
|
|
116
|
+
index: number;
|
|
117
|
+
ui: ComponentStyler<typeof theme>;
|
|
118
|
+
}>;
|
|
119
|
+
declare const _default: typeof __VLS_export;
|
|
120
|
+
export default _default;
|
|
121
|
+
declare const __VLS_export: <T extends ArrayOrNested<ContextMenuItem>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
122
|
+
props: import("vue").PublicProps & __VLS_PrettifyLocal<ContextMenuProps<T> & {
|
|
123
|
+
"onUpdate:open"?: ((payload: boolean) => any) | undefined;
|
|
124
|
+
}> & (typeof globalThis extends {
|
|
125
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
126
|
+
} ? P : {});
|
|
127
|
+
expose: (exposed: {}) => void;
|
|
128
|
+
attrs: any;
|
|
129
|
+
slots: ContextMenuSlots<T, NestedItem<T>>;
|
|
130
|
+
emit: (evt: "update:open", payload: boolean) => void;
|
|
131
|
+
}>) => import("vue").VNode & {
|
|
132
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
133
|
+
};
|
|
134
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
135
|
+
[K in keyof T]: T[K];
|
|
136
|
+
} : {
|
|
137
|
+
[K in keyof T as K]: T[K];
|
|
138
|
+
}) & {};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { createReusableTemplate, reactiveOmit } from "@vueuse/core";
|
|
7
|
+
import { useForwardPropsEmits } from "reka-ui";
|
|
8
|
+
import { ContextMenu } from "reka-ui/namespaced";
|
|
9
|
+
import { computed, toRef } from "vue";
|
|
10
|
+
import { useAppConfig } from "#imports";
|
|
11
|
+
import { useLocale } from "../composables/useLocale";
|
|
12
|
+
import { usePortal } from "../composables/usePortal";
|
|
13
|
+
import { get, isArrayOfArray, omit } from "../utils";
|
|
14
|
+
import { pickLinkProps } from "../utils/link";
|
|
15
|
+
import Avatar from "./Avatar.vue";
|
|
16
|
+
import ContextMenuContent from "./ContextMenuContent.vue";
|
|
17
|
+
import Icon from "./Icon.vue";
|
|
18
|
+
import Kbd from "./Kbd.vue";
|
|
19
|
+
import Link from "./Link.vue";
|
|
20
|
+
import LinkBase from "./LinkBase.vue";
|
|
21
|
+
defineOptions({ inheritAttrs: false });
|
|
22
|
+
const props = defineProps({
|
|
23
|
+
items: { type: null, required: false },
|
|
24
|
+
portal: { type: [Boolean, String], required: false, skipCheck: true },
|
|
25
|
+
sub: { type: Boolean, required: false },
|
|
26
|
+
labelKey: { type: null, required: true },
|
|
27
|
+
descriptionKey: { type: null, required: true },
|
|
28
|
+
checkedIcon: { type: [String, Object], required: false },
|
|
29
|
+
loadingIcon: { type: [String, Object], required: false },
|
|
30
|
+
externalIcon: { type: [Boolean, String, Object], required: false },
|
|
31
|
+
ui: { type: null, required: true },
|
|
32
|
+
uiOverride: { type: null, required: false },
|
|
33
|
+
class: { type: [Object, String, Number, Boolean, null, Array], required: false, skipCheck: true },
|
|
34
|
+
loop: { type: Boolean, required: false },
|
|
35
|
+
sideFlip: { type: Boolean, required: false },
|
|
36
|
+
alignOffset: { type: Number, required: false },
|
|
37
|
+
alignFlip: { type: Boolean, required: false },
|
|
38
|
+
avoidCollisions: { type: Boolean, required: false },
|
|
39
|
+
collisionBoundary: { type: null, required: false },
|
|
40
|
+
collisionPadding: { type: [Number, Object], required: false },
|
|
41
|
+
sticky: { type: String, required: false },
|
|
42
|
+
hideWhenDetached: { type: Boolean, required: false },
|
|
43
|
+
positionStrategy: { type: String, required: false },
|
|
44
|
+
disableUpdateOnLayoutShift: { type: Boolean, required: false },
|
|
45
|
+
prioritizePosition: { type: Boolean, required: false },
|
|
46
|
+
reference: { type: null, required: false }
|
|
47
|
+
});
|
|
48
|
+
const emit = defineEmits(["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "closeAutoFocus"]);
|
|
49
|
+
const slots = defineSlots();
|
|
50
|
+
const { dir } = useLocale();
|
|
51
|
+
const appConfig = useAppConfig();
|
|
52
|
+
const portalProps = usePortal(toRef(() => props.portal));
|
|
53
|
+
const contentProps = useForwardPropsEmits(reactiveOmit(props, "sub", "items", "portal", "labelKey", "descriptionKey", "checkedIcon", "loadingIcon", "externalIcon", "class", "ui", "uiOverride"), emit);
|
|
54
|
+
const getProxySlots = () => omit(slots, ["default"]);
|
|
55
|
+
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate();
|
|
56
|
+
const childrenIcon = computed(() => dir.value === "rtl" ? appConfig.ui.icons.chevronLeft : appConfig.ui.icons.chevronRight);
|
|
57
|
+
const groups = computed(
|
|
58
|
+
() => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
|
|
59
|
+
);
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<template>
|
|
63
|
+
<DefineItemTemplate v-slot="{ item, active, index }">
|
|
64
|
+
<slot :name="item.slot || 'item'" :item="item" :index="index" :ui="ui">
|
|
65
|
+
<slot :name="`${item.slot || 'item'}-leading`" :item="item" :active="active" :index="index" :ui="ui">
|
|
66
|
+
<Icon
|
|
67
|
+
v-if="item.loading"
|
|
68
|
+
:name="props.loadingIcon || appConfig.ui.icons.loading"
|
|
69
|
+
:class="props.ui.itemLeadingIcon({ class: [props.uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item.color, loading: true })"
|
|
70
|
+
data-part="itemLeadingIcon"
|
|
71
|
+
/>
|
|
72
|
+
<Icon
|
|
73
|
+
v-else-if="item.icon"
|
|
74
|
+
:name="item.icon"
|
|
75
|
+
:class="props.ui.itemLeadingIcon({ class: [props.uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item.color, active })"
|
|
76
|
+
data-part="itemLeadingIcon"
|
|
77
|
+
/>
|
|
78
|
+
<Avatar
|
|
79
|
+
v-else-if="item.avatar"
|
|
80
|
+
v-bind="item.avatar"
|
|
81
|
+
:size="item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || props.ui.itemLeadingAvatarSize()"
|
|
82
|
+
:class="props.ui.itemLeadingAvatar({ class: [props.uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })"
|
|
83
|
+
data-part="itemLeadingAvatar"
|
|
84
|
+
/>
|
|
85
|
+
</slot>
|
|
86
|
+
|
|
87
|
+
<span
|
|
88
|
+
v-if="get(item, props.labelKey) || !!slots[`${item.slot || 'item'}-label`] || (get(item, props.descriptionKey) || !!slots[`${item.slot || 'item'}-description`])"
|
|
89
|
+
:class="props.ui.itemWrapper({ class: [props.uiOverride?.itemWrapper, item.ui?.itemWrapper] })"
|
|
90
|
+
data-part="itemWrapper"
|
|
91
|
+
>
|
|
92
|
+
<span
|
|
93
|
+
v-if="get(item, props.labelKey) || !!slots[`${item.slot || 'item'}-label`]"
|
|
94
|
+
:class="props.ui.itemLabel({ class: [props.uiOverride?.itemLabel, item.ui?.itemLabel], active })"
|
|
95
|
+
data-part="itemLabel"
|
|
96
|
+
>
|
|
97
|
+
<slot :name="`${item.slot || 'item'}-label`" :item="item" :active="active" :index="index">
|
|
98
|
+
{{ get(item, props.labelKey) }}
|
|
99
|
+
</slot>
|
|
100
|
+
|
|
101
|
+
<Icon
|
|
102
|
+
v-if="item.target === '_blank' && props.externalIcon !== false"
|
|
103
|
+
:name="typeof props.externalIcon === 'string' ? props.externalIcon : appConfig.ui.icons.external"
|
|
104
|
+
:class="props.ui.itemLabelExternalIcon({ class: [props.uiOverride?.itemLabelExternalIcon, item.ui?.itemLabelExternalIcon], color: item.color, active })"
|
|
105
|
+
data-part="itemLabelExternalIcon"
|
|
106
|
+
/>
|
|
107
|
+
</span>
|
|
108
|
+
|
|
109
|
+
<span v-if="get(item, props.descriptionKey) || !!slots[`${item.slot || 'item'}-description`]" :class="props.ui.itemDescription({ class: [props.uiOverride?.itemDescription, item.ui?.itemDescription] })" data-part="itemDescription">
|
|
110
|
+
<slot :name="`${item.slot || 'item'}-description`" :item="item" :active="active" :index="index">
|
|
111
|
+
{{ get(item, props.descriptionKey) }}
|
|
112
|
+
</slot>
|
|
113
|
+
</span>
|
|
114
|
+
</span>
|
|
115
|
+
|
|
116
|
+
<span :class="props.ui.itemTrailing({ class: [props.uiOverride?.itemTrailing, item.ui?.itemTrailing] })" data-part="itemTrailing">
|
|
117
|
+
<slot :name="`${item.slot || 'item'}-trailing`" :item="item" :active="active" :index="index" :ui="ui">
|
|
118
|
+
<Icon v-if="item.children?.length" :name="childrenIcon" :class="props.ui.itemTrailingIcon({ class: [props.uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item.color, active })" data-part="itemTrailingIcon" />
|
|
119
|
+
<span v-else-if="item.kbds?.length" :class="props.ui.itemTrailingKbds({ class: [props.uiOverride?.itemTrailingKbds, item.ui?.itemTrailingKbds] })" data-part="itemTrailingKbds">
|
|
120
|
+
<Kbd
|
|
121
|
+
v-for="(kbd, kbdIndex) in item.kbds"
|
|
122
|
+
:key="kbdIndex"
|
|
123
|
+
:size="item.ui?.itemTrailingKbdsSize || props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()"
|
|
124
|
+
v-bind="typeof kbd === 'string' ? { value: kbd } : kbd"
|
|
125
|
+
/>
|
|
126
|
+
</span>
|
|
127
|
+
</slot>
|
|
128
|
+
|
|
129
|
+
<ContextMenu.ItemIndicator as-child>
|
|
130
|
+
<Icon :name="props.checkedIcon || appConfig.ui.icons.check" :class="props.ui.itemTrailingIcon({ class: [props.uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item.color })" data-part="itemTrailingIcon" />
|
|
131
|
+
</ContextMenu.ItemIndicator>
|
|
132
|
+
</span>
|
|
133
|
+
</slot>
|
|
134
|
+
</DefineItemTemplate>
|
|
135
|
+
|
|
136
|
+
<ContextMenu.Portal v-bind="portalProps">
|
|
137
|
+
<component :is="props.sub ? ContextMenu.SubContent : ContextMenu.Content" :class="props.ui.content({ class: [props.uiOverride?.content, props.class] })" v-bind="contentProps">
|
|
138
|
+
<slot name="content-top" :sub="props.sub ?? false"></slot>
|
|
139
|
+
|
|
140
|
+
<div role="presentation" :class="props.ui.viewport({ class: props.uiOverride?.viewport })" data-part="viewport">
|
|
141
|
+
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="props.ui.group({ class: props.uiOverride?.group })" data-part="group">
|
|
142
|
+
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
143
|
+
<ContextMenu.Label v-if="item.type === 'label'" :class="props.ui.label({ class: [props.uiOverride?.label, item.ui?.label, item.class] })" data-part="label">
|
|
144
|
+
<ReuseItemTemplate :item="item" :index="index" />
|
|
145
|
+
</ContextMenu.Label>
|
|
146
|
+
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="props.ui.separator({ class: [props.uiOverride?.separator, item.ui?.separator, item.class] })" data-part="separator" />
|
|
147
|
+
<ContextMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
|
148
|
+
<ContextMenu.SubTrigger
|
|
149
|
+
as="button"
|
|
150
|
+
type="button"
|
|
151
|
+
:disabled="item.disabled"
|
|
152
|
+
:text-value="get(item, props.labelKey)"
|
|
153
|
+
:class="props.ui.item({ class: [props.uiOverride?.item, item.ui?.item, item.class], color: item.color })"
|
|
154
|
+
data-part="item"
|
|
155
|
+
>
|
|
156
|
+
<ReuseItemTemplate :item="item" :index="index" />
|
|
157
|
+
</ContextMenu.SubTrigger>
|
|
158
|
+
|
|
159
|
+
<ContextMenuContent
|
|
160
|
+
sub
|
|
161
|
+
:class="item.ui?.content"
|
|
162
|
+
:ui="props.ui"
|
|
163
|
+
:ui-override="props.uiOverride"
|
|
164
|
+
:portal="props.portal"
|
|
165
|
+
:items="item.children"
|
|
166
|
+
side="right"
|
|
167
|
+
align="start"
|
|
168
|
+
:align-offset="-4"
|
|
169
|
+
:side-offset="3"
|
|
170
|
+
:label-key="props.labelKey"
|
|
171
|
+
:description-key="props.descriptionKey"
|
|
172
|
+
:checked-icon="props.checkedIcon"
|
|
173
|
+
:loading-icon="props.loadingIcon"
|
|
174
|
+
:external-icon="props.externalIcon"
|
|
175
|
+
v-bind="item.content"
|
|
176
|
+
>
|
|
177
|
+
<template v-for="(_, name) in getProxySlots()" #[name]="slotProps">
|
|
178
|
+
<slot :name="name" v-bind="slotProps"></slot>
|
|
179
|
+
</template>
|
|
180
|
+
</ContextMenuContent>
|
|
181
|
+
</ContextMenu.Sub>
|
|
182
|
+
<ContextMenu.CheckboxItem
|
|
183
|
+
v-else-if="item.type === 'checkbox'"
|
|
184
|
+
:model-value="item.checked"
|
|
185
|
+
:disabled="item.disabled"
|
|
186
|
+
:text-value="get(item, props.labelKey)"
|
|
187
|
+
:class="props.ui.item({ class: [props.uiOverride?.item, item.ui?.item, item.class], color: item.color })"
|
|
188
|
+
data-part="item"
|
|
189
|
+
@update:model-value="item.onUpdateChecked"
|
|
190
|
+
@select="item.onSelect"
|
|
191
|
+
>
|
|
192
|
+
<ReuseItemTemplate :item="item" :index="index" />
|
|
193
|
+
</ContextMenu.CheckboxItem>
|
|
194
|
+
<Link v-else v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
|
195
|
+
<ContextMenu.Item
|
|
196
|
+
as-child
|
|
197
|
+
:disabled="item.disabled"
|
|
198
|
+
:text-value="get(item, props.labelKey)"
|
|
199
|
+
@select="item.onSelect"
|
|
200
|
+
>
|
|
201
|
+
<LinkBase v-bind="slotProps" :class="props.ui.item({ class: [props.uiOverride?.item, item.ui?.item, item.class], color: item.color, active })" data-part="item">
|
|
202
|
+
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
|
203
|
+
</LinkBase>
|
|
204
|
+
</ContextMenu.Item>
|
|
205
|
+
</Link>
|
|
206
|
+
</template>
|
|
207
|
+
</ContextMenu.Group>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<slot></slot>
|
|
211
|
+
|
|
212
|
+
<slot name="content-bottom" :sub="props.sub ?? false"></slot>
|
|
213
|
+
</component>
|
|
214
|
+
</ContextMenu.Portal>
|
|
215
|
+
</template>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ContextMenuContentProps as RekaContextMenuContentProps } from 'reka-ui';
|
|
2
|
+
import type theme from '#build/ui/context-menu';
|
|
3
|
+
import type { ComponentBaseProps, ComponentStyler, ComponentUIProps, ContextMenuItem, ContextMenuSlots, IconProps } from '../types';
|
|
4
|
+
import type { ArrayOrNested, GetItemKeys } from '../types/utils';
|
|
5
|
+
interface ContextMenuContentProps<T extends ArrayOrNested<ContextMenuItem>> extends ComponentBaseProps, Omit<RekaContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
|
|
6
|
+
items?: T;
|
|
7
|
+
portal?: boolean | string | HTMLElement;
|
|
8
|
+
sub?: boolean;
|
|
9
|
+
labelKey: GetItemKeys<T>;
|
|
10
|
+
descriptionKey: GetItemKeys<T>;
|
|
11
|
+
checkedIcon?: IconProps['name'];
|
|
12
|
+
loadingIcon?: IconProps['name'];
|
|
13
|
+
externalIcon?: boolean | IconProps['name'];
|
|
14
|
+
ui: ComponentStyler<typeof theme>;
|
|
15
|
+
uiOverride?: ComponentUIProps<typeof theme>;
|
|
16
|
+
}
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
19
|
+
declare const __VLS_export: <T extends ArrayOrNested<ContextMenuItem>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
20
|
+
props: import("vue").PublicProps & __VLS_PrettifyLocal<ContextMenuContentProps<T> & {
|
|
21
|
+
onEscapeKeyDown?: ((event: KeyboardEvent) => any) | undefined;
|
|
22
|
+
onPointerDownOutside?: ((event: import("reka-ui").PointerDownOutsideEvent) => any) | undefined;
|
|
23
|
+
onFocusOutside?: ((event: import("reka-ui").FocusOutsideEvent) => any) | undefined;
|
|
24
|
+
onInteractOutside?: ((event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => any) | undefined;
|
|
25
|
+
onCloseAutoFocus?: ((event: Event) => any) | undefined;
|
|
26
|
+
}> & (typeof globalThis extends {
|
|
27
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
28
|
+
} ? P : {});
|
|
29
|
+
expose: (exposed: {}) => void;
|
|
30
|
+
attrs: any;
|
|
31
|
+
slots: ContextMenuSlots<T>;
|
|
32
|
+
emit: ((evt: "escapeKeyDown", event: KeyboardEvent) => void) & ((evt: "pointerDownOutside", event: import("reka-ui").PointerDownOutsideEvent) => void) & ((evt: "focusOutside", event: import("reka-ui").FocusOutsideEvent) => void) & ((evt: "interactOutside", event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => void) & ((evt: "closeAutoFocus", event: Event) => void);
|
|
33
|
+
}>) => import("vue").VNode & {
|
|
34
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
35
|
+
};
|
|
36
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
37
|
+
[K in keyof T]: T[K];
|
|
38
|
+
} : {
|
|
39
|
+
[K in keyof T as K]: T[K];
|
|
40
|
+
}) & {};
|
|
@@ -9,7 +9,7 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
|
|
|
9
9
|
icon?: IconProps['name'];
|
|
10
10
|
color?: ThemeVariants['color'];
|
|
11
11
|
avatar?: AvatarProps;
|
|
12
|
-
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>;
|
|
12
|
+
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & ComponentBaseProps & Partial<EmitsToProps<DropdownMenuContentEmits>>;
|
|
13
13
|
kbds?: KbdProps['value'][] | KbdProps[];
|
|
14
14
|
/**
|
|
15
15
|
* The item type.
|
|
@@ -25,7 +25,7 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
|
|
|
25
25
|
children?: ArrayOrNested<DropdownMenuItem>;
|
|
26
26
|
onSelect?: (e: Event) => void;
|
|
27
27
|
onUpdateChecked?: (checked: boolean) => void;
|
|
28
|
-
ui?: Pick<ComponentUIProps<typeof theme>, 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemWrapper' | 'itemLabel' | 'itemDescription' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>;
|
|
28
|
+
ui?: Pick<ComponentUIProps<typeof theme>, 'content' | 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemWrapper' | 'itemLabel' | 'itemDescription' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>;
|
|
29
29
|
[key: string]: any;
|
|
30
30
|
}
|
|
31
31
|
type ThemeVariants = VariantProps<typeof theme>;
|
|
@@ -20,7 +20,6 @@ import Link from "./Link.vue";
|
|
|
20
20
|
import LinkBase from "./LinkBase.vue";
|
|
21
21
|
defineOptions({ inheritAttrs: false });
|
|
22
22
|
const props = defineProps({
|
|
23
|
-
size: { type: null, required: false },
|
|
24
23
|
items: { type: null, required: false },
|
|
25
24
|
portal: { type: [Boolean, String], required: false, skipCheck: true },
|
|
26
25
|
sub: { type: Boolean, required: false },
|
|
@@ -83,8 +82,8 @@ const groups = computed(
|
|
|
83
82
|
/>
|
|
84
83
|
<Avatar
|
|
85
84
|
v-else-if="item.avatar"
|
|
85
|
+
:size="item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || props.ui.itemLeadingAvatarSize()"
|
|
86
86
|
v-bind="item.avatar"
|
|
87
|
-
:size="item.avatar.size || props.size"
|
|
88
87
|
:class="props.ui.itemLeadingAvatar({ class: [props.uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })"
|
|
89
88
|
data-part="itemLeadingAvatar"
|
|
90
89
|
/>
|
|
@@ -140,7 +139,7 @@ const groups = computed(
|
|
|
140
139
|
</DefineItemTemplate>
|
|
141
140
|
|
|
142
141
|
<DropdownMenu.Portal v-bind="portalProps">
|
|
143
|
-
<component :is="props.sub ? DropdownMenu.SubContent : DropdownMenu.Content"
|
|
142
|
+
<component :is="props.sub ? DropdownMenu.SubContent : DropdownMenu.Content" :class="props.ui.content({ class: [props.uiOverride?.content, props.class] })" v-bind="contentProps">
|
|
144
143
|
<slot name="content-top" :sub="props.sub ?? false"></slot>
|
|
145
144
|
|
|
146
145
|
<div role="presentation" :class="props.ui.viewport({ class: props.uiOverride?.viewport })" data-part="viewport">
|
|
@@ -164,12 +163,11 @@ const groups = computed(
|
|
|
164
163
|
|
|
165
164
|
<DropdownMenuContent
|
|
166
165
|
sub
|
|
167
|
-
:class="
|
|
166
|
+
:class="item.ui?.content"
|
|
168
167
|
:ui="props.ui"
|
|
169
168
|
:ui-override="props.uiOverride"
|
|
170
169
|
:portal="props.portal"
|
|
171
170
|
:items="item.children"
|
|
172
|
-
side="right"
|
|
173
171
|
align="start"
|
|
174
172
|
:align-offset="-4"
|
|
175
173
|
:side-offset="3"
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DropdownMenuContentEmits as RekaDropdownMenuContentEmits, DropdownMenuContentProps as RekaDropdownMenuContentProps } from 'reka-ui';
|
|
1
|
+
import type { DropdownMenuContentProps as RekaDropdownMenuContentProps } from 'reka-ui';
|
|
3
2
|
import type theme from '#build/ui/dropdown-menu';
|
|
4
3
|
import type { ComponentBaseProps, ComponentStyler, ComponentUIProps, DropdownMenuItem, DropdownMenuSlots, IconProps } from '../types';
|
|
5
4
|
import type { ArrayOrNested, DynamicSlots, GetItemKeys, MergeTypes, NestedItem, StaticSlot } from '../types/utils';
|
|
6
|
-
type ThemeVariants = VariantProps<typeof theme>;
|
|
7
5
|
export interface DropdownMenuContentProps<T extends ArrayOrNested<DropdownMenuItem>> extends ComponentBaseProps, Omit<RekaDropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
|
|
8
|
-
size?: ThemeVariants['size'];
|
|
9
6
|
items?: T;
|
|
10
7
|
portal?: boolean | string | HTMLElement;
|
|
11
8
|
sub?: boolean;
|
|
@@ -17,9 +14,7 @@ export interface DropdownMenuContentProps<T extends ArrayOrNested<DropdownMenuIt
|
|
|
17
14
|
ui: ComponentStyler<typeof theme>;
|
|
18
15
|
uiOverride?: ComponentUIProps<typeof theme>;
|
|
19
16
|
}
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
export type DropdownMenuContentSlots<A extends ArrayOrNested<DropdownMenuItem> = ArrayOrNested<DropdownMenuItem>, T extends NestedItem<A> = NestedItem<A>> = Pick<DropdownMenuSlots<A>, 'item' | 'item-leading' | 'item-label' | 'item-description' | 'item-trailing' | 'content-top' | 'content-bottom'> & {
|
|
17
|
+
type DropdownMenuContentSlots<A extends ArrayOrNested<DropdownMenuItem> = ArrayOrNested<DropdownMenuItem>, T extends NestedItem<A> = NestedItem<A>> = Pick<DropdownMenuSlots<A>, 'item' | 'item-leading' | 'item-label' | 'item-description' | 'item-trailing' | 'content-top' | 'content-bottom'> & {
|
|
23
18
|
default: StaticSlot;
|
|
24
19
|
} & DynamicSlots<MergeTypes<T>, 'label' | 'description', {
|
|
25
20
|
active: boolean;
|
|
@@ -291,7 +291,7 @@ function getAccordionDefaultValue(list, level = 0) {
|
|
|
291
291
|
:item="childItem"
|
|
292
292
|
:index="childIndex"
|
|
293
293
|
:level="level + 1"
|
|
294
|
-
:class="ui.childItem({ class: [props.ui?.childItem,
|
|
294
|
+
:class="ui.childItem({ class: [props.ui?.childItem, childItem.ui?.childItem] })"
|
|
295
295
|
data-part="childItem"
|
|
296
296
|
/>
|
|
297
297
|
</AccordionRoot>
|
|
@@ -13,8 +13,8 @@ export interface NavigationMenuItem extends ComponentBaseProps, Omit<LinkProps,
|
|
|
13
13
|
icon?: IconProps['name'];
|
|
14
14
|
avatar?: AvatarProps;
|
|
15
15
|
/**
|
|
16
|
-
* Display a
|
|
17
|
-
* `{ size: '
|
|
16
|
+
* Display a badge on the item.
|
|
17
|
+
* `{ size: 'sm', color: 'neutral', variant: 'outline' }`
|
|
18
18
|
*/
|
|
19
19
|
badge?: string | number | BadgeProps;
|
|
20
20
|
/**
|
|
@@ -54,9 +54,9 @@ export interface NavigationMenuItem extends ComponentBaseProps, Omit<LinkProps,
|
|
|
54
54
|
}
|
|
55
55
|
type ThemeVariants = VariantProps<typeof theme>;
|
|
56
56
|
type SingleOrMultipleType = 'single' | 'multiple';
|
|
57
|
-
type Orientation =
|
|
57
|
+
type Orientation = NavigationMenuRootProps['orientation'];
|
|
58
58
|
type NavigationMenuModelValue<K extends SingleOrMultipleType = SingleOrMultipleType, O extends Orientation = Orientation> = O extends 'horizontal' ? string : K extends 'single' ? string : K extends 'multiple' ? string[] : MaybeArray<string>;
|
|
59
|
-
export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem> = ArrayOrNested<NavigationMenuItem>, K extends SingleOrMultipleType = SingleOrMultipleType, O extends Orientation = Orientation> extends ComponentBaseProps, Pick<NavigationMenuRootProps, 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'>, Pick<AccordionRootProps, 'disabled' | '
|
|
59
|
+
export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem> = ArrayOrNested<NavigationMenuItem>, K extends SingleOrMultipleType = SingleOrMultipleType, O extends Orientation = Orientation> extends ComponentBaseProps, Pick<NavigationMenuRootProps, 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'>, Pick<AccordionRootProps, 'disabled' | 'collapsible'> {
|
|
60
60
|
/**
|
|
61
61
|
* The element or component this component should render as.
|
|
62
62
|
* @default "div"
|
|
@@ -93,22 +93,24 @@ defineExpose({
|
|
|
93
93
|
</div>
|
|
94
94
|
|
|
95
95
|
<div :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })" data-part="wrapper">
|
|
96
|
-
<
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
<slot :name="item.slot ? `${item.slot}-wrapper` : 'wrapper'" :item="item">
|
|
97
|
+
<StepperTitle v-if="item.title || !!slots[item.slot ? `${item.slot}-title` : 'title']" as="div" :class="ui.title({ class: [props.ui?.title, item.ui?.title] })" data-part="title">
|
|
98
|
+
<slot :name="item.slot ? `${item.slot}-title` : 'title'" :item="item">
|
|
99
|
+
{{ item.title }}
|
|
100
|
+
</slot>
|
|
101
|
+
</StepperTitle>
|
|
101
102
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
<StepperDescription v-if="item.description || !!slots[item.slot ? `${item.slot}-description` : 'description']" as="div" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })" data-part="description">
|
|
104
|
+
<slot :name="item.slot ? `${item.slot}-description` : 'description'" :item="item">
|
|
105
|
+
{{ item.description }}
|
|
106
|
+
</slot>
|
|
107
|
+
</StepperDescription>
|
|
108
|
+
</slot>
|
|
107
109
|
</div>
|
|
108
110
|
</StepperItem>
|
|
109
111
|
</div>
|
|
110
112
|
|
|
111
|
-
<div v-if="currentStep?.content || !!slots.content || currentStep?.slot" :class="ui.content({ class: props.ui?.content })" data-part="content">
|
|
113
|
+
<div v-if="currentStep?.content || !!slots.content || currentStep?.slot && !!slots[currentStep.slot]" :class="ui.content({ class: props.ui?.content })" data-part="content">
|
|
112
114
|
<slot :name="currentStep?.slot || 'content'" :item="currentStep">
|
|
113
115
|
{{ currentStep?.content }}
|
|
114
116
|
</slot>
|
|
@@ -42,6 +42,9 @@ export type StepperSlots<T extends StepperItem = StepperItem> = {
|
|
|
42
42
|
item: T;
|
|
43
43
|
ui: ComponentStyler<typeof theme>;
|
|
44
44
|
}>;
|
|
45
|
+
wrapper: StaticSlot<{
|
|
46
|
+
item: T;
|
|
47
|
+
}>;
|
|
45
48
|
title: StaticSlot<{
|
|
46
49
|
item: T;
|
|
47
50
|
}>;
|
|
@@ -51,7 +54,9 @@ export type StepperSlots<T extends StepperItem = StepperItem> = {
|
|
|
51
54
|
content: StaticSlot<{
|
|
52
55
|
item: T;
|
|
53
56
|
}>;
|
|
54
|
-
} & DynamicSlots<T
|
|
57
|
+
} & DynamicSlots<T, 'wrapper' | 'title' | 'description', {
|
|
58
|
+
item: T;
|
|
59
|
+
}>;
|
|
55
60
|
declare const _default: typeof __VLS_export;
|
|
56
61
|
export default _default;
|
|
57
62
|
declare const __VLS_export: <T extends StepperItem>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
@@ -82,21 +82,23 @@ const ui = computed(() => {
|
|
|
82
82
|
</div>
|
|
83
83
|
|
|
84
84
|
<div :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })" data-part="wrapper">
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
85
|
+
<slot :name="item.slot ? `${item.slot}-wrapper` : 'wrapper'" :item="item">
|
|
86
|
+
<div v-if="item.date || !!slots[item.slot ? `${item.slot}-date` : 'date']" :class="ui.date({ class: [props.ui?.date, item.ui?.date] })" data-part="date">
|
|
87
|
+
<slot :name="item.slot ? `${item.slot}-date` : 'date'" :item="item">
|
|
88
|
+
{{ item.date }}
|
|
89
|
+
</slot>
|
|
90
|
+
</div>
|
|
91
|
+
<div v-if="item.title || !!slots[item.slot ? `${item.slot}-title` : 'title']" :class="ui.title({ class: [props.ui?.title, item.ui?.title] })" data-part="title">
|
|
92
|
+
<slot :name="item.slot ? `${item.slot}-title` : 'title'" :item="item">
|
|
93
|
+
{{ item.title }}
|
|
94
|
+
</slot>
|
|
95
|
+
</div>
|
|
96
|
+
<div v-if="item.description || !!slots[item.slot ? `${item.slot}-description` : 'description']" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })" data-part="description">
|
|
97
|
+
<slot :name="item.slot ? `${item.slot}-description` : 'description'" :item="item">
|
|
98
|
+
{{ item.description }}
|
|
99
|
+
</slot>
|
|
100
|
+
</div>
|
|
101
|
+
</slot>
|
|
100
102
|
</div>
|
|
101
103
|
</div>
|
|
102
104
|
</Primitive>
|
|
@@ -44,6 +44,9 @@ export type TimelineSlots<T extends TimelineItem = TimelineItem> = {
|
|
|
44
44
|
indicator: StaticSlot<{
|
|
45
45
|
item: T;
|
|
46
46
|
}>;
|
|
47
|
+
wrapper: StaticSlot<{
|
|
48
|
+
item: T;
|
|
49
|
+
}>;
|
|
47
50
|
date: StaticSlot<{
|
|
48
51
|
item: T;
|
|
49
52
|
}>;
|
|
@@ -53,9 +56,9 @@ export type TimelineSlots<T extends TimelineItem = TimelineItem> = {
|
|
|
53
56
|
description: StaticSlot<{
|
|
54
57
|
item: T;
|
|
55
58
|
}>;
|
|
56
|
-
} & DynamicSlots<T, 'indicator' | 'date' | 'title' | 'description', {
|
|
59
|
+
} & DynamicSlots<T, 'indicator' | 'wrapper' | 'date' | 'title' | 'description', {
|
|
57
60
|
item: T;
|
|
58
|
-
}
|
|
61
|
+
}>;
|
|
59
62
|
declare const _default: typeof __VLS_export;
|
|
60
63
|
export default _default;
|
|
61
64
|
declare const __VLS_export: <T extends TimelineItem>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
@@ -15,6 +15,7 @@ export * from '../components/Checkbox.vue';
|
|
|
15
15
|
export * from '../components/CheckboxGroup.vue';
|
|
16
16
|
export * from '../components/Chip.vue';
|
|
17
17
|
export * from '../components/Collapsible.vue';
|
|
18
|
+
export * from '../components/ContextMenu.vue';
|
|
18
19
|
export * from '../components/Drawer.vue';
|
|
19
20
|
export * from '../components/DropdownMenu.vue';
|
|
20
21
|
export * from '../components/FieldGroup.vue';
|
|
@@ -13,6 +13,7 @@ export * from "../components/Checkbox.vue";
|
|
|
13
13
|
export * from "../components/CheckboxGroup.vue";
|
|
14
14
|
export * from "../components/Chip.vue";
|
|
15
15
|
export * from "../components/Collapsible.vue";
|
|
16
|
+
export * from "../components/ContextMenu.vue";
|
|
16
17
|
export * from "../components/Drawer.vue";
|
|
17
18
|
export * from "../components/DropdownMenu.vue";
|
|
18
19
|
export * from "../components/FieldGroup.vue";
|
|
@@ -35,7 +35,7 @@ const props = defineProps({
|
|
|
35
35
|
exactActiveClass: { type: String, required: false },
|
|
36
36
|
ariaCurrentValue: { type: String, required: false, default: "page" },
|
|
37
37
|
viewTransition: { type: Boolean, required: false },
|
|
38
|
-
to: { type: null, required:
|
|
38
|
+
to: { type: null, required: false },
|
|
39
39
|
replace: { type: Boolean, required: false }
|
|
40
40
|
});
|
|
41
41
|
defineSlots();
|
|
@@ -8,7 +8,7 @@ export interface LinkSlots {
|
|
|
8
8
|
active: boolean;
|
|
9
9
|
}>;
|
|
10
10
|
}
|
|
11
|
-
export interface LinkProps extends ComponentBaseProps, Omit<RouterLinkProps, 'custom'
|
|
11
|
+
export interface LinkProps extends ComponentBaseProps, Partial<Omit<RouterLinkProps, 'custom'>>, /** @vue-ignore */ Omit<ButtonHTMLAttributes, 'type' | 'disabled'>, /** @vue-ignore */ Omit<AnchorHTMLAttributes, 'href' | 'target' | 'rel' | 'type'> {
|
|
12
12
|
/**
|
|
13
13
|
* The element or component this component should render as when not a link.
|
|
14
14
|
* @default "button"
|
|
@@ -9,7 +9,7 @@ import { ct } from '@byyuurin/ui-kit';
|
|
|
9
9
|
import { defu } from 'defu';
|
|
10
10
|
|
|
11
11
|
const name = "@byyuurin/ui";
|
|
12
|
-
const version = "0.
|
|
12
|
+
const version = "0.5.0";
|
|
13
13
|
|
|
14
14
|
const accordion = ct({
|
|
15
15
|
parts: {
|
|
@@ -820,7 +820,7 @@ const calendar = (options) => ct({
|
|
|
820
820
|
|
|
821
821
|
const card = ct({
|
|
822
822
|
parts: {
|
|
823
|
-
root: "rounded divide-y",
|
|
823
|
+
root: "rounded divide-y overflow-hidden",
|
|
824
824
|
header: "flex flex-wrap items-center gap-1 p-4 sm:px-6",
|
|
825
825
|
body: "flex-1 overflow-y-auto p-4 sm:p-6 empty:hidden",
|
|
826
826
|
footer: "flex items-center gap-1.5 p-4 sm:px-6",
|
|
@@ -1200,6 +1200,123 @@ const collapsible = ct({
|
|
|
1200
1200
|
}
|
|
1201
1201
|
});
|
|
1202
1202
|
|
|
1203
|
+
const contextMenu = (options) => ct({
|
|
1204
|
+
parts: {
|
|
1205
|
+
content: "min-w-32 bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-[--reka-context-menu-content-transform-origin] flex flex-col",
|
|
1206
|
+
viewport: "relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1",
|
|
1207
|
+
group: "p-1 isolate",
|
|
1208
|
+
label: "w-full flex items-center font-semibold text-highlighted",
|
|
1209
|
+
separator: "-mx-1 my-1 h-px bg-border",
|
|
1210
|
+
item: "group relative w-full flex items-start select-none outline-none before:content-empty before:absolute before:z-[-1] before:inset-px before:rounded-md data-[disabled]:cursor-not-allowed data-[disabled]:opacity-75",
|
|
1211
|
+
itemLeadingIcon: "shrink-0",
|
|
1212
|
+
itemLeadingAvatar: "shrink-0",
|
|
1213
|
+
itemLeadingAvatarSize: "",
|
|
1214
|
+
itemTrailing: "ms-auto inline-flex gap-1.5 items-center",
|
|
1215
|
+
itemTrailingIcon: "shrink-0",
|
|
1216
|
+
itemTrailingKbds: "hidden lg:inline-flex items-center shrink-0",
|
|
1217
|
+
itemTrailingKbdsSize: "",
|
|
1218
|
+
itemWrapper: "flex-1 flex flex-col text-start min-w-0",
|
|
1219
|
+
itemLabel: "truncate",
|
|
1220
|
+
itemDescription: "truncate text-muted",
|
|
1221
|
+
itemLabelExternalIcon: "inline-block size-3 align-top text-dimmed"
|
|
1222
|
+
},
|
|
1223
|
+
variants: {
|
|
1224
|
+
color: {
|
|
1225
|
+
...Object.fromEntries((options.theme.colors || []).map((color) => [color, ""])),
|
|
1226
|
+
neutral: ""
|
|
1227
|
+
},
|
|
1228
|
+
active: {
|
|
1229
|
+
true: {
|
|
1230
|
+
item: "text-highlighted before:bg-elevated",
|
|
1231
|
+
itemLeadingIcon: "text-default"
|
|
1232
|
+
},
|
|
1233
|
+
false: {
|
|
1234
|
+
item: [
|
|
1235
|
+
"text-default data-highlighted:text-highlighted data-[state=open]:text-highlighted data-[highlighted]:before:bg-elevated/50 data-[state=open]:before:bg-elevated/50",
|
|
1236
|
+
options.theme.transitions && "transition-colors before:transition-colors"
|
|
1237
|
+
],
|
|
1238
|
+
itemLeadingIcon: [
|
|
1239
|
+
"text-dimmed group-data-[highlighted]:text-default group-data-[state=open]:text-default",
|
|
1240
|
+
options.theme.transitions && "transition-colors"
|
|
1241
|
+
]
|
|
1242
|
+
}
|
|
1243
|
+
},
|
|
1244
|
+
loading: {
|
|
1245
|
+
true: {
|
|
1246
|
+
itemLeadingIcon: "animate-spin"
|
|
1247
|
+
}
|
|
1248
|
+
},
|
|
1249
|
+
size: {
|
|
1250
|
+
xs: {
|
|
1251
|
+
label: "p-1 text-xs gap-1",
|
|
1252
|
+
item: "p-1 text-xs gap-1",
|
|
1253
|
+
itemLeadingIcon: "size-4",
|
|
1254
|
+
itemLeadingAvatarSize: "3xs",
|
|
1255
|
+
itemTrailingIcon: "size-4",
|
|
1256
|
+
itemTrailingKbds: "gap-0.5",
|
|
1257
|
+
itemTrailingKbdsSize: "sm"
|
|
1258
|
+
},
|
|
1259
|
+
sm: {
|
|
1260
|
+
label: "p-1.5 text-xs gap-1.5",
|
|
1261
|
+
item: "p-1.5 text-xs gap-1.5",
|
|
1262
|
+
itemLeadingIcon: "size-4",
|
|
1263
|
+
itemLeadingAvatarSize: "3xs",
|
|
1264
|
+
itemTrailingIcon: "size-4",
|
|
1265
|
+
itemTrailingKbds: "gap-0.5",
|
|
1266
|
+
itemTrailingKbdsSize: "sm"
|
|
1267
|
+
},
|
|
1268
|
+
md: {
|
|
1269
|
+
label: "p-1.5 text-sm gap-1.5",
|
|
1270
|
+
item: "p-1.5 text-sm gap-1.5",
|
|
1271
|
+
itemLeadingIcon: "size-5",
|
|
1272
|
+
itemLeadingAvatarSize: "2xs",
|
|
1273
|
+
itemTrailingIcon: "size-5",
|
|
1274
|
+
itemTrailingKbds: "gap-0.5",
|
|
1275
|
+
itemTrailingKbdsSize: "md"
|
|
1276
|
+
},
|
|
1277
|
+
lg: {
|
|
1278
|
+
label: "p-2 text-sm gap-2",
|
|
1279
|
+
item: "p-2 text-sm gap-2",
|
|
1280
|
+
itemLeadingIcon: "size-5",
|
|
1281
|
+
itemLeadingAvatarSize: "2xs",
|
|
1282
|
+
itemTrailingIcon: "size-5",
|
|
1283
|
+
itemTrailingKbds: "gap-1",
|
|
1284
|
+
itemTrailingKbdsSize: "md"
|
|
1285
|
+
},
|
|
1286
|
+
xl: {
|
|
1287
|
+
label: "p-2 text-base gap-2",
|
|
1288
|
+
item: "p-2 text-base gap-2",
|
|
1289
|
+
itemLeadingIcon: "size-6",
|
|
1290
|
+
itemLeadingAvatarSize: "xs",
|
|
1291
|
+
itemTrailingIcon: "size-6",
|
|
1292
|
+
itemTrailingKbds: "gap-1",
|
|
1293
|
+
itemTrailingKbdsSize: "lg"
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
},
|
|
1297
|
+
compoundVariants: [
|
|
1298
|
+
...(options.theme.colors || []).map((color) => ({
|
|
1299
|
+
color,
|
|
1300
|
+
active: false,
|
|
1301
|
+
class: {
|
|
1302
|
+
item: `text-${color} data-[highlighted]:text-${color} data-[highlighted]:before:bg-${color}/10 data-[state=open]:before:bg-${color}/10`,
|
|
1303
|
+
itemLeadingIcon: `text-${color}/75 group-data-[highlighted]:text-${color} group-data-[state=open]:text-${color}`
|
|
1304
|
+
}
|
|
1305
|
+
})),
|
|
1306
|
+
...(options.theme.colors || []).map((color) => ({
|
|
1307
|
+
color,
|
|
1308
|
+
active: true,
|
|
1309
|
+
class: {
|
|
1310
|
+
item: `text-${color} before:bg-${color}/10`,
|
|
1311
|
+
itemLeadingIcon: `text-${color}`
|
|
1312
|
+
}
|
|
1313
|
+
}))
|
|
1314
|
+
],
|
|
1315
|
+
defaultVariants: {
|
|
1316
|
+
size: "md"
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1203
1320
|
const drawer = ct({
|
|
1204
1321
|
parts: {
|
|
1205
1322
|
overlay: "fixed inset-0 bg-elevated/75",
|
|
@@ -4511,6 +4628,7 @@ const theme = {
|
|
|
4511
4628
|
checkboxGroup: checkboxGroup,
|
|
4512
4629
|
chip: chip,
|
|
4513
4630
|
collapsible: collapsible,
|
|
4631
|
+
contextMenu: contextMenu,
|
|
4514
4632
|
drawer: drawer,
|
|
4515
4633
|
dropdownMenu: dropdownMenu,
|
|
4516
4634
|
fieldGroup: fieldGroup,
|
package/dist/unplugin.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
import { join, normalize } from 'pathe';
|
|
4
4
|
import { createUnplugin } from 'unplugin';
|
|
5
|
-
import { g as getTemplates, n as name } from './shared/ui.
|
|
5
|
+
import { g as getTemplates, n as name } from './shared/ui.Cakz_vv4.mjs';
|
|
6
6
|
import { d as defaultOptions, r as resolveColors, g as getDefaultUIConfig } from './shared/ui.DYMXCXO6.mjs';
|
|
7
7
|
import AutoImport from 'unplugin-auto-import';
|
|
8
8
|
import { globSync } from 'tinyglobby';
|
package/dist/vite.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byyuurin/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
|
+
"packageManager": "pnpm@10.28.0",
|
|
5
6
|
"description": "",
|
|
6
7
|
"author": "Yuurin <byyuurin@gmail.com>",
|
|
7
8
|
"license": "MIT",
|
|
@@ -97,6 +98,21 @@
|
|
|
97
98
|
"dist",
|
|
98
99
|
"vue-plugin.d.ts"
|
|
99
100
|
],
|
|
101
|
+
"scripts": {
|
|
102
|
+
"dev": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi dev playground/nuxt --uiDev",
|
|
103
|
+
"dev:build": "nuxi build playground/nuxt",
|
|
104
|
+
"dev:preview": "nuxi preview playground/nuxt",
|
|
105
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground/nuxt && pnpm dev:vue:build",
|
|
106
|
+
"dev:vue": "pnpm --filter \"./playground/vue\" dev -- --uiDev",
|
|
107
|
+
"dev:vue:build": "pnpm --filter \"./playground/vue\" build",
|
|
108
|
+
"dev:vue:preview": "pnpm --filter \"./playground/vue\" preview",
|
|
109
|
+
"release": "bumpp && pnpm publish",
|
|
110
|
+
"lint": "eslint .",
|
|
111
|
+
"test": "vitest",
|
|
112
|
+
"test:types": "vue-tsc --noEmit && nuxi typecheck playground/nuxt",
|
|
113
|
+
"prepare": "simple-git-hooks",
|
|
114
|
+
"prepack": "nuxt-module-build build"
|
|
115
|
+
},
|
|
100
116
|
"peerDependencies": {
|
|
101
117
|
"joi": "^18.0.0",
|
|
102
118
|
"superstruct": "^2.0.2",
|
|
@@ -201,18 +217,5 @@
|
|
|
201
217
|
},
|
|
202
218
|
"lint-staged": {
|
|
203
219
|
"*": "eslint --fix"
|
|
204
|
-
},
|
|
205
|
-
"scripts": {
|
|
206
|
-
"dev": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi dev playground/nuxt --uiDev",
|
|
207
|
-
"dev:build": "nuxi build playground/nuxt",
|
|
208
|
-
"dev:preview": "nuxi preview playground/nuxt",
|
|
209
|
-
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground/nuxt && pnpm dev:vue:build",
|
|
210
|
-
"dev:vue": "pnpm --filter \"./playground/vue\" dev -- --uiDev",
|
|
211
|
-
"dev:vue:build": "pnpm --filter \"./playground/vue\" build",
|
|
212
|
-
"dev:vue:preview": "pnpm --filter \"./playground/vue\" preview",
|
|
213
|
-
"release": "bumpp && pnpm publish",
|
|
214
|
-
"lint": "eslint .",
|
|
215
|
-
"test": "vitest",
|
|
216
|
-
"test:types": "vue-tsc --noEmit && nuxi typecheck playground/nuxt"
|
|
217
220
|
}
|
|
218
|
-
}
|
|
221
|
+
}
|