@sewadah/selaras 0.5.0 → 0.6.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/agent/catalog.json +1 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/DashboardSidebar.d.vue.ts +16 -1
- package/dist/runtime/components/DashboardSidebar.vue +44 -6
- package/dist/runtime/components/DashboardSidebar.vue.d.ts +16 -1
- package/dist/runtime/components/DatePicker.vue +1 -1
- package/dist/runtime/components/NavigationMenu.d.vue.ts +16 -11
- package/dist/runtime/components/NavigationMenu.vue +40 -21
- package/dist/runtime/components/NavigationMenu.vue.d.ts +16 -11
- package/dist/runtime/components/NavigationMenuFlyoutTrigger.d.vue.ts +2 -1
- package/dist/runtime/components/NavigationMenuFlyoutTrigger.vue +11 -1
- package/dist/runtime/components/NavigationMenuFlyoutTrigger.vue.d.ts +2 -1
- package/dist/runtime/internal/NavigationMenuTooltip.d.vue.ts +19 -0
- package/dist/runtime/internal/NavigationMenuTooltip.vue +13 -0
- package/dist/runtime/internal/NavigationMenuTooltip.vue.d.ts +19 -0
- package/dist/runtime/theme/date-picker.d.ts +3 -0
- package/dist/runtime/theme/date-picker.js +1 -0
- package/dist/runtime/utils/navigation-menu.d.ts +7 -0
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -2,6 +2,8 @@ import type { DashboardSidebarThemeSlots } from '../theme/dashboard-sidebar.js';
|
|
|
2
2
|
import type { UiProp } from '../utils/ui.js';
|
|
3
3
|
type __VLS_Slots = DashboardSidebarSlots;
|
|
4
4
|
export interface DashboardSidebarProps {
|
|
5
|
+
/** Controlled desktop collapse state. Omit to keep resizing and persistence uncontrolled. */
|
|
6
|
+
collapsed?: boolean;
|
|
5
7
|
/** @default 260 */
|
|
6
8
|
defaultSize?: number;
|
|
7
9
|
/** @default 200 */
|
|
@@ -16,6 +18,9 @@ export interface DashboardSidebarProps {
|
|
|
16
18
|
sizeUnit?: 'px' | '%';
|
|
17
19
|
ui?: UiProp<DashboardSidebarThemeSlots>;
|
|
18
20
|
}
|
|
21
|
+
export interface DashboardSidebarEmits {
|
|
22
|
+
'update:collapsed': [value: boolean];
|
|
23
|
+
}
|
|
19
24
|
export interface DashboardSidebarSlots {
|
|
20
25
|
/** `isCollapsed` lets a header (a logo mark, say) swap to a narrower version once the sidebar collapses to its icon rail - always `false` on mobile, where there's no in-between state, just the drawer open or closed. */
|
|
21
26
|
header?: (props: {
|
|
@@ -29,7 +34,17 @@ export interface DashboardSidebarSlots {
|
|
|
29
34
|
isCollapsed: boolean;
|
|
30
35
|
}) => any;
|
|
31
36
|
}
|
|
32
|
-
declare
|
|
37
|
+
declare function toggle(): void;
|
|
38
|
+
declare const __VLS_base: import("vue").DefineComponent<DashboardSidebarProps, {
|
|
39
|
+
collapse: () => void;
|
|
40
|
+
expand: () => void;
|
|
41
|
+
toggle: typeof toggle;
|
|
42
|
+
isCollapsed: import("vue").ComputedRef<boolean>;
|
|
43
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
44
|
+
"update:collapsed": (value: boolean) => any;
|
|
45
|
+
}, string, import("vue").PublicProps, Readonly<DashboardSidebarProps> & Readonly<{
|
|
46
|
+
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
47
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
48
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
34
49
|
declare const _default: typeof __VLS_export;
|
|
35
50
|
export default _default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed, inject, onMounted, onUnmounted, ref, watch } from "vue";
|
|
2
|
+
import { computed, inject, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
3
3
|
import { dashboardSidebarTheme } from "../theme/dashboard-sidebar";
|
|
4
4
|
import { DASHBOARD_INJECTION_KEY } from "../utils/injection-keys";
|
|
5
5
|
import { resolveSlot, useComponentTheme, useRootProps } from "../utils/ui";
|
|
@@ -8,6 +8,7 @@ import ScrollArea from "./ScrollArea.vue";
|
|
|
8
8
|
import SplitterPanel from "./SplitterPanel.vue";
|
|
9
9
|
defineOptions({ inheritAttrs: false });
|
|
10
10
|
const props = defineProps({
|
|
11
|
+
collapsed: { type: Boolean, required: false, default: void 0 },
|
|
11
12
|
defaultSize: { type: Number, required: false, default: 260 },
|
|
12
13
|
minSize: { type: Number, required: false, default: 200 },
|
|
13
14
|
maxSize: { type: Number, required: false, default: 400 },
|
|
@@ -16,22 +17,48 @@ const props = defineProps({
|
|
|
16
17
|
sizeUnit: { type: String, required: false, default: "px" },
|
|
17
18
|
ui: { type: Object, required: false }
|
|
18
19
|
});
|
|
20
|
+
const emit = defineEmits(["update:collapsed"]);
|
|
19
21
|
defineSlots();
|
|
20
22
|
const dashboard = inject(DASHBOARD_INJECTION_KEY, null);
|
|
21
23
|
const isMobile = computed(() => dashboard?.isMobile.value ?? false);
|
|
22
24
|
const panelRef = ref();
|
|
23
25
|
const mobileOpen = ref(false);
|
|
26
|
+
let panelReady = false;
|
|
27
|
+
function setCollapsed(value) {
|
|
28
|
+
if (isMobile.value || !props.collapsible || !panelReady)
|
|
29
|
+
return;
|
|
30
|
+
if (value)
|
|
31
|
+
panelRef.value?.collapse();
|
|
32
|
+
else
|
|
33
|
+
panelRef.value?.expand();
|
|
34
|
+
}
|
|
35
|
+
watch(() => props.collapsed, (value) => {
|
|
36
|
+
if (value !== void 0)
|
|
37
|
+
setCollapsed(value);
|
|
38
|
+
});
|
|
39
|
+
defineExpose({
|
|
40
|
+
collapse: () => setCollapsed(true),
|
|
41
|
+
expand: () => setCollapsed(false),
|
|
42
|
+
toggle,
|
|
43
|
+
isCollapsed: computed(() => panelRef.value?.isCollapsed ?? false)
|
|
44
|
+
});
|
|
24
45
|
function toggle() {
|
|
25
46
|
if (isMobile.value) {
|
|
26
47
|
mobileOpen.value = !mobileOpen.value;
|
|
27
48
|
return;
|
|
28
49
|
}
|
|
29
|
-
|
|
30
|
-
panelRef.value.expand();
|
|
31
|
-
else
|
|
32
|
-
panelRef.value?.collapse();
|
|
50
|
+
setCollapsed(!panelRef.value?.isCollapsed);
|
|
33
51
|
}
|
|
34
52
|
function handleResize(size) {
|
|
53
|
+
if (!panelReady) {
|
|
54
|
+
nextTick(() => {
|
|
55
|
+
if (!panelRef.value || panelReady)
|
|
56
|
+
return;
|
|
57
|
+
panelReady = true;
|
|
58
|
+
if (props.collapsed !== void 0)
|
|
59
|
+
setCollapsed(props.collapsed);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
35
62
|
if (dashboard)
|
|
36
63
|
dashboard.lastDesktopWidthPx.value = size;
|
|
37
64
|
}
|
|
@@ -40,11 +67,22 @@ onMounted(() => {
|
|
|
40
67
|
if (isMobile.value || targetWidthPx === void 0)
|
|
41
68
|
return;
|
|
42
69
|
setTimeout(() => {
|
|
43
|
-
|
|
70
|
+
if (props.collapsed === void 0)
|
|
71
|
+
panelRef.value?.resize(targetWidthPx);
|
|
44
72
|
}, 50);
|
|
45
73
|
});
|
|
46
74
|
if (dashboard)
|
|
47
75
|
dashboard.toggleSidebar.value = toggle;
|
|
76
|
+
watch(() => panelRef.value?.isCollapsed, (value) => {
|
|
77
|
+
if (!panelReady || isMobile.value || value === void 0)
|
|
78
|
+
return;
|
|
79
|
+
if (value !== props.collapsed)
|
|
80
|
+
emit("update:collapsed", value);
|
|
81
|
+
nextTick(() => {
|
|
82
|
+
if (props.collapsed !== void 0 && panelRef.value?.isCollapsed !== props.collapsed)
|
|
83
|
+
setCollapsed(props.collapsed);
|
|
84
|
+
});
|
|
85
|
+
}, { flush: "post" });
|
|
48
86
|
const isSidebarCollapsed = computed(() => isMobile.value ? !mobileOpen.value : panelRef.value?.isCollapsed ?? false);
|
|
49
87
|
if (dashboard) {
|
|
50
88
|
watch(isSidebarCollapsed, (value) => {
|
|
@@ -2,6 +2,8 @@ import type { DashboardSidebarThemeSlots } from '../theme/dashboard-sidebar.js';
|
|
|
2
2
|
import type { UiProp } from '../utils/ui.js';
|
|
3
3
|
type __VLS_Slots = DashboardSidebarSlots;
|
|
4
4
|
export interface DashboardSidebarProps {
|
|
5
|
+
/** Controlled desktop collapse state. Omit to keep resizing and persistence uncontrolled. */
|
|
6
|
+
collapsed?: boolean;
|
|
5
7
|
/** @default 260 */
|
|
6
8
|
defaultSize?: number;
|
|
7
9
|
/** @default 200 */
|
|
@@ -16,6 +18,9 @@ export interface DashboardSidebarProps {
|
|
|
16
18
|
sizeUnit?: 'px' | '%';
|
|
17
19
|
ui?: UiProp<DashboardSidebarThemeSlots>;
|
|
18
20
|
}
|
|
21
|
+
export interface DashboardSidebarEmits {
|
|
22
|
+
'update:collapsed': [value: boolean];
|
|
23
|
+
}
|
|
19
24
|
export interface DashboardSidebarSlots {
|
|
20
25
|
/** `isCollapsed` lets a header (a logo mark, say) swap to a narrower version once the sidebar collapses to its icon rail - always `false` on mobile, where there's no in-between state, just the drawer open or closed. */
|
|
21
26
|
header?: (props: {
|
|
@@ -29,7 +34,17 @@ export interface DashboardSidebarSlots {
|
|
|
29
34
|
isCollapsed: boolean;
|
|
30
35
|
}) => any;
|
|
31
36
|
}
|
|
32
|
-
declare
|
|
37
|
+
declare function toggle(): void;
|
|
38
|
+
declare const __VLS_base: import("vue").DefineComponent<DashboardSidebarProps, {
|
|
39
|
+
collapse: () => void;
|
|
40
|
+
expand: () => void;
|
|
41
|
+
toggle: typeof toggle;
|
|
42
|
+
isCollapsed: import("vue").ComputedRef<boolean>;
|
|
43
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
44
|
+
"update:collapsed": (value: boolean) => any;
|
|
45
|
+
}, string, import("vue").PublicProps, Readonly<DashboardSidebarProps> & Readonly<{
|
|
46
|
+
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
47
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
48
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
34
49
|
declare const _default: typeof __VLS_export;
|
|
35
50
|
export default _default;
|
|
@@ -446,7 +446,7 @@ const timeBodyProps = computed(() => ({
|
|
|
446
446
|
close: () => {
|
|
447
447
|
onUpdateOpen(false);
|
|
448
448
|
},
|
|
449
|
-
timeSectionProps:
|
|
449
|
+
timeSectionProps: resolveSlot(ui.value.timeSectionStandalone, props.ui?.timeSectionStandalone)
|
|
450
450
|
}));
|
|
451
451
|
const buttonTriggerUi = computed(() => ({
|
|
452
452
|
base: [
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { NavigationMenuThemeSlots } from '../theme/navigation-menu.js';
|
|
2
2
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
3
|
-
import type { NavigationMenuItem } from '../utils/navigation-menu.js';
|
|
3
|
+
import type { NavigationMenuItem, NavigationMenuPopover } from '../utils/navigation-menu.js';
|
|
4
4
|
import type { UiProp } from '../utils/ui.js';
|
|
5
|
+
import type { TooltipProps } from './Tooltip.vue.js';
|
|
5
6
|
export interface NavigationMenuProps {
|
|
6
7
|
items: NavigationMenuItem[];
|
|
7
8
|
/** Horizontal uses Reka's real shared-viewport flyout for a single level of dropdown children. Vertical falls back to a recursive accordion (see NavigationMenuAccordionItem.vue) for arbitrary depth - Reka's own NavigationMenuContent isn't built for deep nested trees. */
|
|
@@ -12,6 +13,10 @@ export interface NavigationMenuProps {
|
|
|
12
13
|
highlight?: boolean;
|
|
13
14
|
/** Icon-only rail mode (vertical only) - labels stay in the DOM for assistive tech (`sr-only`, not removed) but visually collapse to just each item's own leading icon. A parent with children renders as a themed Popover trigger instead of an expandable accordion row - no room for a nested list in an icon rail, so its children surface in a flyout next to the icon instead (the common "collapsed sidebar" pattern - VSCode's activity bar, Linear, Notion). */
|
|
14
15
|
collapsed?: boolean;
|
|
16
|
+
/** Labels for collapsed vertical leaf items. An object customizes Tooltip props. @default false */
|
|
17
|
+
tooltip?: boolean | TooltipProps;
|
|
18
|
+
/** Presentation of collapsed child flyouts; item settings override these defaults. */
|
|
19
|
+
popover?: NavigationMenuPopover;
|
|
15
20
|
ui?: UiProp<NavigationMenuThemeSlots>;
|
|
16
21
|
}
|
|
17
22
|
declare var __VLS_8: {}, __VLS_17: string, __VLS_18: {
|
|
@@ -45,19 +50,19 @@ declare var __VLS_8: {}, __VLS_17: string, __VLS_18: {
|
|
|
45
50
|
}, __VLS_124: string, __VLS_125: {
|
|
46
51
|
item: NavigationMenuItem;
|
|
47
52
|
active: boolean;
|
|
48
|
-
},
|
|
53
|
+
}, __VLS_153: string, __VLS_154: {
|
|
49
54
|
item: NavigationMenuItem;
|
|
50
55
|
active: boolean;
|
|
51
|
-
},
|
|
56
|
+
}, __VLS_157: string, __VLS_158: {
|
|
52
57
|
item: NavigationMenuItem;
|
|
53
58
|
active: boolean;
|
|
54
|
-
},
|
|
59
|
+
}, __VLS_166: string, __VLS_167: {
|
|
55
60
|
item: NavigationMenuItem;
|
|
56
61
|
active: boolean;
|
|
57
|
-
},
|
|
62
|
+
}, __VLS_170: string, __VLS_171: {
|
|
58
63
|
item: NavigationMenuItem;
|
|
59
64
|
active: boolean;
|
|
60
|
-
},
|
|
65
|
+
}, __VLS_178: {};
|
|
61
66
|
type __VLS_Slots = {} & {
|
|
62
67
|
[K in NonNullable<typeof __VLS_17>]?: (props: typeof __VLS_18) => any;
|
|
63
68
|
} & {
|
|
@@ -83,17 +88,17 @@ type __VLS_Slots = {} & {
|
|
|
83
88
|
} & {
|
|
84
89
|
[K in NonNullable<typeof __VLS_124>]?: (props: typeof __VLS_125) => any;
|
|
85
90
|
} & {
|
|
86
|
-
[K in NonNullable<typeof
|
|
91
|
+
[K in NonNullable<typeof __VLS_153>]?: (props: typeof __VLS_154) => any;
|
|
87
92
|
} & {
|
|
88
|
-
[K in NonNullable<typeof
|
|
93
|
+
[K in NonNullable<typeof __VLS_157>]?: (props: typeof __VLS_158) => any;
|
|
89
94
|
} & {
|
|
90
|
-
[K in NonNullable<typeof
|
|
95
|
+
[K in NonNullable<typeof __VLS_166>]?: (props: typeof __VLS_167) => any;
|
|
91
96
|
} & {
|
|
92
|
-
[K in NonNullable<typeof
|
|
97
|
+
[K in NonNullable<typeof __VLS_170>]?: (props: typeof __VLS_171) => any;
|
|
93
98
|
} & {
|
|
94
99
|
'list-leading'?: (props: typeof __VLS_8) => any;
|
|
95
100
|
} & {
|
|
96
|
-
'list-trailing'?: (props: typeof
|
|
101
|
+
'list-trailing'?: (props: typeof __VLS_178) => any;
|
|
97
102
|
};
|
|
98
103
|
declare const __VLS_base: import("vue").DefineComponent<NavigationMenuProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<NavigationMenuProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
99
104
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -6,13 +6,15 @@ import {
|
|
|
6
6
|
NavigationMenuRoot,
|
|
7
7
|
NavigationMenuTrigger,
|
|
8
8
|
NavigationMenuViewport,
|
|
9
|
-
NavigationMenuItem as RekaNavigationMenuItem
|
|
9
|
+
NavigationMenuItem as RekaNavigationMenuItem,
|
|
10
|
+
useDirection
|
|
10
11
|
} from "reka-ui";
|
|
11
12
|
import { computed, ref, useSlots } from "vue";
|
|
12
13
|
import { NuxtLink } from "#components";
|
|
13
14
|
import { useRoute } from "#imports";
|
|
14
15
|
import { useIcons } from "../composables/use-icons";
|
|
15
16
|
import { vHotkey } from "../directives/hotkey";
|
|
17
|
+
import NavigationMenuTooltip from "../internal/NavigationMenuTooltip.vue";
|
|
16
18
|
import ShortcutHint from "../internal/ShortcutHint.vue";
|
|
17
19
|
import { navigationMenuTheme } from "../theme/navigation-menu";
|
|
18
20
|
import { isNavigationMenuItemActive, navigationMenuHotkey } from "../utils/navigation-menu";
|
|
@@ -28,8 +30,11 @@ const props = defineProps({
|
|
|
28
30
|
variant: { type: String, required: false, default: "pill" },
|
|
29
31
|
highlight: { type: Boolean, required: false },
|
|
30
32
|
collapsed: { type: Boolean, required: false },
|
|
33
|
+
tooltip: { type: [Boolean, Object], required: false },
|
|
34
|
+
popover: { type: Object, required: false },
|
|
31
35
|
ui: { type: Object, required: false }
|
|
32
36
|
});
|
|
37
|
+
const direction = useDirection();
|
|
33
38
|
const route = useRoute();
|
|
34
39
|
const icons = useIcons();
|
|
35
40
|
const slots = useSlots();
|
|
@@ -44,6 +49,18 @@ const effectiveColor = computed(() => resolveRegisteredColorRole(props.color ??
|
|
|
44
49
|
const ui = computed(() => theme.value({ orientation: props.orientation, color: effectiveColor.value, variant: props.variant, highlight: props.highlight, collapsed: props.collapsed }));
|
|
45
50
|
const rootProps = computed(() => resolveSlot(ui.value.root, props.ui?.root));
|
|
46
51
|
const listProps = computed(() => resolveSlot(ui.value.list, props.ui?.list));
|
|
52
|
+
function tooltipProps(item) {
|
|
53
|
+
const setting = item.tooltip ?? props.tooltip;
|
|
54
|
+
if (props.orientation !== "vertical" || !props.collapsed || item.disabled || !setting)
|
|
55
|
+
return void 0;
|
|
56
|
+
return {
|
|
57
|
+
text: item.ariaLabel ?? item.label,
|
|
58
|
+
side: direction.value === "rtl" ? "left" : "right",
|
|
59
|
+
delayDuration: 0,
|
|
60
|
+
...typeof props.tooltip === "object" ? props.tooltip : {},
|
|
61
|
+
...typeof item.tooltip === "object" ? item.tooltip : {}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
47
64
|
function isActive(item) {
|
|
48
65
|
return isNavigationMenuItemActive(item, route.path);
|
|
49
66
|
}
|
|
@@ -93,7 +110,7 @@ function onSelect(item, event) {
|
|
|
93
110
|
</template>
|
|
94
111
|
<template v-else-if="orientation === 'vertical' && item.children?.length && collapsed">
|
|
95
112
|
<NavigationMenuFlyoutTrigger
|
|
96
|
-
:item="item" :color="color" :variant="variant" :highlight="highlight" :on-select="onSelect" :ui="props.ui"
|
|
113
|
+
:item="item" :color="color" :variant="variant" :highlight="highlight" :on-select="onSelect" :ui="props.ui" :popover="props.popover"
|
|
97
114
|
:open="openFlyoutLabel === item.label" :another-flyout-open="anotherFlyoutOpen(item)"
|
|
98
115
|
@update:open="onFlyoutOpenChange(item, $event)"
|
|
99
116
|
>
|
|
@@ -144,26 +161,28 @@ function onSelect(item, event) {
|
|
|
144
161
|
</slot>
|
|
145
162
|
</NavigationMenuContent>
|
|
146
163
|
</template>
|
|
147
|
-
<
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
<slot :name="slotName(item, '
|
|
156
|
-
<
|
|
157
|
-
|
|
164
|
+
<NavigationMenuTooltip v-else :tooltip="tooltipProps(item)">
|
|
165
|
+
<NavigationMenuLink as-child :active="isActive(item)">
|
|
166
|
+
<component
|
|
167
|
+
:is="item.to ? NuxtLink : 'button'" v-hotkey="navigationMenuHotkey(item)" :to="item.to"
|
|
168
|
+
:type="item.to ? void 0 : 'button'" :disabled="item.to ? void 0 : item.disabled"
|
|
169
|
+
v-bind="linkProps(item)" :target="item.target" :rel="item.rel"
|
|
170
|
+
:aria-label="item.ariaLabel" :aria-disabled="item.to && item.disabled ? 'true' : void 0" @click="onSelect(item, $event)"
|
|
171
|
+
>
|
|
172
|
+
<slot :name="slotName(item, '')" :item="item" :active="isActive(item)">
|
|
173
|
+
<slot :name="slotName(item, '-leading')" :item="item" :active="isActive(item)">
|
|
174
|
+
<Icon v-if="item.icon" :name="item.icon" v-bind="resolveSlot(ui.linkIcon, props.ui?.linkIcon)" />
|
|
175
|
+
<span v-else-if="collapsed" v-bind="resolveSlot(ui.linkIconFallback, props.ui?.linkIconFallback)" aria-hidden="true">{{ item.label.charAt(0) }}</span>
|
|
176
|
+
</slot>
|
|
177
|
+
<slot :name="slotName(item, '-label')" :item="item" :active="isActive(item)">
|
|
178
|
+
<span v-bind="resolveSlot(ui.linkLabel, props.ui?.linkLabel)">{{ item.label }}</span>
|
|
179
|
+
</slot>
|
|
180
|
+
<slot :name="slotName(item, '-trailing')" :item="item" :active="isActive(item)" />
|
|
181
|
+
<ShortcutHint :shortcut="collapsed ? void 0 : item.shortcut" />
|
|
158
182
|
</slot>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
<slot :name="slotName(item, '-trailing')" :item="item" :active="isActive(item)" />
|
|
163
|
-
<ShortcutHint :shortcut="collapsed ? void 0 : item.shortcut" />
|
|
164
|
-
</slot>
|
|
165
|
-
</component>
|
|
166
|
-
</NavigationMenuLink>
|
|
183
|
+
</component>
|
|
184
|
+
</NavigationMenuLink>
|
|
185
|
+
</NavigationMenuTooltip>
|
|
167
186
|
</RekaNavigationMenuItem>
|
|
168
187
|
</template>
|
|
169
188
|
</NavigationMenuList>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { NavigationMenuThemeSlots } from '../theme/navigation-menu.js';
|
|
2
2
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
3
|
-
import type { NavigationMenuItem } from '../utils/navigation-menu.js';
|
|
3
|
+
import type { NavigationMenuItem, NavigationMenuPopover } from '../utils/navigation-menu.js';
|
|
4
4
|
import type { UiProp } from '../utils/ui.js';
|
|
5
|
+
import type { TooltipProps } from './Tooltip.vue.js';
|
|
5
6
|
export interface NavigationMenuProps {
|
|
6
7
|
items: NavigationMenuItem[];
|
|
7
8
|
/** Horizontal uses Reka's real shared-viewport flyout for a single level of dropdown children. Vertical falls back to a recursive accordion (see NavigationMenuAccordionItem.vue) for arbitrary depth - Reka's own NavigationMenuContent isn't built for deep nested trees. */
|
|
@@ -12,6 +13,10 @@ export interface NavigationMenuProps {
|
|
|
12
13
|
highlight?: boolean;
|
|
13
14
|
/** Icon-only rail mode (vertical only) - labels stay in the DOM for assistive tech (`sr-only`, not removed) but visually collapse to just each item's own leading icon. A parent with children renders as a themed Popover trigger instead of an expandable accordion row - no room for a nested list in an icon rail, so its children surface in a flyout next to the icon instead (the common "collapsed sidebar" pattern - VSCode's activity bar, Linear, Notion). */
|
|
14
15
|
collapsed?: boolean;
|
|
16
|
+
/** Labels for collapsed vertical leaf items. An object customizes Tooltip props. @default false */
|
|
17
|
+
tooltip?: boolean | TooltipProps;
|
|
18
|
+
/** Presentation of collapsed child flyouts; item settings override these defaults. */
|
|
19
|
+
popover?: NavigationMenuPopover;
|
|
15
20
|
ui?: UiProp<NavigationMenuThemeSlots>;
|
|
16
21
|
}
|
|
17
22
|
declare var __VLS_8: {}, __VLS_17: string, __VLS_18: {
|
|
@@ -45,19 +50,19 @@ declare var __VLS_8: {}, __VLS_17: string, __VLS_18: {
|
|
|
45
50
|
}, __VLS_124: string, __VLS_125: {
|
|
46
51
|
item: NavigationMenuItem;
|
|
47
52
|
active: boolean;
|
|
48
|
-
},
|
|
53
|
+
}, __VLS_153: string, __VLS_154: {
|
|
49
54
|
item: NavigationMenuItem;
|
|
50
55
|
active: boolean;
|
|
51
|
-
},
|
|
56
|
+
}, __VLS_157: string, __VLS_158: {
|
|
52
57
|
item: NavigationMenuItem;
|
|
53
58
|
active: boolean;
|
|
54
|
-
},
|
|
59
|
+
}, __VLS_166: string, __VLS_167: {
|
|
55
60
|
item: NavigationMenuItem;
|
|
56
61
|
active: boolean;
|
|
57
|
-
},
|
|
62
|
+
}, __VLS_170: string, __VLS_171: {
|
|
58
63
|
item: NavigationMenuItem;
|
|
59
64
|
active: boolean;
|
|
60
|
-
},
|
|
65
|
+
}, __VLS_178: {};
|
|
61
66
|
type __VLS_Slots = {} & {
|
|
62
67
|
[K in NonNullable<typeof __VLS_17>]?: (props: typeof __VLS_18) => any;
|
|
63
68
|
} & {
|
|
@@ -83,17 +88,17 @@ type __VLS_Slots = {} & {
|
|
|
83
88
|
} & {
|
|
84
89
|
[K in NonNullable<typeof __VLS_124>]?: (props: typeof __VLS_125) => any;
|
|
85
90
|
} & {
|
|
86
|
-
[K in NonNullable<typeof
|
|
91
|
+
[K in NonNullable<typeof __VLS_153>]?: (props: typeof __VLS_154) => any;
|
|
87
92
|
} & {
|
|
88
|
-
[K in NonNullable<typeof
|
|
93
|
+
[K in NonNullable<typeof __VLS_157>]?: (props: typeof __VLS_158) => any;
|
|
89
94
|
} & {
|
|
90
|
-
[K in NonNullable<typeof
|
|
95
|
+
[K in NonNullable<typeof __VLS_166>]?: (props: typeof __VLS_167) => any;
|
|
91
96
|
} & {
|
|
92
|
-
[K in NonNullable<typeof
|
|
97
|
+
[K in NonNullable<typeof __VLS_170>]?: (props: typeof __VLS_171) => any;
|
|
93
98
|
} & {
|
|
94
99
|
'list-leading'?: (props: typeof __VLS_8) => any;
|
|
95
100
|
} & {
|
|
96
|
-
'list-trailing'?: (props: typeof
|
|
101
|
+
'list-trailing'?: (props: typeof __VLS_178) => any;
|
|
97
102
|
};
|
|
98
103
|
declare const __VLS_base: import("vue").DefineComponent<NavigationMenuProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<NavigationMenuProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
99
104
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { NavigationMenuThemeSlots } from '../theme/navigation-menu.js';
|
|
2
2
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
3
|
-
import type { NavigationMenuItem } from '../utils/navigation-menu.js';
|
|
3
|
+
import type { NavigationMenuItem, NavigationMenuPopover } from '../utils/navigation-menu.js';
|
|
4
4
|
import type { UiProp } from '../utils/ui.js';
|
|
5
5
|
export interface NavigationMenuFlyoutTriggerProps {
|
|
6
6
|
item: NavigationMenuItem;
|
|
7
|
+
popover?: NavigationMenuPopover;
|
|
7
8
|
color?: ColorRole;
|
|
8
9
|
variant?: 'pill' | 'link';
|
|
9
10
|
highlight?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useDirection } from "reka-ui";
|
|
2
3
|
import { computed, ref, useSlots } from "vue";
|
|
3
4
|
import { navigationMenuTheme } from "../theme/navigation-menu";
|
|
4
5
|
import { resolveRegisteredColorRole } from "../utils/registered-colors";
|
|
@@ -8,6 +9,7 @@ import NavigationMenuFlyoutList from "./NavigationMenuFlyoutList.vue";
|
|
|
8
9
|
import Popover from "./Popover.vue";
|
|
9
10
|
const props = defineProps({
|
|
10
11
|
item: { type: Object, required: true },
|
|
12
|
+
popover: { type: Object, required: false },
|
|
11
13
|
color: { type: null, required: false },
|
|
12
14
|
variant: { type: String, required: false },
|
|
13
15
|
highlight: { type: Boolean, required: false },
|
|
@@ -18,6 +20,14 @@ const props = defineProps({
|
|
|
18
20
|
});
|
|
19
21
|
const emit = defineEmits(["update:open"]);
|
|
20
22
|
const slots = useSlots();
|
|
23
|
+
const direction = useDirection();
|
|
24
|
+
const popoverProps = computed(() => ({
|
|
25
|
+
side: direction.value === "rtl" ? "left" : "right",
|
|
26
|
+
align: "start",
|
|
27
|
+
...props.popover,
|
|
28
|
+
...props.item.popover,
|
|
29
|
+
ui: { content: "p-2", ...props.popover?.ui, ...props.item.popover?.ui }
|
|
30
|
+
}));
|
|
21
31
|
function slotName(item, suffix) {
|
|
22
32
|
const named = item.slot ? `${item.slot}${suffix}` : void 0;
|
|
23
33
|
if (named && slots[named])
|
|
@@ -88,7 +98,7 @@ function onContentKeydown(event) {
|
|
|
88
98
|
|
|
89
99
|
<template>
|
|
90
100
|
<Popover
|
|
91
|
-
|
|
101
|
+
v-bind="popoverProps" :open="open" :return-focus-on-close="!anotherFlyoutOpen"
|
|
92
102
|
@update:open="emit('update:open', $event)" @open-auto-focus="onOpenAutoFocus"
|
|
93
103
|
>
|
|
94
104
|
<button
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { NavigationMenuThemeSlots } from '../theme/navigation-menu.js';
|
|
2
2
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
3
|
-
import type { NavigationMenuItem } from '../utils/navigation-menu.js';
|
|
3
|
+
import type { NavigationMenuItem, NavigationMenuPopover } from '../utils/navigation-menu.js';
|
|
4
4
|
import type { UiProp } from '../utils/ui.js';
|
|
5
5
|
export interface NavigationMenuFlyoutTriggerProps {
|
|
6
6
|
item: NavigationMenuItem;
|
|
7
|
+
popover?: NavigationMenuPopover;
|
|
7
8
|
color?: ColorRole;
|
|
8
9
|
variant?: 'pill' | 'link';
|
|
9
10
|
highlight?: boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TooltipProps } from '../components/Tooltip.vue.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
tooltip?: TooltipProps;
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_8: {}, __VLS_10: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_8) => any;
|
|
8
|
+
} & {
|
|
9
|
+
default?: (props: typeof __VLS_10) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
15
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
16
|
+
new (): {
|
|
17
|
+
$slots: S;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import Tooltip from "../components/Tooltip.vue";
|
|
3
|
+
defineProps({
|
|
4
|
+
tooltip: { type: Object, required: false }
|
|
5
|
+
});
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<Tooltip v-if="tooltip" v-bind="tooltip">
|
|
10
|
+
<slot />
|
|
11
|
+
</Tooltip>
|
|
12
|
+
<slot v-else />
|
|
13
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TooltipProps } from '../components/Tooltip.vue.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
tooltip?: TooltipProps;
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_8: {}, __VLS_10: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_8) => any;
|
|
8
|
+
} & {
|
|
9
|
+
default?: (props: typeof __VLS_10) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
15
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
16
|
+
new (): {
|
|
17
|
+
$slots: S;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -35,6 +35,7 @@ export declare const datePickerTheme: import("tailwind-variants").TVReturnType<{
|
|
|
35
35
|
headCell: string;
|
|
36
36
|
cell: string;
|
|
37
37
|
viewGrid: string;
|
|
38
|
+
timeSectionStandalone: string;
|
|
38
39
|
timeSection: string;
|
|
39
40
|
arrow: string;
|
|
40
41
|
}, undefined, {
|
|
@@ -74,6 +75,7 @@ export declare const datePickerTheme: import("tailwind-variants").TVReturnType<{
|
|
|
74
75
|
headCell: string;
|
|
75
76
|
cell: string;
|
|
76
77
|
viewGrid: string;
|
|
78
|
+
timeSectionStandalone: string;
|
|
77
79
|
timeSection: string;
|
|
78
80
|
arrow: string;
|
|
79
81
|
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
@@ -113,6 +115,7 @@ export declare const datePickerTheme: import("tailwind-variants").TVReturnType<{
|
|
|
113
115
|
headCell: string;
|
|
114
116
|
cell: string;
|
|
115
117
|
viewGrid: string;
|
|
118
|
+
timeSectionStandalone: string;
|
|
116
119
|
timeSection: string;
|
|
117
120
|
arrow: string;
|
|
118
121
|
}>>;
|
|
@@ -49,6 +49,7 @@ export const datePickerTheme = tv({
|
|
|
49
49
|
viewGrid: "grid grid-cols-3 gap-1",
|
|
50
50
|
// Hour/minute granularity only - sits below the day grid, separated by
|
|
51
51
|
// a divider so it doesn't read as part of the grid itself.
|
|
52
|
+
timeSectionStandalone: "flex items-center justify-center gap-1.5",
|
|
52
53
|
timeSection: "mt-3 flex items-center justify-center gap-1.5 border-t border-[var(--selaras-resolved-border-default)] pt-3",
|
|
53
54
|
arrow: "fill-[var(--selaras-resolved-surface-default)] stroke-[var(--selaras-resolved-border-default)] stroke-1"
|
|
54
55
|
},
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { PopoverProps } from '../components/Popover.vue.js';
|
|
2
|
+
import type { TooltipProps } from '../components/Tooltip.vue.js';
|
|
1
3
|
import type { HotkeyOptions } from '../directives/hotkey.js';
|
|
4
|
+
export type NavigationMenuPopover = Pick<PopoverProps, 'side' | 'align' | 'positioning' | 'portal' | 'arrow' | 'ui'>;
|
|
2
5
|
export interface NavigationMenuItem {
|
|
3
6
|
label: string;
|
|
4
7
|
icon?: string;
|
|
@@ -6,6 +9,10 @@ export interface NavigationMenuItem {
|
|
|
6
9
|
target?: string;
|
|
7
10
|
rel?: string;
|
|
8
11
|
ariaLabel?: string;
|
|
12
|
+
/** Collapsed leaf tooltip override. `false` disables this item's tooltip. */
|
|
13
|
+
tooltip?: boolean | TooltipProps;
|
|
14
|
+
/** Presentation of this item's collapsed child flyout. */
|
|
15
|
+
popover?: NavigationMenuPopover;
|
|
9
16
|
disabled?: boolean;
|
|
10
17
|
/** Force active state - otherwise auto-detected against the current route when `to` is set. */
|
|
11
18
|
active?: boolean;
|
package/package.json
CHANGED