@v1nt1248/3nclient-lib 0.3.22 → 0.3.23
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 +2 -0
- package/dist/components/index.d.ts +5 -1
- package/dist/components/ui3n-mobile-menu/types.d.ts +35 -0
- package/dist/components/ui3n-mobile-menu/ui3n-mobile-menu.vue.d.ts +20 -0
- package/dist/components/ui3n-mobile-menu-item/types.d.ts +21 -0
- package/dist/components/ui3n-mobile-menu-item/ui3n-mobile-menu-item.vue.d.ts +16 -0
- package/dist/index.d.ts +4 -0
- package/dist/style.css +1 -1
- package/dist/ui3n-components.d.ts +4 -0
- package/dist/ui3n-components.js +88 -2
- package/dist/variables.css +2 -0
- package/package.json +1 -1
- package/src/components/index.ts +16 -0
- package/src/components/ui3n-dialog/ui3n-dialog.vue +6 -6
- package/src/components/ui3n-mobile-menu/types.ts +38 -0
- package/src/components/ui3n-mobile-menu/ui3n-mobile-menu.vue +151 -0
- package/src/components/ui3n-mobile-menu-item/types.ts +23 -0
- package/src/components/ui3n-mobile-menu-item/ui3n-mobile-menu-item.vue +73 -0
|
@@ -29,6 +29,8 @@ import { default as Ui3nEditable } from './components/ui3n-editable/ui3n-editabl
|
|
|
29
29
|
import { default as Ui3nAutocomplete } from './components/ui3n-autocomplete/ui3n-autocomplete.vue';
|
|
30
30
|
import { default as Ui3nSlider } from './components/ui3n-slider/ui3n-slider.vue';
|
|
31
31
|
import { default as Ui3nSelector } from './components/ui3n-selector/ui3n-selector.vue';
|
|
32
|
+
import { default as Ui3nMobileMenu } from './components/ui3n-mobile-menu/ui3n-mobile-menu.vue';
|
|
33
|
+
import { default as Ui3nMobileMenuItem } from './components/ui3n-mobile-menu-item/ui3n-mobile-menu-item.vue';
|
|
32
34
|
import { default as Ui3nHtml } from './directives/ui3n-html';
|
|
33
35
|
import { default as Ui3nClickOutside } from './directives/ui3n-click-outside';
|
|
34
36
|
import { default as Ui3nResize } from './directives/ui3n-resize';
|
|
@@ -72,6 +74,8 @@ declare module 'vue' {
|
|
|
72
74
|
Ui3nText: typeof Ui3nText;
|
|
73
75
|
Ui3nVirtualScroll: typeof Ui3nVirtualScroll;
|
|
74
76
|
Ui3nTooltip: typeof Ui3nTooltip;
|
|
77
|
+
Ui3nMobileMenu: typeof Ui3nMobileMenu;
|
|
78
|
+
Ui3nMobileMenuItem: typeof Ui3nMobileMenuItem;
|
|
75
79
|
}
|
|
76
80
|
interface GlobalDirectives {
|
|
77
81
|
Ui3nHtml: typeof Ui3nHtml;
|
package/dist/ui3n-components.js
CHANGED
|
@@ -20596,10 +20596,96 @@ var Qu = /* @__PURE__ */ Q(/* @__PURE__ */ d({
|
|
|
20596
20596
|
item: "_item_11ric_91",
|
|
20597
20597
|
itemSelected: "_itemSelected_11ric_105",
|
|
20598
20598
|
itemDisabled: "_itemDisabled_11ric_109"
|
|
20599
|
+
} }]]), Rd = /* @__PURE__ */ Q(/* @__PURE__ */ d({
|
|
20600
|
+
__name: "ui3n-mobile-menu",
|
|
20601
|
+
props: {
|
|
20602
|
+
modelValue: { type: Boolean },
|
|
20603
|
+
width: {},
|
|
20604
|
+
withBlur: { type: Boolean }
|
|
20605
|
+
},
|
|
20606
|
+
emits: ["update:modelValue"],
|
|
20607
|
+
setup(e, { emit: n }) {
|
|
20608
|
+
M((e) => ({
|
|
20609
|
+
v5ec41730: f.value,
|
|
20610
|
+
v06b55ad7: p.value
|
|
20611
|
+
}));
|
|
20612
|
+
let l = e, d = n, f = i(() => l.width || "240px"), p = i(() => l.withBlur ? "2px" : "0");
|
|
20613
|
+
function m() {
|
|
20614
|
+
d("update:modelValue", !l.modelValue);
|
|
20615
|
+
}
|
|
20616
|
+
return (n, i) => (x(), s(t, null, [c("div", { class: g(n.$style.ui3nMobileMenu) }, [e.modelValue ? o("", !0) : (x(), a(Gl, {
|
|
20617
|
+
key: 0,
|
|
20618
|
+
type: "icon",
|
|
20619
|
+
class: g(n.$style.menuButton),
|
|
20620
|
+
color: "var(--color-bg-block-primary-default)",
|
|
20621
|
+
icon: "round-menu",
|
|
20622
|
+
"icon-color": "var(--color-icon-block-primary-default)",
|
|
20623
|
+
"icon-size": "32",
|
|
20624
|
+
onClick: B(m, ["stop", "prevent"])
|
|
20625
|
+
}, null, 8, ["class"])), u(r, { name: "slide-fade" }, {
|
|
20626
|
+
default: L(() => [e.modelValue ? (x(), s("div", {
|
|
20627
|
+
key: 0,
|
|
20628
|
+
class: g(n.$style.appMenu)
|
|
20629
|
+
}, [
|
|
20630
|
+
c("div", { class: g(n.$style.appMenuHeader) }, [T(n.$slots, "header")], 2),
|
|
20631
|
+
c("div", { class: g(n.$style.appMenuBody) }, [T(n.$slots, "menuBody")], 2),
|
|
20632
|
+
c("div", { class: g(n.$style.appMenuFooter) }, [T(n.$slots, "footer")], 2),
|
|
20633
|
+
u(Gl, {
|
|
20634
|
+
type: "icon",
|
|
20635
|
+
icon: "round-close",
|
|
20636
|
+
color: "transparent",
|
|
20637
|
+
"icon-color": "var(--color-icon-block-secondary-default)",
|
|
20638
|
+
"icon-size": "32",
|
|
20639
|
+
class: g(n.$style.closeBtn),
|
|
20640
|
+
onClick: B(m, ["stop", "prevent"])
|
|
20641
|
+
}, null, 8, ["class"])
|
|
20642
|
+
], 2)) : o("", !0)]),
|
|
20643
|
+
_: 3
|
|
20644
|
+
})], 2), e.modelValue ? (x(), s("div", {
|
|
20645
|
+
key: 0,
|
|
20646
|
+
class: g(n.$style.overlay)
|
|
20647
|
+
}, null, 2)) : o("", !0)], 64));
|
|
20648
|
+
}
|
|
20649
|
+
}), [["__cssModules", { $style: {
|
|
20650
|
+
ui3nMobileMenu: "_ui3nMobileMenu_b61ep_1",
|
|
20651
|
+
appMenu: "_appMenu_b61ep_6",
|
|
20652
|
+
appMenuHeader: "_appMenuHeader_b61ep_25",
|
|
20653
|
+
appMenuBody: "_appMenuBody_b61ep_30",
|
|
20654
|
+
appMenuFooter: "_appMenuFooter_b61ep_38",
|
|
20655
|
+
menuButton: "_menuButton_b61ep_43",
|
|
20656
|
+
closeBtn: "_closeBtn_b61ep_48",
|
|
20657
|
+
overlay: "_overlay_b61ep_57"
|
|
20658
|
+
} }]]), zd = /* @__PURE__ */ Q(/* @__PURE__ */ d({
|
|
20659
|
+
__name: "ui3n-mobile-menu-item",
|
|
20660
|
+
props: {
|
|
20661
|
+
item: {},
|
|
20662
|
+
isActive: { type: Boolean }
|
|
20663
|
+
},
|
|
20664
|
+
emits: ["selectItem"],
|
|
20665
|
+
setup(e, { emit: t }) {
|
|
20666
|
+
let n = e, r = t;
|
|
20667
|
+
async function i() {
|
|
20668
|
+
r("selectItem", n.item);
|
|
20669
|
+
}
|
|
20670
|
+
return (t, n) => (x(), s("div", {
|
|
20671
|
+
class: g([t.$style.menuItem, e.isActive && t.$style.menuItemSelected]),
|
|
20672
|
+
onClick: i
|
|
20673
|
+
}, [e.item.icon ? (x(), a(Hl, {
|
|
20674
|
+
key: 0,
|
|
20675
|
+
icon: e.item.icon,
|
|
20676
|
+
size: "20",
|
|
20677
|
+
color: "var(--color-icon-control-secondary-default)"
|
|
20678
|
+
}, null, 8, ["icon"])) : o("", !0), c("span", { class: g(t.$style.menuItemName) }, D(e.item.name), 3)], 2));
|
|
20679
|
+
}
|
|
20680
|
+
}), [["__cssModules", { $style: {
|
|
20681
|
+
menuItem: "_menuItem_1a8ao_2",
|
|
20682
|
+
menuItemName: "_menuItemName_1a8ao_13",
|
|
20683
|
+
menuItemSelected: "_menuItemSelected_1a8ao_19",
|
|
20684
|
+
bounceOnce: "_bounceOnce_1a8ao_1"
|
|
20599
20685
|
} }]]);
|
|
20600
20686
|
//#endregion
|
|
20601
20687
|
//#region src/composables/useDblClickHandler.ts
|
|
20602
|
-
function
|
|
20688
|
+
function Bd(e, t, n = 250) {
|
|
20603
20689
|
let r = 0, i = null;
|
|
20604
20690
|
function a(a) {
|
|
20605
20691
|
r++, i && clearTimeout(i), i = setTimeout(() => {
|
|
@@ -20609,4 +20695,4 @@ function Rd(e, t, n = 250) {
|
|
|
20609
20695
|
return { handleDblClick: a };
|
|
20610
20696
|
}
|
|
20611
20697
|
//#endregion
|
|
20612
|
-
export { Pd as Ui3nAutocomplete, ad as Ui3nBadge, od as Ui3nBreadcrumb, sd as Ui3nBreadcrumbs, Gl as Ui3nButton, Ou as Ui3nCheckbox, Kl as Ui3nChip, Ho as Ui3nClickOutside, Bu as Ui3nDialog, Lu as Ui3nDialogProvider, Jl as Ui3nDropFiles, Ad as Ui3nEditable, Xl as Ui3nEmoji, Bo as Ui3nHtml, Hl as Ui3nIcon, Ql as Ui3nInput, Su as Ui3nInputFile, ed as Ui3nList, Rl as Ui3nLongPress, Qu as Ui3nMenu, Au as Ui3nNotification, yd as Ui3nProgressCircular, md as Ui3nProgressLinear, Td as Ui3nRadio, Ed as Ui3nRadioGroup, Yo as Ui3nResize, es as Ui3nRipple, Ld as Ui3nSelector, Fd as Ui3nSlider, ud as Ui3nStepLineBar, ld as Ui3nSwitch, Pu as Ui3nTable, ju as Ui3nTableSortIcon, rd as Ui3nTabs, wu as Ui3nText, jl as Ui3nTitle, xd as Ui3nTooltip, nd as Ui3nVirtualScroll,
|
|
20698
|
+
export { Pd as Ui3nAutocomplete, ad as Ui3nBadge, od as Ui3nBreadcrumb, sd as Ui3nBreadcrumbs, Gl as Ui3nButton, Ou as Ui3nCheckbox, Kl as Ui3nChip, Ho as Ui3nClickOutside, Bu as Ui3nDialog, Lu as Ui3nDialogProvider, Jl as Ui3nDropFiles, Ad as Ui3nEditable, Xl as Ui3nEmoji, Bo as Ui3nHtml, Hl as Ui3nIcon, Ql as Ui3nInput, Su as Ui3nInputFile, ed as Ui3nList, Rl as Ui3nLongPress, Qu as Ui3nMenu, Rd as Ui3nMobileMenu, zd as Ui3nMobileMenuItem, Au as Ui3nNotification, yd as Ui3nProgressCircular, md as Ui3nProgressLinear, Td as Ui3nRadio, Ed as Ui3nRadioGroup, Yo as Ui3nResize, es as Ui3nRipple, Ld as Ui3nSelector, Fd as Ui3nSlider, ud as Ui3nStepLineBar, ld as Ui3nSwitch, Pu as Ui3nTable, ju as Ui3nTableSortIcon, rd as Ui3nTabs, wu as Ui3nText, jl as Ui3nTitle, xd as Ui3nTooltip, nd as Ui3nVirtualScroll, Bd as useDblClickHandler };
|
package/dist/variables.css
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
--spacing-l: 32px;
|
|
7
7
|
--spacing-xl: 40px;
|
|
8
8
|
--spacing-xxl: 48px;
|
|
9
|
+
--spacing-xxxl: 64px;
|
|
9
10
|
--white-inf: oklch(100% 0.000 0.0deg / 0.000);
|
|
10
11
|
--white-100: oklch(100% 0.000 0.0deg);
|
|
11
12
|
--white-4: oklch(98.5% 0.000 0.0deg / 0.040);
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
--font-20: 20px;
|
|
120
121
|
--font-24: 24px;
|
|
121
122
|
--font-32: 32px;
|
|
123
|
+
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
.default-theme {
|
package/package.json
CHANGED
package/src/components/index.ts
CHANGED
|
@@ -112,6 +112,14 @@ import type {
|
|
|
112
112
|
Ui3nSelectorSlots,
|
|
113
113
|
Ui3nSelectorItemDisplayingFunction,
|
|
114
114
|
} from './ui3n-selector/types';
|
|
115
|
+
import Ui3nMobileMenu from './ui3n-mobile-menu/ui3n-mobile-menu.vue';
|
|
116
|
+
import type { Ui3nMobileMenuProps, Ui3nMobileMenuEmits, Ui3nMobileMenuSlots } from './ui3n-mobile-menu/types';
|
|
117
|
+
import Ui3nMobileMenuItem from './ui3n-mobile-menu-item/ui3n-mobile-menu-item.vue';
|
|
118
|
+
import type {
|
|
119
|
+
Ui3nMobileMenuItemBase,
|
|
120
|
+
Ui3nMobileMenuItemProps,
|
|
121
|
+
Ui3nMobileMenuItemEmits,
|
|
122
|
+
} from './ui3n-mobile-menu-item/types';
|
|
115
123
|
|
|
116
124
|
export {
|
|
117
125
|
Ui3nIcon,
|
|
@@ -233,4 +241,12 @@ export {
|
|
|
233
241
|
Ui3nSelectorSlots,
|
|
234
242
|
Ui3nSelectorOptionBase,
|
|
235
243
|
Ui3nSelectorItemDisplayingFunction,
|
|
244
|
+
Ui3nMobileMenu,
|
|
245
|
+
Ui3nMobileMenuProps,
|
|
246
|
+
Ui3nMobileMenuEmits,
|
|
247
|
+
Ui3nMobileMenuSlots,
|
|
248
|
+
Ui3nMobileMenuItem,
|
|
249
|
+
Ui3nMobileMenuItemBase,
|
|
250
|
+
Ui3nMobileMenuItemProps,
|
|
251
|
+
Ui3nMobileMenuItemEmits,
|
|
236
252
|
};
|
|
@@ -134,12 +134,12 @@
|
|
|
134
134
|
v-on="
|
|
135
135
|
draggable
|
|
136
136
|
? {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
dragstart: onDragstart,
|
|
138
|
+
mousedown: onMousedown,
|
|
139
|
+
mouseup: onMouseup,
|
|
140
|
+
mousemove: onMousemove,
|
|
141
|
+
keydown: onKeydown,
|
|
142
|
+
}
|
|
143
143
|
: { keydown: onKeydown }
|
|
144
144
|
"
|
|
145
145
|
>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { VNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Menu component properties
|
|
5
|
+
*/
|
|
6
|
+
export interface Ui3nMobileMenuProps {
|
|
7
|
+
modelValue: boolean;
|
|
8
|
+
width?: string;
|
|
9
|
+
withBlur?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Menu component emits
|
|
14
|
+
*/
|
|
15
|
+
export interface Ui3nMobileMenuEmits {
|
|
16
|
+
/**
|
|
17
|
+
* Emitted when model value updates
|
|
18
|
+
*/
|
|
19
|
+
(event: 'update:modelValue', value: boolean): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Menu component slots
|
|
24
|
+
*/
|
|
25
|
+
export interface Ui3nMobileMenuSlots {
|
|
26
|
+
/**
|
|
27
|
+
* Menu Header slot - section to add custom data on top of the menu
|
|
28
|
+
*/
|
|
29
|
+
header: () => VNode;
|
|
30
|
+
/**
|
|
31
|
+
* Menu body slot - The section is where your menu items are placed
|
|
32
|
+
*/
|
|
33
|
+
menuBody: () => VNode;
|
|
34
|
+
/**
|
|
35
|
+
* Menu footer slot - section to add custm data on the bottom of menu
|
|
36
|
+
*/
|
|
37
|
+
footer: () => VNode;
|
|
38
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Ui3nMobileMenuProps, Ui3nMobileMenuEmits, Ui3nMobileMenuSlots } from './types';
|
|
4
|
+
import Ui3nButton from '../ui3n-button/ui3n-button.vue';
|
|
5
|
+
|
|
6
|
+
const props = defineProps<Ui3nMobileMenuProps>();
|
|
7
|
+
const emits = defineEmits<Ui3nMobileMenuEmits>();
|
|
8
|
+
defineSlots<Ui3nMobileMenuSlots>();
|
|
9
|
+
|
|
10
|
+
const widthCss = computed(() => props.width || '240px');
|
|
11
|
+
const blurValue = computed(() => (props.withBlur ? '2px' : '0'));
|
|
12
|
+
|
|
13
|
+
function toggleMenu() {
|
|
14
|
+
emits('update:modelValue', !props.modelValue);
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div :class="$style.ui3nMobileMenu">
|
|
20
|
+
<ui3n-button
|
|
21
|
+
v-if="!modelValue"
|
|
22
|
+
type="icon"
|
|
23
|
+
:class="$style.menuButton"
|
|
24
|
+
color="var(--color-bg-block-primary-default)"
|
|
25
|
+
icon="round-menu"
|
|
26
|
+
icon-color="var(--color-icon-block-primary-default)"
|
|
27
|
+
icon-size="32"
|
|
28
|
+
@click.stop.prevent="toggleMenu"
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<transition name="slide-fade">
|
|
32
|
+
<div
|
|
33
|
+
v-if="modelValue"
|
|
34
|
+
:class="$style.appMenu"
|
|
35
|
+
>
|
|
36
|
+
<div :class="$style.appMenuHeader">
|
|
37
|
+
<slot name="header" />
|
|
38
|
+
</div>
|
|
39
|
+
<div :class="$style.appMenuBody">
|
|
40
|
+
<slot name="menuBody" />
|
|
41
|
+
</div>
|
|
42
|
+
<div :class="$style.appMenuFooter">
|
|
43
|
+
<slot name="footer" />
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<ui3n-button
|
|
47
|
+
type="icon"
|
|
48
|
+
icon="round-close"
|
|
49
|
+
color="transparent"
|
|
50
|
+
icon-color="var(--color-icon-block-secondary-default)"
|
|
51
|
+
icon-size="32"
|
|
52
|
+
:class="$style.closeBtn"
|
|
53
|
+
@click.stop.prevent="toggleMenu"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
</transition>
|
|
57
|
+
</div>
|
|
58
|
+
<div
|
|
59
|
+
v-if="modelValue"
|
|
60
|
+
:class="$style.overlay"
|
|
61
|
+
/>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<style lang="scss" module>
|
|
65
|
+
@use '../../assets/styles/mixins' as mixins;
|
|
66
|
+
.ui3nMobileMenu {
|
|
67
|
+
--ui3n-menu-width-custom: v-bind(widthCss);
|
|
68
|
+
|
|
69
|
+
width: max-content;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.appMenu {
|
|
73
|
+
position: fixed;
|
|
74
|
+
top: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
width: var(--ui3n-menu-width-custom);
|
|
77
|
+
max-width: 80vw;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
justify-content: flex-start;
|
|
81
|
+
align-items: stretch;
|
|
82
|
+
min-height: 100dvh;
|
|
83
|
+
max-height: 100dvh;
|
|
84
|
+
color: var(--color-text-block-primary-default);
|
|
85
|
+
background-color: var(--color-bg-block-primary-default);
|
|
86
|
+
overflow-x: hidden;
|
|
87
|
+
overflow-y: auto;
|
|
88
|
+
z-index: 1050;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.appMenuHeader {
|
|
92
|
+
position: relative;
|
|
93
|
+
width: 100%;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.appMenuBody {
|
|
97
|
+
position: relative;
|
|
98
|
+
width: 100%;
|
|
99
|
+
flex-grow: 1;
|
|
100
|
+
overflow-x: hidden;
|
|
101
|
+
overflow-y: auto;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.appMenuFooter {
|
|
105
|
+
position: relative;
|
|
106
|
+
width: 100%;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.menuButton {
|
|
110
|
+
min-width: 48px !important;
|
|
111
|
+
height: 48px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.closeBtn {
|
|
115
|
+
position: fixed;
|
|
116
|
+
min-width: 48px !important;
|
|
117
|
+
height: 48px;
|
|
118
|
+
top: 8px;
|
|
119
|
+
left: calc(var(--ui3n-menu-width-custom) + 8px);
|
|
120
|
+
z-index: 1005;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.overlay {
|
|
124
|
+
position: fixed;
|
|
125
|
+
inset: 0;
|
|
126
|
+
background-color: oklch(from var(--color-bg-block-primary-default) calc(l * 0.1) c h / 0.5);
|
|
127
|
+
backdrop-filter: blur(v-bind(blurValue));
|
|
128
|
+
z-index: 1000;
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
131
|
+
|
|
132
|
+
<style lang="scss">
|
|
133
|
+
.slide-fade-enter-active,
|
|
134
|
+
.slide-fade-leave-active {
|
|
135
|
+
transition:
|
|
136
|
+
transform 0.2s ease-in-out,
|
|
137
|
+
opacity 0.2s ease-in-out;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.slide-fade-enter-from,
|
|
141
|
+
.slide-fade-leave-to {
|
|
142
|
+
transform: translateX(calc(var(--ui3n-menu-width-custom) * -1));
|
|
143
|
+
opacity: 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.slide-fade-enter-to,
|
|
147
|
+
.slide-fade-leave-from {
|
|
148
|
+
transform: translateX(0);
|
|
149
|
+
opacity: 1;
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface Ui3nMobileMenuItemBase {
|
|
2
|
+
id: string | number;
|
|
3
|
+
name: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Menu Item component properties
|
|
9
|
+
*/
|
|
10
|
+
export interface Ui3nMobileMenuItemProps<T extends Ui3nMobileMenuItemBase> {
|
|
11
|
+
item: T;
|
|
12
|
+
isActive?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Menu Item component emits
|
|
17
|
+
*/
|
|
18
|
+
export interface Ui3nMobileMenuItemEmits<T extends Ui3nMobileMenuItemBase> {
|
|
19
|
+
/**
|
|
20
|
+
* Emitted when an item is selected on the menu
|
|
21
|
+
*/
|
|
22
|
+
(event: 'selectItem', item: T): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts" setup generic="T extends Ui3nMobileMenuItemBase">
|
|
2
|
+
import type { Ui3nMobileMenuItemBase, Ui3nMobileMenuItemProps, Ui3nMobileMenuItemEmits } from './types';
|
|
3
|
+
import Ui3nIcon from '../ui3n-icon/ui3n-icon.vue';
|
|
4
|
+
|
|
5
|
+
const props = defineProps<Ui3nMobileMenuItemProps<T>>();
|
|
6
|
+
const emits = defineEmits<Ui3nMobileMenuItemEmits<T>>();
|
|
7
|
+
|
|
8
|
+
async function selectMenuItem() {
|
|
9
|
+
emits('selectItem', props.item);
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div
|
|
15
|
+
:class="[$style.menuItem, isActive && $style.menuItemSelected]"
|
|
16
|
+
@click="selectMenuItem"
|
|
17
|
+
>
|
|
18
|
+
<ui3n-icon
|
|
19
|
+
v-if="item.icon"
|
|
20
|
+
:icon="item.icon"
|
|
21
|
+
size="20"
|
|
22
|
+
color="var(--color-icon-control-secondary-default)"
|
|
23
|
+
/>
|
|
24
|
+
<span :class="$style.menuItemName">
|
|
25
|
+
{{ item.name }}
|
|
26
|
+
</span>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<style lang="scss" module>
|
|
31
|
+
@use '../../assets/styles/mixins' as mixins;
|
|
32
|
+
|
|
33
|
+
.menuItem {
|
|
34
|
+
display: flex;
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: var(--spacing-xxl);
|
|
37
|
+
border-radius: var(--spacing-s);
|
|
38
|
+
justify-content: flex-start;
|
|
39
|
+
align-items: center;
|
|
40
|
+
column-gap: var(--spacing-s);
|
|
41
|
+
padding: 0 var(--spacing-s);
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
|
|
44
|
+
.menuItemName {
|
|
45
|
+
font-size: var(--font-14);
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
line-height: var(--font-20);
|
|
48
|
+
color: var(--color-text-control-primary-default);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&:hover,
|
|
52
|
+
&.menuItemSelected {
|
|
53
|
+
background-color: var(--color-bg-control-primary-hover);
|
|
54
|
+
|
|
55
|
+
& > div {
|
|
56
|
+
color: var(--color-icon-control-accent-default);
|
|
57
|
+
animation: bounceOnce 0.4s ease-in-out forwards;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@keyframes bounceOnce {
|
|
63
|
+
0% {
|
|
64
|
+
transform: scale(1);
|
|
65
|
+
}
|
|
66
|
+
50% {
|
|
67
|
+
transform: scale(1.25); /* Пик увеличения */
|
|
68
|
+
}
|
|
69
|
+
100% {
|
|
70
|
+
transform: scale(1); /* Финал анимации */
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
</style>
|