@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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "selaras",
3
3
  "configKey": "selaras",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
@@ -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 const __VLS_base: import("vue").DefineComponent<DashboardSidebarProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DashboardSidebarProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
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
- if (panelRef.value?.isCollapsed)
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
- panelRef.value?.resize(targetWidthPx);
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 const __VLS_base: import("vue").DefineComponent<DashboardSidebarProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DashboardSidebarProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
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: timeSectionProps.value
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
- }, __VLS_147: string, __VLS_148: {
53
+ }, __VLS_153: string, __VLS_154: {
49
54
  item: NavigationMenuItem;
50
55
  active: boolean;
51
- }, __VLS_151: string, __VLS_152: {
56
+ }, __VLS_157: string, __VLS_158: {
52
57
  item: NavigationMenuItem;
53
58
  active: boolean;
54
- }, __VLS_160: string, __VLS_161: {
59
+ }, __VLS_166: string, __VLS_167: {
55
60
  item: NavigationMenuItem;
56
61
  active: boolean;
57
- }, __VLS_164: string, __VLS_165: {
62
+ }, __VLS_170: string, __VLS_171: {
58
63
  item: NavigationMenuItem;
59
64
  active: boolean;
60
- }, __VLS_172: {};
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 __VLS_147>]?: (props: typeof __VLS_148) => any;
91
+ [K in NonNullable<typeof __VLS_153>]?: (props: typeof __VLS_154) => any;
87
92
  } & {
88
- [K in NonNullable<typeof __VLS_151>]?: (props: typeof __VLS_152) => any;
93
+ [K in NonNullable<typeof __VLS_157>]?: (props: typeof __VLS_158) => any;
89
94
  } & {
90
- [K in NonNullable<typeof __VLS_160>]?: (props: typeof __VLS_161) => any;
95
+ [K in NonNullable<typeof __VLS_166>]?: (props: typeof __VLS_167) => any;
91
96
  } & {
92
- [K in NonNullable<typeof __VLS_164>]?: (props: typeof __VLS_165) => any;
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 __VLS_172) => any;
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
- <NavigationMenuLink v-else as-child :active="isActive(item)">
148
- <component
149
- :is="item.to ? NuxtLink : 'button'" v-hotkey="navigationMenuHotkey(item)" :to="item.to"
150
- :type="item.to ? void 0 : 'button'" :disabled="item.to ? void 0 : item.disabled"
151
- v-bind="linkProps(item)" :target="item.target" :rel="item.rel"
152
- :aria-label="item.ariaLabel" :aria-disabled="item.to && item.disabled ? 'true' : void 0" @click="onSelect(item, $event)"
153
- >
154
- <slot :name="slotName(item, '')" :item="item" :active="isActive(item)">
155
- <slot :name="slotName(item, '-leading')" :item="item" :active="isActive(item)">
156
- <Icon v-if="item.icon" :name="item.icon" v-bind="resolveSlot(ui.linkIcon, props.ui?.linkIcon)" />
157
- <span v-else-if="collapsed" v-bind="resolveSlot(ui.linkIconFallback, props.ui?.linkIconFallback)" aria-hidden="true">{{ item.label.charAt(0) }}</span>
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
- <slot :name="slotName(item, '-label')" :item="item" :active="isActive(item)">
160
- <span v-bind="resolveSlot(ui.linkLabel, props.ui?.linkLabel)">{{ item.label }}</span>
161
- </slot>
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
- }, __VLS_147: string, __VLS_148: {
53
+ }, __VLS_153: string, __VLS_154: {
49
54
  item: NavigationMenuItem;
50
55
  active: boolean;
51
- }, __VLS_151: string, __VLS_152: {
56
+ }, __VLS_157: string, __VLS_158: {
52
57
  item: NavigationMenuItem;
53
58
  active: boolean;
54
- }, __VLS_160: string, __VLS_161: {
59
+ }, __VLS_166: string, __VLS_167: {
55
60
  item: NavigationMenuItem;
56
61
  active: boolean;
57
- }, __VLS_164: string, __VLS_165: {
62
+ }, __VLS_170: string, __VLS_171: {
58
63
  item: NavigationMenuItem;
59
64
  active: boolean;
60
- }, __VLS_172: {};
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 __VLS_147>]?: (props: typeof __VLS_148) => any;
91
+ [K in NonNullable<typeof __VLS_153>]?: (props: typeof __VLS_154) => any;
87
92
  } & {
88
- [K in NonNullable<typeof __VLS_151>]?: (props: typeof __VLS_152) => any;
93
+ [K in NonNullable<typeof __VLS_157>]?: (props: typeof __VLS_158) => any;
89
94
  } & {
90
- [K in NonNullable<typeof __VLS_160>]?: (props: typeof __VLS_161) => any;
95
+ [K in NonNullable<typeof __VLS_166>]?: (props: typeof __VLS_167) => any;
91
96
  } & {
92
- [K in NonNullable<typeof __VLS_164>]?: (props: typeof __VLS_165) => any;
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 __VLS_172) => any;
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
- :open="open" side="right" align="start" :return-focus-on-close="!anotherFlyoutOpen" :ui="{ content: 'p-2' }"
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sewadah/selaras",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "description": "A UI component library for Nuxt, built on Reka UI and Tailwind v4",
6
6
  "author": "Wicaksana Pratama <wicaksanapratama@gmail.com>",
7
7
  "license": "MIT",