@sewadah/selaras 0.2.0 → 0.3.1
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/README.md +36 -7
- package/dist/module.json +1 -1
- package/dist/module.mjs +31 -15
- package/dist/runtime/components/Autocomplete.vue +3 -1
- package/dist/runtime/components/Badge.d.vue.ts +1 -1
- package/dist/runtime/components/Badge.vue.d.ts +1 -1
- package/dist/runtime/components/Calendar.d.vue.ts +69 -0
- package/dist/runtime/components/Calendar.vue +163 -0
- package/dist/runtime/components/Calendar.vue.d.ts +69 -0
- package/dist/runtime/components/Callout.vue +12 -1
- package/dist/runtime/components/CodeGroup.vue +13 -3
- package/dist/runtime/components/CodeTree.d.vue.ts +2 -0
- package/dist/runtime/components/CodeTree.vue +52 -1
- package/dist/runtime/components/CodeTree.vue.d.ts +2 -0
- package/dist/runtime/components/ColorPicker.d.vue.ts +8 -0
- package/dist/runtime/components/ColorPicker.vue +66 -45
- package/dist/runtime/components/ColorPicker.vue.d.ts +8 -0
- package/dist/runtime/components/Column.js +1 -1
- package/dist/runtime/components/CommandPalette.d.vue.ts +3 -1
- package/dist/runtime/components/CommandPalette.vue +5 -0
- package/dist/runtime/components/CommandPalette.vue.d.ts +3 -1
- package/dist/runtime/components/ContentNavigation.d.vue.ts +8 -1
- package/dist/runtime/components/ContentNavigation.vue +9 -2
- package/dist/runtime/components/ContentNavigation.vue.d.ts +8 -1
- package/dist/runtime/components/ContentToc.vue +14 -7
- package/dist/runtime/components/ContextMenu.d.vue.ts +8 -1
- package/dist/runtime/components/ContextMenu.vue +16 -4
- package/dist/runtime/components/ContextMenu.vue.d.ts +8 -1
- package/dist/runtime/components/DatePicker.d.vue.ts +10 -3
- package/dist/runtime/components/DatePicker.vue +24 -16
- package/dist/runtime/components/DatePicker.vue.d.ts +10 -3
- package/dist/runtime/components/Dropdown.d.vue.ts +33 -6
- package/dist/runtime/components/Dropdown.vue +143 -11
- package/dist/runtime/components/Dropdown.vue.d.ts +33 -6
- package/dist/runtime/components/FileTree.d.vue.ts +2 -0
- package/dist/runtime/components/FileTree.vue +8 -4
- package/dist/runtime/components/FileTree.vue.d.ts +2 -0
- package/dist/runtime/components/FileUpload.vue +1 -1
- package/dist/runtime/components/FormField.d.vue.ts +4 -0
- package/dist/runtime/components/FormField.vue +19 -4
- package/dist/runtime/components/FormField.vue.d.ts +4 -0
- package/dist/runtime/components/Input.vue +3 -2
- package/dist/runtime/components/Kbd.vue +12 -2
- package/dist/runtime/components/NavigationMenu.d.vue.ts +10 -10
- package/dist/runtime/components/NavigationMenu.vue +13 -7
- package/dist/runtime/components/NavigationMenu.vue.d.ts +10 -10
- package/dist/runtime/components/NavigationMenuAccordionItem.vue +5 -1
- package/dist/runtime/components/NavigationMenuFlyoutList.vue +7 -4
- package/dist/runtime/components/PinInput.vue +1 -1
- package/dist/runtime/components/Popover.d.vue.ts +8 -2
- package/dist/runtime/components/Popover.vue +9 -4
- package/dist/runtime/components/Popover.vue.d.ts +8 -2
- package/dist/runtime/components/ProsePre.d.vue.ts +6 -2
- package/dist/runtime/components/ProsePre.vue +11 -4
- package/dist/runtime/components/ProsePre.vue.d.ts +6 -2
- package/dist/runtime/components/Select.vue +3 -1
- package/dist/runtime/components/SplitterPanel.d.vue.ts +2 -2
- package/dist/runtime/components/SplitterPanel.vue.d.ts +2 -2
- package/dist/runtime/components/Table.vue +95 -26
- package/dist/runtime/components/Tabs.d.vue.ts +44 -4
- package/dist/runtime/components/Tabs.vue +171 -18
- package/dist/runtime/components/Tabs.vue.d.ts +44 -4
- package/dist/runtime/components/Textarea.vue +3 -2
- package/dist/runtime/components/Timeline.d.vue.ts +19 -0
- package/dist/runtime/components/Timeline.vue +99 -0
- package/dist/runtime/components/Timeline.vue.d.ts +19 -0
- package/dist/runtime/components/Toast.d.vue.ts +10 -1
- package/dist/runtime/components/Toast.vue +94 -8
- package/dist/runtime/components/Toast.vue.d.ts +10 -1
- package/dist/runtime/components/Tooltip.d.vue.ts +8 -2
- package/dist/runtime/components/Tooltip.vue +9 -4
- package/dist/runtime/components/Tooltip.vue.d.ts +8 -2
- package/dist/runtime/composables/use-form-field.d.ts +1 -0
- package/dist/runtime/composables/use-table.d.ts +3 -0
- package/dist/runtime/composables/use-table.js +10 -4
- package/dist/runtime/composables/use-toast.js +5 -1
- package/dist/runtime/default-colors.css +1 -1
- package/dist/runtime/directives/hotkey.d.ts +13 -0
- package/dist/runtime/directives/hotkey.js +107 -0
- package/dist/runtime/directives/index.d.ts +2 -0
- package/dist/runtime/directives/index.js +2 -0
- package/dist/runtime/directives/mask.d.ts +30 -0
- package/dist/runtime/directives/mask.js +165 -0
- package/dist/runtime/internal/ComboboxSelectBase.d.vue.ts +29 -25
- package/dist/runtime/internal/ComboboxSelectBase.vue +104 -20
- package/dist/runtime/internal/ComboboxSelectBase.vue.d.ts +29 -25
- package/dist/runtime/internal/ComboboxSelectBody.d.vue.ts +16 -11
- package/dist/runtime/internal/ComboboxSelectBody.vue +49 -10
- package/dist/runtime/internal/ComboboxSelectBody.vue.d.ts +16 -11
- package/dist/runtime/internal/DatePickerCalendarBody.vue +1 -1
- package/dist/runtime/internal/DatePickerRangeCalendarBody.vue +1 -1
- package/dist/runtime/internal/ShortcutHint.d.vue.ts +6 -0
- package/dist/runtime/internal/ShortcutHint.vue +13 -0
- package/dist/runtime/internal/ShortcutHint.vue.d.ts +6 -0
- package/dist/runtime/internal/ToastItemRenderer.d.vue.ts +9 -1
- package/dist/runtime/internal/ToastItemRenderer.vue +55 -8
- package/dist/runtime/internal/ToastItemRenderer.vue.d.ts +9 -1
- package/dist/runtime/internal/combobox-select.js +2 -1
- package/dist/runtime/internal/programmatic-services.d.ts +2 -0
- package/dist/runtime/internal/programmatic-services.js +8 -0
- package/dist/runtime/internal/toast-stack.d.ts +36 -0
- package/dist/runtime/internal/toast-stack.js +36 -0
- package/dist/runtime/structural.css +1 -1
- package/dist/runtime/table.d.ts +1 -1
- package/dist/runtime/theme/alert-dialog.js +1 -1
- package/dist/runtime/theme/avatar.js +7 -7
- package/dist/runtime/theme/badge.js +2 -2
- package/dist/runtime/theme/calendar.d.ts +86 -0
- package/dist/runtime/theme/calendar.js +19 -0
- package/dist/runtime/theme/callout.d.ts +0 -12
- package/dist/runtime/theme/callout.js +8 -8
- package/dist/runtime/theme/checkbox.js +1 -1
- package/dist/runtime/theme/code-tree.js +1 -1
- package/dist/runtime/theme/command-palette.js +1 -1
- package/dist/runtime/theme/content-navigation.d.ts +3 -0
- package/dist/runtime/theme/content-navigation.js +1 -0
- package/dist/runtime/theme/date-picker.js +1 -1
- package/dist/runtime/theme/drawer.js +1 -1
- package/dist/runtime/theme/dropdown.d.ts +21 -0
- package/dist/runtime/theme/dropdown.js +15 -2
- package/dist/runtime/theme/file-tree.js +1 -1
- package/dist/runtime/theme/file-upload.js +2 -2
- package/dist/runtime/theme/form-field.d.ts +18 -0
- package/dist/runtime/theme/form-field.js +6 -1
- package/dist/runtime/theme/icon.js +1 -1
- package/dist/runtime/theme/input-number.js +1 -1
- package/dist/runtime/theme/input.js +1 -1
- package/dist/runtime/theme/modal.js +1 -1
- package/dist/runtime/theme/pin-input.js +1 -1
- package/dist/runtime/theme/progress.js +2 -2
- package/dist/runtime/theme/prose.d.ts +6 -0
- package/dist/runtime/theme/prose.js +2 -0
- package/dist/runtime/theme/radio-group.js +4 -4
- package/dist/runtime/theme/rating.js +1 -1
- package/dist/runtime/theme/select.js +2 -2
- package/dist/runtime/theme/separator.js +1 -1
- package/dist/runtime/theme/slideover.js +1 -1
- package/dist/runtime/theme/slider.js +2 -2
- package/dist/runtime/theme/splitter-resize-handle.js +1 -1
- package/dist/runtime/theme/switch.js +1 -1
- package/dist/runtime/theme/table.d.ts +27 -0
- package/dist/runtime/theme/table.js +11 -2
- package/dist/runtime/theme/tabs.d.ts +87 -3
- package/dist/runtime/theme/tabs.js +46 -22
- package/dist/runtime/theme/textarea.js +1 -1
- package/dist/runtime/theme/timeline.d.ts +251 -0
- package/dist/runtime/theme/timeline.js +84 -0
- package/dist/runtime/theme/toast.d.ts +92 -0
- package/dist/runtime/theme/toast.js +29 -7
- package/dist/runtime/theme-config.d.ts +12 -1
- package/dist/runtime/types/index.d.ts +6 -1
- package/dist/runtime/utils/arrow.d.ts +21 -0
- package/dist/runtime/utils/arrow.js +10 -0
- package/dist/runtime/utils/color-registry.d.ts +3 -1
- package/dist/runtime/utils/color-registry.js +4 -0
- package/dist/runtime/utils/file-icons.d.ts +8 -0
- package/dist/runtime/utils/file-icons.js +133 -0
- package/dist/runtime/utils/functional-tokens.d.ts +1 -1
- package/dist/runtime/utils/functional-tokens.js +1 -1
- package/dist/runtime/utils/icons.d.ts +2 -0
- package/dist/runtime/utils/icons.js +2 -0
- package/dist/runtime/utils/messages.d.ts +6 -0
- package/dist/runtime/utils/messages.js +6 -0
- package/dist/runtime/utils/navigation-menu.d.ts +10 -0
- package/dist/runtime/utils/navigation-menu.js +3 -0
- package/dist/runtime/utils/overlay.d.ts +17 -0
- package/dist/runtime/utils/overlay.js +7 -0
- package/dist/runtime/utils/seed-colors.d.ts +2 -1
- package/dist/runtime/utils/seed-colors.js +24 -16
- package/dist/runtime/utils/select-contracts.d.ts +7 -1
- package/dist/runtime/utils/table-columns.js +1 -1
- package/dist/runtime/utils/table-contracts.d.ts +9 -1
- package/dist/runtime/utils/timeline-contracts.d.ts +42 -0
- package/dist/runtime/utils/timeline-contracts.js +0 -0
- package/dist/tokens/default-colors.tokens.json +100 -100
- package/package.json +21 -9
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { VariantProps } from 'tailwind-variants';
|
|
2
2
|
import type { ColorPickerThemeSlots } from '../theme/color-picker.js';
|
|
3
|
+
import type { RoundedArrowConfig } from '../utils/arrow.js';
|
|
3
4
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
5
|
+
import type { OverlayPortal, OverlayPositioning } from '../utils/overlay.js';
|
|
4
6
|
import type { UiProp } from '../utils/ui.js';
|
|
5
7
|
import { colorPickerTheme } from '../theme/color-picker.js';
|
|
6
8
|
type ColorPickerVariants = VariantProps<typeof colorPickerTheme>;
|
|
@@ -21,6 +23,12 @@ export interface ColorPickerProps {
|
|
|
21
23
|
placeholder?: string;
|
|
22
24
|
/** Opts into the picker's accessible small-screen modal presentation. */
|
|
23
25
|
adaptive?: boolean;
|
|
26
|
+
/** Shows a pointer on the anchored picker; the adaptive modal has no arrow. */
|
|
27
|
+
arrow?: boolean | RoundedArrowConfig;
|
|
28
|
+
/** Positioning of the anchored picker (the adaptive modal uses its own layout). */
|
|
29
|
+
positioning?: OverlayPositioning;
|
|
30
|
+
/** Teleport target for the anchored picker, or `false` to render it inline. */
|
|
31
|
+
portal?: OverlayPortal;
|
|
24
32
|
size?: ColorPickerVariants['size'];
|
|
25
33
|
color?: ColorRole;
|
|
26
34
|
ui?: UiProp<ColorPickerThemeSlots>;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ColorSwatch } from "reka-ui";
|
|
2
|
+
import { ColorSwatch, PopoverArrow, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from "reka-ui";
|
|
3
3
|
import { computed, getCurrentInstance, onMounted, onUnmounted, ref, watch } from "vue";
|
|
4
|
+
import { useFormField } from "../composables/use-form-field";
|
|
4
5
|
import { useIsMobile } from "../composables/use-media-query";
|
|
5
6
|
import { useMessages } from "../composables/use-messages";
|
|
6
7
|
import ColorPickerBody from "../internal/ColorPickerBody.vue";
|
|
7
8
|
import { colorPickerTheme } from "../theme/color-picker";
|
|
9
|
+
import { popoverTheme } from "../theme/popover";
|
|
10
|
+
import { arrowContentProps, arrowElementProps } from "../utils/arrow";
|
|
11
|
+
import { overlayPortalProps } from "../utils/overlay";
|
|
8
12
|
import { resolveRegisteredColorRole } from "../utils/registered-colors";
|
|
9
13
|
import { resolveSlot, useComponentTheme, useThemeBindings } from "../utils/ui";
|
|
10
14
|
import Modal from "./Modal.vue";
|
|
11
|
-
import Popover from "./Popover.vue";
|
|
12
15
|
const props = defineProps({
|
|
13
16
|
name: { type: String, required: false },
|
|
14
17
|
form: { type: String, required: false },
|
|
@@ -21,12 +24,17 @@ const props = defineProps({
|
|
|
21
24
|
swatches: { type: Array, required: false },
|
|
22
25
|
placeholder: { type: String, required: false },
|
|
23
26
|
adaptive: { type: Boolean, required: false },
|
|
27
|
+
arrow: { type: [Boolean, Object], required: false },
|
|
28
|
+
positioning: { type: Object, required: false },
|
|
29
|
+
portal: { type: [Boolean, String], required: false, skipCheck: true, default: void 0 },
|
|
24
30
|
size: { type: null, required: false },
|
|
25
31
|
color: { type: null, required: false },
|
|
26
32
|
ui: { type: Object, required: false }
|
|
27
33
|
});
|
|
28
34
|
const emit = defineEmits(["update:open", "update:modelValue"]);
|
|
29
35
|
const messages = useMessages();
|
|
36
|
+
const field = useFormField();
|
|
37
|
+
const formName = computed(() => props.name ?? field?.name);
|
|
30
38
|
const instance = getCurrentInstance();
|
|
31
39
|
const formAnchor = ref();
|
|
32
40
|
const initialColor = props.defaultValue ?? "#000000";
|
|
@@ -104,55 +112,68 @@ const bodyProps = computed(() => ({
|
|
|
104
112
|
swatchIndicatorProps: swatchIndicatorProps.value,
|
|
105
113
|
colorRoleMarker: colorRoleMarker.value
|
|
106
114
|
}));
|
|
107
|
-
const
|
|
115
|
+
const popoverThemeFn = useComponentTheme("popover", popoverTheme);
|
|
116
|
+
const popoverUi = computed(() => popoverThemeFn.value());
|
|
117
|
+
const popoverContentProps = computed(() => ({
|
|
118
|
+
...resolveSlot(popoverUi.value.content, resolveSlot(ui.value.content, props.ui?.content)),
|
|
119
|
+
...arrowContentProps(props.arrow),
|
|
120
|
+
...props.positioning
|
|
121
|
+
}));
|
|
122
|
+
const popoverArrowProps = computed(() => ({ ...resolveSlot(popoverUi.value.arrow, void 0), ...arrowElementProps(props.arrow) }));
|
|
123
|
+
const popoverPortalProps = computed(() => overlayPortalProps(props.portal));
|
|
108
124
|
const adaptiveUi = computed(() => ({ content: "rounded-[var(--selaras-resolved-radius-md)]" }));
|
|
109
125
|
const mobileContentProps = computed(() => resolveSlot(ui.value.mobileContent, props.ui?.mobileContent));
|
|
110
126
|
</script>
|
|
111
127
|
|
|
112
128
|
<template>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
<!--
|
|
130
|
+
The root and trigger stay mounted for both presentations. Only the
|
|
131
|
+
content switches: the anchored panel is removed outright while the
|
|
132
|
+
adaptive Modal is showing, and the Modal returns focus to this same
|
|
133
|
+
trigger on close.
|
|
134
|
+
-->
|
|
135
|
+
<PopoverRoot :open="open" @update:open="onUpdateOpen">
|
|
136
|
+
<PopoverTrigger as-child>
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
:disabled="disabled"
|
|
140
|
+
:aria-label="messages.colorPicker"
|
|
141
|
+
:data-selaras-color="colorRoleMarker"
|
|
142
|
+
:data-selaras-theme="themeBindings['data-selaras-theme']"
|
|
143
|
+
:data-selaras-mode="themeBindings['data-selaras-mode']"
|
|
144
|
+
:style="themeBindings.style"
|
|
145
|
+
v-bind="triggerProps"
|
|
146
|
+
>
|
|
147
|
+
<ColorSwatch :color="internalColor" v-bind="triggerSwatchProps" />
|
|
148
|
+
<span v-bind="triggerValueProps">{{ internalColor }}</span>
|
|
149
|
+
</button>
|
|
150
|
+
</PopoverTrigger>
|
|
127
151
|
|
|
128
|
-
<
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
152
|
+
<PopoverPortal v-if="!showMobileModal" v-bind="popoverPortalProps">
|
|
153
|
+
<PopoverContent
|
|
154
|
+
:data-selaras-theme="themeBindings['data-selaras-theme']"
|
|
155
|
+
:data-selaras-mode="themeBindings['data-selaras-mode']"
|
|
156
|
+
:style="themeBindings.style"
|
|
157
|
+
side="bottom"
|
|
158
|
+
align="start"
|
|
159
|
+
:side-offset="8"
|
|
160
|
+
v-bind="popoverContentProps"
|
|
161
|
+
>
|
|
162
|
+
<ColorPickerBody v-bind="bodyProps" @update:model-value="onUpdateColor" />
|
|
163
|
+
<PopoverArrow v-if="arrow" v-bind="popoverArrowProps" />
|
|
164
|
+
</PopoverContent>
|
|
165
|
+
</PopoverPortal>
|
|
132
166
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
>
|
|
137
|
-
<button
|
|
138
|
-
type="button"
|
|
139
|
-
:disabled="disabled"
|
|
140
|
-
:aria-label="messages.colorPicker"
|
|
141
|
-
:data-selaras-color="colorRoleMarker"
|
|
142
|
-
:data-selaras-theme="themeBindings['data-selaras-theme']"
|
|
143
|
-
:data-selaras-mode="themeBindings['data-selaras-mode']"
|
|
144
|
-
:style="themeBindings.style"
|
|
145
|
-
v-bind="triggerProps"
|
|
167
|
+
<Modal
|
|
168
|
+
v-else :open="open" :title="messages.colorPicker" :description="messages.colorPickerDescription"
|
|
169
|
+
:ui="adaptiveUi" @update:open="onUpdateOpen"
|
|
146
170
|
>
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
</template>
|
|
156
|
-
</Modal>
|
|
157
|
-
<input ref="formAnchor" type="hidden" :name="name" :form="form" :value="internalColor">
|
|
171
|
+
<template #content>
|
|
172
|
+
<div v-bind="mobileContentProps">
|
|
173
|
+
<ColorPickerBody v-bind="bodyProps" @update:model-value="onUpdateColor" />
|
|
174
|
+
</div>
|
|
175
|
+
</template>
|
|
176
|
+
</Modal>
|
|
177
|
+
</PopoverRoot>
|
|
178
|
+
<input ref="formAnchor" type="hidden" :name="formName" :form="form" :value="internalColor" :disabled="disabled">
|
|
158
179
|
</template>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { VariantProps } from 'tailwind-variants';
|
|
2
2
|
import type { ColorPickerThemeSlots } from '../theme/color-picker.js';
|
|
3
|
+
import type { RoundedArrowConfig } from '../utils/arrow.js';
|
|
3
4
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
5
|
+
import type { OverlayPortal, OverlayPositioning } from '../utils/overlay.js';
|
|
4
6
|
import type { UiProp } from '../utils/ui.js';
|
|
5
7
|
import { colorPickerTheme } from '../theme/color-picker.js';
|
|
6
8
|
type ColorPickerVariants = VariantProps<typeof colorPickerTheme>;
|
|
@@ -21,6 +23,12 @@ export interface ColorPickerProps {
|
|
|
21
23
|
placeholder?: string;
|
|
22
24
|
/** Opts into the picker's accessible small-screen modal presentation. */
|
|
23
25
|
adaptive?: boolean;
|
|
26
|
+
/** Shows a pointer on the anchored picker; the adaptive modal has no arrow. */
|
|
27
|
+
arrow?: boolean | RoundedArrowConfig;
|
|
28
|
+
/** Positioning of the anchored picker (the adaptive modal uses its own layout). */
|
|
29
|
+
positioning?: OverlayPositioning;
|
|
30
|
+
/** Teleport target for the anchored picker, or `false` to render it inline. */
|
|
31
|
+
portal?: OverlayPortal;
|
|
24
32
|
size?: ColorPickerVariants['size'];
|
|
25
33
|
color?: ColorRole;
|
|
26
34
|
ui?: UiProp<ColorPickerThemeSlots>;
|
|
@@ -3,8 +3,10 @@ import type { UiProp } from '../utils/ui.js';
|
|
|
3
3
|
export interface CommandPaletteItem {
|
|
4
4
|
label: string;
|
|
5
5
|
icon?: string;
|
|
6
|
-
/**
|
|
6
|
+
/** Displayed via Kbd. */
|
|
7
7
|
shortcut?: string;
|
|
8
|
+
/** Bind `shortcut` while this palette is open; activation uses this item's normal selection behavior. */
|
|
9
|
+
hotkey?: boolean;
|
|
8
10
|
disabled?: boolean;
|
|
9
11
|
onSelect?: () => void;
|
|
10
12
|
}
|
|
@@ -4,6 +4,7 @@ import { computed, onMounted, onUnmounted, ref, useId, watch } from "vue";
|
|
|
4
4
|
import { useCommandPalette } from "../composables/use-command-palette";
|
|
5
5
|
import { useIcons } from "../composables/use-icons";
|
|
6
6
|
import { useMessages } from "../composables/use-messages";
|
|
7
|
+
import { vHotkey } from "../directives/hotkey";
|
|
7
8
|
import { commandPaletteTheme } from "../theme/command-palette";
|
|
8
9
|
import { fuzzyScore } from "../utils/fuzzy-match";
|
|
9
10
|
import { applyClassPrefix, resolveSlot, useComponentTheme, useRootProps, useThemeBindings } from "../utils/ui";
|
|
@@ -40,6 +41,9 @@ const query = ref("");
|
|
|
40
41
|
const highlightedIndex = ref(0);
|
|
41
42
|
const inputRef = ref();
|
|
42
43
|
const listboxId = `selaras-command-palette-list-${useId()}`;
|
|
44
|
+
function hotkeyFor(item) {
|
|
45
|
+
return item.hotkey && item.shortcut && !item.disabled ? { keys: item.shortcut, when: () => isOpen.value, allowInEditable: true } : void 0;
|
|
46
|
+
}
|
|
43
47
|
watch(isOpen, (open) => {
|
|
44
48
|
if (!open) {
|
|
45
49
|
query.value = "";
|
|
@@ -178,6 +182,7 @@ function itemId(index) {
|
|
|
178
182
|
v-for="item in group.items"
|
|
179
183
|
:id="itemId(allItems.indexOf(item))"
|
|
180
184
|
:key="item.label"
|
|
185
|
+
v-hotkey="hotkeyFor(item)"
|
|
181
186
|
role="option"
|
|
182
187
|
:aria-selected="isHighlighted(item)"
|
|
183
188
|
:aria-disabled="item.disabled"
|
|
@@ -3,8 +3,10 @@ import type { UiProp } from '../utils/ui.js';
|
|
|
3
3
|
export interface CommandPaletteItem {
|
|
4
4
|
label: string;
|
|
5
5
|
icon?: string;
|
|
6
|
-
/**
|
|
6
|
+
/** Displayed via Kbd. */
|
|
7
7
|
shortcut?: string;
|
|
8
|
+
/** Bind `shortcut` while this palette is open; activation uses this item's normal selection behavior. */
|
|
9
|
+
hotkey?: boolean;
|
|
8
10
|
disabled?: boolean;
|
|
9
11
|
onSelect?: () => void;
|
|
10
12
|
}
|
|
@@ -4,7 +4,12 @@ import type { UiProp } from '../utils/ui.js';
|
|
|
4
4
|
export interface ContentNavigationLink {
|
|
5
5
|
title: string;
|
|
6
6
|
path: string;
|
|
7
|
-
icon?: string;
|
|
7
|
+
icon?: string | false;
|
|
8
|
+
order?: number;
|
|
9
|
+
collapse?: boolean;
|
|
10
|
+
navBadges?: Array<string | {
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
8
13
|
children?: ContentNavigationLink[];
|
|
9
14
|
}
|
|
10
15
|
type __VLS_Slots = ContentNavigationSlots;
|
|
@@ -12,6 +17,8 @@ export interface ContentNavigationProps {
|
|
|
12
17
|
navigation: ContentNavigationLink[];
|
|
13
18
|
/** The active-link accent. @default 'primary' */
|
|
14
19
|
color?: ColorRole;
|
|
20
|
+
/** Collapse every group initially unless the item's own `collapse` metadata overrides it. @default false */
|
|
21
|
+
collapsed?: boolean;
|
|
15
22
|
/** Set only by this component's own recursive self-call, one level down for each nested group - gates the tree-connector rail (see `content-navigation.ts`'s own `isNested` variant), since a root-level entry has no parent trunk to its left to branch off of. */
|
|
16
23
|
isNested?: boolean;
|
|
17
24
|
ui?: UiProp<ContentNavigationThemeSlots>;
|
|
@@ -10,6 +10,7 @@ defineOptions({ inheritAttrs: false });
|
|
|
10
10
|
const props = defineProps({
|
|
11
11
|
navigation: { type: Array, required: true },
|
|
12
12
|
color: { type: null, required: false },
|
|
13
|
+
collapsed: { type: Boolean, required: false },
|
|
13
14
|
isNested: { type: Boolean, required: false },
|
|
14
15
|
ui: { type: Object, required: false }
|
|
15
16
|
});
|
|
@@ -37,19 +38,22 @@ const groupUi = computed(() => ({
|
|
|
37
38
|
<Accordion
|
|
38
39
|
v-if="link.children?.length"
|
|
39
40
|
:items="[{ value: link.path, label: link.title }]"
|
|
40
|
-
:default-value="[link.path]"
|
|
41
|
+
:default-value="link.collapse ?? collapsed ? [] : [link.path]"
|
|
41
42
|
:ui="groupUi"
|
|
42
43
|
>
|
|
43
44
|
<template #label>
|
|
44
45
|
<slot name="link" :link="link" :active="false">
|
|
45
46
|
<Icon v-if="link.icon" :name="link.icon" v-bind="resolveSlot(ui.icon, props.ui?.icon)" />
|
|
46
47
|
{{ link.title }}
|
|
48
|
+
<span v-for="(badge, index) in link.navBadges" :key="`${link.path}:badge:${index}`" v-bind="resolveSlot(ui.badge, props.ui?.badge)">
|
|
49
|
+
{{ typeof badge === "string" ? badge : badge.text }}
|
|
50
|
+
</span>
|
|
47
51
|
</slot>
|
|
48
52
|
</template>
|
|
49
53
|
<template #[link.path]>
|
|
50
54
|
<!-- Vue's SFC self-recursion resolves by this file's own bare name -
|
|
51
55
|
keep it unprefixed even though the public component is SContentNavigation. -->
|
|
52
|
-
<ContentNavigation :navigation="link.children" is-nested :color="color" :ui="props.ui">
|
|
56
|
+
<ContentNavigation :navigation="link.children" is-nested :color="color" :collapsed="collapsed" :ui="props.ui">
|
|
53
57
|
<template #link="scope">
|
|
54
58
|
<slot name="link" v-bind="scope" />
|
|
55
59
|
</template>
|
|
@@ -60,6 +64,9 @@ const groupUi = computed(() => ({
|
|
|
60
64
|
<slot name="link" :link="link" :active="isActive(link)">
|
|
61
65
|
<Icon v-if="link.icon" :name="link.icon" v-bind="resolveSlot(ui.icon, props.ui?.icon)" />
|
|
62
66
|
{{ link.title }}
|
|
67
|
+
<span v-for="(badge, index) in link.navBadges" :key="`${link.path}:badge:${index}`" v-bind="resolveSlot(ui.badge, props.ui?.badge)">
|
|
68
|
+
{{ typeof badge === "string" ? badge : badge.text }}
|
|
69
|
+
</span>
|
|
63
70
|
</slot>
|
|
64
71
|
</NuxtLink>
|
|
65
72
|
</li>
|
|
@@ -4,7 +4,12 @@ import type { UiProp } from '../utils/ui.js';
|
|
|
4
4
|
export interface ContentNavigationLink {
|
|
5
5
|
title: string;
|
|
6
6
|
path: string;
|
|
7
|
-
icon?: string;
|
|
7
|
+
icon?: string | false;
|
|
8
|
+
order?: number;
|
|
9
|
+
collapse?: boolean;
|
|
10
|
+
navBadges?: Array<string | {
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
8
13
|
children?: ContentNavigationLink[];
|
|
9
14
|
}
|
|
10
15
|
type __VLS_Slots = ContentNavigationSlots;
|
|
@@ -12,6 +17,8 @@ export interface ContentNavigationProps {
|
|
|
12
17
|
navigation: ContentNavigationLink[];
|
|
13
18
|
/** The active-link accent. @default 'primary' */
|
|
14
19
|
color?: ColorRole;
|
|
20
|
+
/** Collapse every group initially unless the item's own `collapse` metadata overrides it. @default false */
|
|
21
|
+
collapsed?: boolean;
|
|
15
22
|
/** Set only by this component's own recursive self-call, one level down for each nested group - gates the tree-connector rail (see `content-navigation.ts`'s own `isNested` variant), since a root-level entry has no parent trunk to its left to branch off of. */
|
|
16
23
|
isNested?: boolean;
|
|
17
24
|
ui?: UiProp<ContentNavigationThemeSlots>;
|
|
@@ -119,27 +119,34 @@ function buildRailPath(links, height) {
|
|
|
119
119
|
const x2 = RAIL_X_OUTER + index * indentStep;
|
|
120
120
|
return Math.round(clamp(x2, RAIL_X_OUTER, RAIL_X_INNER_MAX));
|
|
121
121
|
};
|
|
122
|
+
const curveHalf = RAIL_CURVE_SPAN / 2;
|
|
122
123
|
let x = xForDepth(items[0]?.depth ?? baseDepth);
|
|
124
|
+
let yPath = 0;
|
|
123
125
|
let yPrev = 0;
|
|
124
126
|
let d = `M ${x} 0`;
|
|
125
127
|
for (const item of items) {
|
|
126
128
|
const y = clamp(item.y, 0, height);
|
|
127
129
|
const xNext = xForDepth(item.depth);
|
|
128
130
|
if (xNext === x) {
|
|
129
|
-
if (y >
|
|
131
|
+
if (y > yPath) {
|
|
130
132
|
d += ` L ${x} ${y}`;
|
|
131
|
-
|
|
133
|
+
yPath = y;
|
|
134
|
+
}
|
|
135
|
+
yPrev = y;
|
|
132
136
|
continue;
|
|
133
137
|
}
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
138
|
+
const midY = (yPrev + y) / 2;
|
|
139
|
+
const y0 = clamp(midY - curveHalf, yPath, y);
|
|
140
|
+
const y1 = clamp(midY + curveHalf, y0, y);
|
|
141
|
+
const controlY = (y0 + y1) / 2;
|
|
142
|
+
if (y0 > yPath)
|
|
137
143
|
d += ` L ${x} ${y0}`;
|
|
138
|
-
d += ` C ${x} ${
|
|
144
|
+
d += ` C ${x} ${controlY} ${xNext} ${controlY} ${xNext} ${y1}`;
|
|
139
145
|
x = xNext;
|
|
146
|
+
yPath = y1;
|
|
140
147
|
yPrev = y;
|
|
141
148
|
}
|
|
142
|
-
if (height >
|
|
149
|
+
if (height > yPath)
|
|
143
150
|
d += ` L ${x} ${height}`;
|
|
144
151
|
return d;
|
|
145
152
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ContextMenuThemeSlots } from '../theme/context-menu.js';
|
|
2
|
+
import type { ContextMenuPositioning, OverlayPortal } from '../utils/overlay.js';
|
|
2
3
|
import type { UiProp } from '../utils/ui.js';
|
|
3
4
|
export interface ContextMenuItemDef {
|
|
4
5
|
label: string;
|
|
@@ -7,12 +8,18 @@ export interface ContextMenuItemDef {
|
|
|
7
8
|
/** Styles this item for a delete/remove-style action (danger text, danger-tinted hover) - matches Dropdown's own `destructive` flag. */
|
|
8
9
|
destructive?: boolean;
|
|
9
10
|
onSelect?: () => void;
|
|
10
|
-
/**
|
|
11
|
+
/** Displays a keyboard shortcut hint. */
|
|
11
12
|
shortcut?: string;
|
|
13
|
+
/** Bind `shortcut` while this menu is open; activation follows the normal menu item click path. */
|
|
14
|
+
hotkey?: boolean;
|
|
12
15
|
}
|
|
13
16
|
type __VLS_Slots = ContextMenuSlots;
|
|
14
17
|
export interface ContextMenuProps {
|
|
15
18
|
items: ContextMenuItemDef[][];
|
|
19
|
+
/** Collision and offset controls for the menu anchored to the right-click point. */
|
|
20
|
+
positioning?: ContextMenuPositioning;
|
|
21
|
+
/** Teleport target, or `false` to render inline. Defaults to `body`. */
|
|
22
|
+
portal?: OverlayPortal;
|
|
16
23
|
ui?: UiProp<ContextMenuThemeSlots>;
|
|
17
24
|
}
|
|
18
25
|
export interface ContextMenuSlots {
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuSeparator, ContextMenuTrigger } from "reka-ui";
|
|
3
|
-
import { computed } from "vue";
|
|
3
|
+
import { computed, ref } from "vue";
|
|
4
|
+
import { vHotkey } from "../directives/hotkey";
|
|
5
|
+
import ShortcutHint from "../internal/ShortcutHint.vue";
|
|
4
6
|
import { contextMenuTheme } from "../theme/context-menu";
|
|
7
|
+
import { overlayPortalProps } from "../utils/overlay";
|
|
5
8
|
import { resolveSlot, useComponentTheme, useThemeBindings } from "../utils/ui";
|
|
6
9
|
import Icon from "./Icon.vue";
|
|
7
10
|
const props = defineProps({
|
|
8
11
|
items: { type: Array, required: true },
|
|
12
|
+
positioning: { type: Object, required: false },
|
|
13
|
+
portal: { type: [Boolean, String], required: false, skipCheck: true, default: void 0 },
|
|
9
14
|
ui: { type: Object, required: false }
|
|
10
15
|
});
|
|
11
16
|
defineSlots();
|
|
12
17
|
const theme = useComponentTheme("contextMenu", contextMenuTheme);
|
|
18
|
+
const open = ref(false);
|
|
13
19
|
const themeBindings = useThemeBindings();
|
|
14
20
|
const ui = computed(() => theme.value());
|
|
15
|
-
const contentProps = computed(() => resolveSlot(ui.value.content, props.ui?.content));
|
|
21
|
+
const contentProps = computed(() => ({ ...resolveSlot(ui.value.content, props.ui?.content), ...props.positioning }));
|
|
22
|
+
const portalProps = computed(() => overlayPortalProps(props.portal));
|
|
16
23
|
function itemPropsFor(item) {
|
|
17
24
|
return resolveSlot(theme.value({ destructive: item.destructive }).item, props.ui?.item);
|
|
18
25
|
}
|
|
@@ -20,20 +27,24 @@ function iconPropsFor(item) {
|
|
|
20
27
|
return resolveSlot(theme.value({ destructive: item.destructive }).icon, props.ui?.icon);
|
|
21
28
|
}
|
|
22
29
|
const separatorProps = computed(() => resolveSlot(ui.value.separator, props.ui?.separator));
|
|
30
|
+
function hotkeyFor(item) {
|
|
31
|
+
return item.hotkey && item.shortcut && !item.disabled ? { keys: item.shortcut, when: () => open.value } : void 0;
|
|
32
|
+
}
|
|
23
33
|
</script>
|
|
24
34
|
|
|
25
35
|
<template>
|
|
26
|
-
<ContextMenuRoot>
|
|
36
|
+
<ContextMenuRoot :open="open" @update:open="open = $event">
|
|
27
37
|
<ContextMenuTrigger as-child>
|
|
28
38
|
<slot />
|
|
29
39
|
</ContextMenuTrigger>
|
|
30
|
-
<ContextMenuPortal>
|
|
40
|
+
<ContextMenuPortal v-bind="portalProps">
|
|
31
41
|
<ContextMenuContent :data-selaras-theme="themeBindings['data-selaras-theme']" :data-selaras-mode="themeBindings['data-selaras-mode']" :style="themeBindings.style" v-bind="contentProps">
|
|
32
42
|
<template v-for="(group, groupIndex) in items" :key="groupIndex">
|
|
33
43
|
<ContextMenuSeparator v-if="groupIndex > 0" v-bind="separatorProps" />
|
|
34
44
|
<ContextMenuItem
|
|
35
45
|
v-for="(item, itemIndex) in group"
|
|
36
46
|
:key="itemIndex"
|
|
47
|
+
v-hotkey="hotkeyFor(item)"
|
|
37
48
|
:disabled="item.disabled"
|
|
38
49
|
v-bind="itemPropsFor(item)"
|
|
39
50
|
@select="item.onSelect?.()"
|
|
@@ -41,6 +52,7 @@ const separatorProps = computed(() => resolveSlot(ui.value.separator, props.ui?.
|
|
|
41
52
|
<Icon v-if="item.icon" :name="item.icon" v-bind="iconPropsFor(item)" />
|
|
42
53
|
<slot name="item" :item="item">
|
|
43
54
|
{{ item.label }}
|
|
55
|
+
<ShortcutHint :shortcut="item.shortcut" />
|
|
44
56
|
</slot>
|
|
45
57
|
</ContextMenuItem>
|
|
46
58
|
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ContextMenuThemeSlots } from '../theme/context-menu.js';
|
|
2
|
+
import type { ContextMenuPositioning, OverlayPortal } from '../utils/overlay.js';
|
|
2
3
|
import type { UiProp } from '../utils/ui.js';
|
|
3
4
|
export interface ContextMenuItemDef {
|
|
4
5
|
label: string;
|
|
@@ -7,12 +8,18 @@ export interface ContextMenuItemDef {
|
|
|
7
8
|
/** Styles this item for a delete/remove-style action (danger text, danger-tinted hover) - matches Dropdown's own `destructive` flag. */
|
|
8
9
|
destructive?: boolean;
|
|
9
10
|
onSelect?: () => void;
|
|
10
|
-
/**
|
|
11
|
+
/** Displays a keyboard shortcut hint. */
|
|
11
12
|
shortcut?: string;
|
|
13
|
+
/** Bind `shortcut` while this menu is open; activation follows the normal menu item click path. */
|
|
14
|
+
hotkey?: boolean;
|
|
12
15
|
}
|
|
13
16
|
type __VLS_Slots = ContextMenuSlots;
|
|
14
17
|
export interface ContextMenuProps {
|
|
15
18
|
items: ContextMenuItemDef[][];
|
|
19
|
+
/** Collision and offset controls for the menu anchored to the right-click point. */
|
|
20
|
+
positioning?: ContextMenuPositioning;
|
|
21
|
+
/** Teleport target, or `false` to render inline. Defaults to `body`. */
|
|
22
|
+
portal?: OverlayPortal;
|
|
16
23
|
ui?: UiProp<ContextMenuThemeSlots>;
|
|
17
24
|
}
|
|
18
25
|
export interface ContextMenuSlots {
|
|
@@ -2,7 +2,9 @@ import type { DateValue } from '@internationalized/date';
|
|
|
2
2
|
import type { DateRange } from 'reka-ui';
|
|
3
3
|
import type { VariantProps } from 'tailwind-variants';
|
|
4
4
|
import type { DatePickerThemeSlots } from '../theme/date-picker.js';
|
|
5
|
+
import type { RoundedArrowConfig } from '../utils/arrow.js';
|
|
5
6
|
import type { ColorRole } from '../utils/color-registry.js';
|
|
7
|
+
import type { OverlayPortal, OverlayPositioning } from '../utils/overlay.js';
|
|
6
8
|
import type { UiProp } from '../utils/ui.js';
|
|
7
9
|
import { Time } from '@internationalized/date';
|
|
8
10
|
import { datePickerTheme } from '../theme/date-picker.js';
|
|
@@ -73,7 +75,12 @@ export interface DatePickerProps {
|
|
|
73
75
|
activeColor?: ColorRole;
|
|
74
76
|
size?: DatePickerVariants['size'];
|
|
75
77
|
/** Shows a small pointer triangle connecting the panel to its trigger. */
|
|
76
|
-
|
|
78
|
+
/** Shows the pointer; an object configures its size, rounding, and edge clearance. */
|
|
79
|
+
arrow?: boolean | RoundedArrowConfig;
|
|
80
|
+
/** Positioning of the anchored calendar (the adaptive modal uses its own layout). */
|
|
81
|
+
positioning?: OverlayPositioning;
|
|
82
|
+
/** Teleport target for the anchored calendar, or `false` to render it inline. */
|
|
83
|
+
portal?: OverlayPortal;
|
|
77
84
|
/** Opts into the calendar's accessible small-screen modal presentation. It is selected when the calendar opens and held until close. */
|
|
78
85
|
adaptive?: boolean;
|
|
79
86
|
ui?: UiProp<DatePickerThemeSlots>;
|
|
@@ -158,11 +165,11 @@ type __VLS_Slots = {} & {
|
|
|
158
165
|
declare const __VLS_base: import("vue").DefineComponent<DatePickerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
159
166
|
"update:modelValue": (value: DateValue | DateRange | Time | undefined) => any;
|
|
160
167
|
"update:open": (value: boolean) => any;
|
|
161
|
-
"update:view": (view: "
|
|
168
|
+
"update:view": (view: "date" | "month" | "year") => any;
|
|
162
169
|
}, string, import("vue").PublicProps, Readonly<DatePickerProps> & Readonly<{
|
|
163
170
|
"onUpdate:modelValue"?: ((value: DateValue | DateRange | Time | undefined) => any) | undefined;
|
|
164
171
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
165
|
-
"onUpdate:view"?: ((view: "
|
|
172
|
+
"onUpdate:view"?: ((view: "date" | "month" | "year") => any) | undefined;
|
|
166
173
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
167
174
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
168
175
|
declare const _default: typeof __VLS_export;
|