@flyanra/vue-core 1.0.2 → 1.2.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/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.types.d.ts +14 -1
- package/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.vue.d.ts +10 -4
- package/dist/types/composables/UseLocaleInjector.d.ts +7 -1
- package/dist/types/composables/index.d.ts +3 -1
- package/dist/types/composables/useSidebarActiveIndex.d.ts +66 -0
- package/package.json +3 -1
- package/src/components/basic/fly-button/FlyButton.types.ts +28 -28
- package/src/components/basic/fly-button/FlyButton.vue +178 -178
- package/src/components/basic/typography/FlyCollapseTitleRenderer.vue +46 -46
- package/src/components/feedback/tooltip/FlyInfoTooltip.vue +49 -49
- package/src/components/feedback/tooltip/FlyTooltip.element.scss +4 -4
- package/src/components/feedback/tooltip/FlyTooltip.vue +60 -60
- package/src/components/form/form.utils.ts +72 -72
- package/src/components/form/index.ts +6 -6
- package/src/components/form/input-renderers/boolean/FlyBoolean.vue +48 -48
- package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.vue +48 -48
- package/src/components/form/input-renderers/form-item-renderer/index.ts +4 -4
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.types.ts +3 -3
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.utils.ts +221 -221
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.vue +75 -75
- package/src/components/form/input-renderers/form-schema-renderer/UseFormSchemaRenderer.ts +97 -97
- package/src/components/form/input-renderers/input-renderer/FlyInputRenderer.vue +49 -49
- package/src/components/form/input-renderers/input-renderer/index.ts +4 -4
- package/src/components/form/input-renderers/input-renderer.utils.ts +18 -18
- package/src/components/form/input-renderers/number/FlyNumber.vue +64 -64
- package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.types.ts +15 -15
- package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.vue +99 -99
- package/src/components/form/input-renderers/select/FlySelect.scss +1 -1
- package/src/components/form/input-renderers/select/FlySelect.utils.ts +37 -37
- package/src/components/form/input-renderers/text/FlyText.vue +70 -70
- package/src/components/form/input-renderers/value-unit/FlyValueUnit.vue +102 -102
- package/src/components/form/input-validators.ts +99 -99
- package/src/components/general/fly-icon-v2/FlyIconV2.types.ts +6 -6
- package/src/components/general/fly-icon-v2/FlyIconV2.vue +17 -17
- package/src/components/general/fly-icon-v2/index.ts +6 -6
- package/src/components/general/index.ts +5 -5
- package/src/components/index.ts +7 -7
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.types.ts +8 -8
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebarItem.vue +55 -55
- package/src/components/navigation/menu/fly-sidebar/FlySidebar.types.ts +49 -36
- package/src/components/navigation/menu/fly-sidebar/FlySidebar.vue +146 -151
- package/src/components/navigation/menu/fly-sidebar/FlySidebarNode.vue +47 -47
- package/src/composables/UseLocaleInjector.ts +37 -18
- package/src/composables/index.ts +4 -1
- package/src/composables/useSidebarActiveIndex.ts +103 -0
- package/src/styles/_scss-tokens.scss +71 -71
- package/src/styles/element/mixins/collapse.scss +61 -61
- package/src/styles/element/overrides/form.scss +121 -121
- package/src/styles/element/overrides/message-box.scss +2 -2
- package/src/styles/element/overrides/radio.scss +2 -2
- package/src/styles/element/overrides/select.scss +9 -9
- package/src/styles/index.scss +1 -1
- package/src/styles/tokens.scss +1 -0
- package/src/utils/index.ts +2 -2
- package/src/utils/pure-functions.ts +15 -15
- package/src/utils/validators.ts +81 -81
|
@@ -21,9 +21,22 @@ export type T_FlySidebarGroup = {
|
|
|
21
21
|
export type T_FlySidebarNode = T_FlySidebarItem | T_FlySidebarSubMenu | T_FlySidebarGroup;
|
|
22
22
|
export type T_FlySidebar = T_FlySidebarNode[];
|
|
23
23
|
export type T_FlySidebarProps = {
|
|
24
|
-
isCollapsed?: boolean;
|
|
25
24
|
router?: boolean;
|
|
26
25
|
defaultActive?: string;
|
|
27
26
|
menu: T_FlySidebarNode[];
|
|
28
27
|
height?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Controls the collapsed state of the sidebar.
|
|
30
|
+
* Must be bound with `v-model:collapsed` — a plain `:collapsed` binding
|
|
31
|
+
* is one-way only and will not reflect toggle actions back to the parent.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const sidebarCollapsed = useStorage('sidebar-collapsed', false)
|
|
36
|
+
* ```
|
|
37
|
+
* ```html
|
|
38
|
+
* <FlySidebar v-model:collapsed="sidebarCollapsed" ... />
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
collapsed?: boolean;
|
|
29
42
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import './FlySidebar.element.scss';
|
|
2
2
|
import type { T_FlySidebarProps } from './FlySidebar.types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
type __VLS_Props = T_FlySidebarProps;
|
|
4
|
+
type __VLS_ModelProps = {
|
|
5
|
+
'collapsed'?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
"update:collapsed": (value: boolean) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
11
|
+
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
13
|
declare const _default: typeof __VLS_export;
|
|
8
14
|
export default _default;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import type { MaybeRef } from 'vue';
|
|
1
2
|
import type { Locale } from '@flyanra/js-utils/locales';
|
|
2
3
|
import type { ComposerTranslation } from 'vue-i18n';
|
|
3
|
-
type T_LocaleInjector = {
|
|
4
|
+
export type T_LocaleInjector = {
|
|
4
5
|
t: ComposerTranslation;
|
|
5
6
|
locale: Locale;
|
|
6
7
|
};
|
|
8
|
+
type I18nLike = {
|
|
9
|
+
t: ComposerTranslation;
|
|
10
|
+
locale: MaybeRef<Locale>;
|
|
11
|
+
};
|
|
12
|
+
export declare function initLocaleInjector(i18n: I18nLike): void;
|
|
7
13
|
export declare function UseLocaleInjector(): T_LocaleInjector;
|
|
8
14
|
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import type { T_FlySidebar } from '../components';
|
|
3
|
+
/**
|
|
4
|
+
* Minimal route shape required by `useSidebarActiveIndex`.
|
|
5
|
+
*
|
|
6
|
+
* You can pass your full route objects directly — only these fields are read.
|
|
7
|
+
* `meta.sidebarActiveIndex` is the route **name** of the sidebar item that
|
|
8
|
+
* should stay highlighted while on this route (see composable docs below).
|
|
9
|
+
*/
|
|
10
|
+
interface RouteItem {
|
|
11
|
+
name?: string;
|
|
12
|
+
path: string;
|
|
13
|
+
meta?: {
|
|
14
|
+
/** Route name of the sidebar item to keep active on this route. */
|
|
15
|
+
sidebarActiveIndex?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolves the correct active sidebar index for Element Plus menus in router mode.
|
|
20
|
+
*
|
|
21
|
+
* **Resolution order** (first match wins):
|
|
22
|
+
* 1. **Exact path match** — `route.path` matches a menu item's `index` directly.
|
|
23
|
+
* 2. **`sidebarActiveIndex` meta** — the current route's `meta.sidebarActiveIndex`
|
|
24
|
+
* names which sidebar route should appear active. Use this for pages that are
|
|
25
|
+
* not listed in the sidebar (e.g. edit, create, or detail views).
|
|
26
|
+
* 3. **Longest static-prefix fallback** — strips dynamic segments (`:id`) and
|
|
27
|
+
* picks the menu item whose path is the longest prefix of the current path.
|
|
28
|
+
* This is a best-effort catch-all for any unhandled cases.
|
|
29
|
+
*
|
|
30
|
+
* > **Note:** Only one level of submenus is flattened. Deeply nested menu trees
|
|
31
|
+
* > (submenu inside a submenu) are not supported.
|
|
32
|
+
*
|
|
33
|
+
* @param menuItems - The sidebar menu tree passed to `FlySidebar`. Each leaf item
|
|
34
|
+
* must have `index` set to a route path (e.g. `/config/list`). Submenu items
|
|
35
|
+
* must have `type: 'submenu'` and a `children` array of leaf items.
|
|
36
|
+
* Accepts a plain value, `ref`, or `computed`.
|
|
37
|
+
*
|
|
38
|
+
* @param allRoutes - Flat list of all application routes. Only used to resolve a
|
|
39
|
+
* `sidebarActiveIndex` route name back to its path (resolution step 2).
|
|
40
|
+
* Each entry needs at minimum `{ name, path }`.
|
|
41
|
+
* Accepts a plain array, `ref`, or `computed`.
|
|
42
|
+
*
|
|
43
|
+
* @returns `ComputedRef<string>` — bind directly to `:default-active` on
|
|
44
|
+
* `FlySidebar` or `el-menu`.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* // In your sidebar component setup:
|
|
49
|
+
* const activeIndex = useSidebarActiveIndex(menuItems, router.getRoutes())
|
|
50
|
+
* ```
|
|
51
|
+
* ```html
|
|
52
|
+
* <!-- In your sidebar template: -->
|
|
53
|
+
* <FlySidebar :default-active="activeIndex" ... />
|
|
54
|
+
* ```
|
|
55
|
+
* ```ts
|
|
56
|
+
* // In a route that is NOT listed in the sidebar (e.g. an edit page),
|
|
57
|
+
* // tell the composable which sidebar item should stay highlighted:
|
|
58
|
+
* {
|
|
59
|
+
* name: 'ConfigEdit',
|
|
60
|
+
* path: '/config/:id/edit',
|
|
61
|
+
* meta: { sidebarActiveIndex: 'ConfigList' }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function useSidebarActiveIndex(menuItems: MaybeRefOrGetter<T_FlySidebar>, allRoutes: MaybeRefOrGetter<RouteItem[]>): import("vue").ComputedRef<string>;
|
|
66
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flyanra/vue-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Source-distributed Vue component library for Vite and Nuxt consumers.",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
"@changesets/cli": "^2.30.0",
|
|
99
99
|
"@eslint/js": "^10.0.1",
|
|
100
100
|
"@flyanra/js-utils": "^1.5.0",
|
|
101
|
+
"@iconify-json/mdi": "^1.2.3",
|
|
101
102
|
"@iconify-json/ri": "^1.2.10",
|
|
102
103
|
"@jamescoyle/vue-icon": "^0.1.2",
|
|
103
104
|
"@mdi/js": "^7.4.47",
|
|
@@ -134,6 +135,7 @@
|
|
|
134
135
|
"typescript": "~6.0.2",
|
|
135
136
|
"typescript-eslint": "^8.58.2",
|
|
136
137
|
"unplugin-icons": "^23.0.1",
|
|
138
|
+
"unplugin-vue-components": "^32.1.0",
|
|
137
139
|
"vite": "^8.0.4",
|
|
138
140
|
"vitest": "^4.1.4",
|
|
139
141
|
"vue": "^3.5.32",
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import type { ButtonType, ElButton, UseTooltipProps } from 'element-plus'
|
|
2
|
-
|
|
3
|
-
import type { T_FlyIconV2Props } from '../../general'
|
|
4
|
-
|
|
5
|
-
export type FlyButtonIconPosition = 'left' | 'right'
|
|
6
|
-
|
|
7
|
-
export type FlyButtonSizes = InstanceType<typeof ElButton>['$props']['size']
|
|
8
|
-
export type FlyButtonTypes = ButtonType
|
|
9
|
-
|
|
10
|
-
export type FlyButtonProps = {
|
|
11
|
-
active?: boolean
|
|
12
|
-
appButtonClass?: string
|
|
13
|
-
aspect1?: boolean
|
|
14
|
-
/**
|
|
15
|
-
* Test
|
|
16
|
-
*/
|
|
17
|
-
clipRound?: boolean
|
|
18
|
-
full?: boolean
|
|
19
|
-
icon?: T_FlyIconV2Props['icon']
|
|
20
|
-
iconPosition?: FlyButtonIconPosition
|
|
21
|
-
imageUrl?: string
|
|
22
|
-
label?: string
|
|
23
|
-
size?: FlyButtonSizes
|
|
24
|
-
stop?: boolean
|
|
25
|
-
title?: string
|
|
26
|
-
tooltip?: UseTooltipProps
|
|
27
|
-
type?: FlyButtonTypes
|
|
28
|
-
}
|
|
1
|
+
import type { ButtonType, ElButton, UseTooltipProps } from 'element-plus'
|
|
2
|
+
|
|
3
|
+
import type { T_FlyIconV2Props } from '../../general'
|
|
4
|
+
|
|
5
|
+
export type FlyButtonIconPosition = 'left' | 'right'
|
|
6
|
+
|
|
7
|
+
export type FlyButtonSizes = InstanceType<typeof ElButton>['$props']['size']
|
|
8
|
+
export type FlyButtonTypes = ButtonType
|
|
9
|
+
|
|
10
|
+
export type FlyButtonProps = {
|
|
11
|
+
active?: boolean
|
|
12
|
+
appButtonClass?: string
|
|
13
|
+
aspect1?: boolean
|
|
14
|
+
/**
|
|
15
|
+
* Test
|
|
16
|
+
*/
|
|
17
|
+
clipRound?: boolean
|
|
18
|
+
full?: boolean
|
|
19
|
+
icon?: T_FlyIconV2Props['icon']
|
|
20
|
+
iconPosition?: FlyButtonIconPosition
|
|
21
|
+
imageUrl?: string
|
|
22
|
+
label?: string
|
|
23
|
+
size?: FlyButtonSizes
|
|
24
|
+
stop?: boolean
|
|
25
|
+
title?: string
|
|
26
|
+
tooltip?: UseTooltipProps
|
|
27
|
+
type?: FlyButtonTypes
|
|
28
|
+
}
|
|
@@ -1,178 +1,178 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="fly-button" :class="[{ full }, appButtonClass]">
|
|
3
|
-
<FlyTooltip
|
|
4
|
-
:tooltip="{
|
|
5
|
-
// effect: 'dark',
|
|
6
|
-
content: title,
|
|
7
|
-
placement: tooltip?.placement ?? 'bottom',
|
|
8
|
-
disabled: !!tooltip?.disabled || isEmpty(title)
|
|
9
|
-
}"
|
|
10
|
-
>
|
|
11
|
-
<el-button
|
|
12
|
-
v-bind="additionalButtonBindingValues"
|
|
13
|
-
:class="[{ active, 'aspect-1': aspect1 }]"
|
|
14
|
-
@click="handleClick"
|
|
15
|
-
>
|
|
16
|
-
<FlyIconV2
|
|
17
|
-
v-if="icon && resolvedIconPosition === 'left'"
|
|
18
|
-
:icon="icon"
|
|
19
|
-
:class="[{ 'left-icon': slots.default }]"
|
|
20
|
-
/>
|
|
21
|
-
|
|
22
|
-
<slot></slot>
|
|
23
|
-
|
|
24
|
-
<FlyIconV2
|
|
25
|
-
v-if="icon && resolvedIconPosition === 'right'"
|
|
26
|
-
:icon="icon"
|
|
27
|
-
:class="[{ 'right-icon': slots.default }]"
|
|
28
|
-
/>
|
|
29
|
-
|
|
30
|
-
<span v-if="imageUrl" class="btn-image" :class="[{ 'clip-round': clipRound }]">
|
|
31
|
-
<img :src="imageUrl" />
|
|
32
|
-
</span>
|
|
33
|
-
</el-button>
|
|
34
|
-
</FlyTooltip>
|
|
35
|
-
</div>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<script lang="ts" setup>
|
|
39
|
-
import { computed, useAttrs, useSlots } from 'vue'
|
|
40
|
-
|
|
41
|
-
import { ElButton } from 'element-plus'
|
|
42
|
-
|
|
43
|
-
import { isEmpty } from 'lodash-es'
|
|
44
|
-
|
|
45
|
-
import FlyTooltip from '../../feedback/tooltip/FlyTooltip.vue'
|
|
46
|
-
import FlyIconV2 from '../../general/fly-icon-v2/FlyIconV2.vue'
|
|
47
|
-
|
|
48
|
-
import './FlyButton.element.scss'
|
|
49
|
-
import type { FlyButtonIconPosition, FlyButtonProps } from './FlyButton.types'
|
|
50
|
-
|
|
51
|
-
const attrs = useAttrs()
|
|
52
|
-
const slots = useSlots()
|
|
53
|
-
const emit = defineEmits(['click'])
|
|
54
|
-
|
|
55
|
-
defineOptions({
|
|
56
|
-
inheritAttrs: false
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
const props = withDefaults(defineProps<FlyButtonProps>(), {
|
|
60
|
-
active: false,
|
|
61
|
-
aspect1: false,
|
|
62
|
-
clipRound: false,
|
|
63
|
-
full: false,
|
|
64
|
-
stop: false,
|
|
65
|
-
tooltip: () => ({
|
|
66
|
-
placement: 'bottom',
|
|
67
|
-
disabled: false
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const additionalButtonBindingValues = computed(() => {
|
|
72
|
-
const { type, size } = props
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
...attrs,
|
|
76
|
-
size,
|
|
77
|
-
type
|
|
78
|
-
} as object
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const resolvedIconPosition = computed<FlyButtonIconPosition>(() => props.iconPosition || 'left')
|
|
82
|
-
|
|
83
|
-
function handleClick(e: MouseEvent) {
|
|
84
|
-
/**
|
|
85
|
-
* Stop the event propagation if the stop prop is set to true
|
|
86
|
-
*/
|
|
87
|
-
if (props.stop) {
|
|
88
|
-
e.stopPropagation()
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
emit('click', e)
|
|
92
|
-
}
|
|
93
|
-
</script>
|
|
94
|
-
|
|
95
|
-
<style lang="scss" scoped>
|
|
96
|
-
.fly-button {
|
|
97
|
-
pointer-events: auto;
|
|
98
|
-
|
|
99
|
-
&.full button {
|
|
100
|
-
width: 100%;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
:deep(.el-button) {
|
|
104
|
-
&.active {
|
|
105
|
-
/* 1px ring stile */
|
|
106
|
-
box-shadow: 0 0 0 1px var(--anra-white);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.fly-icon {
|
|
110
|
-
svg {
|
|
111
|
-
width: calc(1em + 2px);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
:deep(.fly-icon.left-icon) {
|
|
117
|
-
padding-inline-end: 0.25rem;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
:deep(.fly-icon.right-icon) {
|
|
121
|
-
padding-inline-start: 0.25rem;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.btn-image {
|
|
125
|
-
display: flex;
|
|
126
|
-
align-items: center;
|
|
127
|
-
justify-content: center;
|
|
128
|
-
position: absolute;
|
|
129
|
-
top: 0;
|
|
130
|
-
left: 0;
|
|
131
|
-
right: 0;
|
|
132
|
-
bottom: 0;
|
|
133
|
-
|
|
134
|
-
&.clip-round {
|
|
135
|
-
-webkit-box-align: stretch;
|
|
136
|
-
align-items: stretch;
|
|
137
|
-
border-radius: 50%;
|
|
138
|
-
box-sizing: content-box;
|
|
139
|
-
display: flex;
|
|
140
|
-
flex-direction: column;
|
|
141
|
-
-webkit-box-pack: center;
|
|
142
|
-
justify-content: center;
|
|
143
|
-
overflow: hidden;
|
|
144
|
-
|
|
145
|
-
img {
|
|
146
|
-
border: 5px solid transparent;
|
|
147
|
-
border-radius: 50%;
|
|
148
|
-
display: flex;
|
|
149
|
-
width: 100%;
|
|
150
|
-
height: 100%;
|
|
151
|
-
flex: 1 1 100%;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
</style>
|
|
157
|
-
|
|
158
|
-
<style lang="scss">
|
|
159
|
-
@use './FlyButton.mixins.scss' as button;
|
|
160
|
-
|
|
161
|
-
.el-button-group {
|
|
162
|
-
display: flex;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
html.dark {
|
|
166
|
-
button.el-button {
|
|
167
|
-
@include button.fly-button-overrides-dark;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
button.el-button {
|
|
172
|
-
position: relative;
|
|
173
|
-
overflow: hidden;
|
|
174
|
-
transition: 0.1s;
|
|
175
|
-
text-wrap: balance;
|
|
176
|
-
@include button.fly-button-overrides;
|
|
177
|
-
}
|
|
178
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="fly-button" :class="[{ full }, appButtonClass]">
|
|
3
|
+
<FlyTooltip
|
|
4
|
+
:tooltip="{
|
|
5
|
+
// effect: 'dark',
|
|
6
|
+
content: title,
|
|
7
|
+
placement: tooltip?.placement ?? 'bottom',
|
|
8
|
+
disabled: !!tooltip?.disabled || isEmpty(title)
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
<el-button
|
|
12
|
+
v-bind="additionalButtonBindingValues"
|
|
13
|
+
:class="[{ active, 'aspect-1': aspect1 }]"
|
|
14
|
+
@click="handleClick"
|
|
15
|
+
>
|
|
16
|
+
<FlyIconV2
|
|
17
|
+
v-if="icon && resolvedIconPosition === 'left'"
|
|
18
|
+
:icon="icon"
|
|
19
|
+
:class="[{ 'left-icon': slots.default }]"
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
<slot></slot>
|
|
23
|
+
|
|
24
|
+
<FlyIconV2
|
|
25
|
+
v-if="icon && resolvedIconPosition === 'right'"
|
|
26
|
+
:icon="icon"
|
|
27
|
+
:class="[{ 'right-icon': slots.default }]"
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<span v-if="imageUrl" class="btn-image" :class="[{ 'clip-round': clipRound }]">
|
|
31
|
+
<img :src="imageUrl" />
|
|
32
|
+
</span>
|
|
33
|
+
</el-button>
|
|
34
|
+
</FlyTooltip>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script lang="ts" setup>
|
|
39
|
+
import { computed, useAttrs, useSlots } from 'vue'
|
|
40
|
+
|
|
41
|
+
import { ElButton } from 'element-plus'
|
|
42
|
+
|
|
43
|
+
import { isEmpty } from 'lodash-es'
|
|
44
|
+
|
|
45
|
+
import FlyTooltip from '../../feedback/tooltip/FlyTooltip.vue'
|
|
46
|
+
import FlyIconV2 from '../../general/fly-icon-v2/FlyIconV2.vue'
|
|
47
|
+
|
|
48
|
+
import './FlyButton.element.scss'
|
|
49
|
+
import type { FlyButtonIconPosition, FlyButtonProps } from './FlyButton.types'
|
|
50
|
+
|
|
51
|
+
const attrs = useAttrs()
|
|
52
|
+
const slots = useSlots()
|
|
53
|
+
const emit = defineEmits(['click'])
|
|
54
|
+
|
|
55
|
+
defineOptions({
|
|
56
|
+
inheritAttrs: false
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const props = withDefaults(defineProps<FlyButtonProps>(), {
|
|
60
|
+
active: false,
|
|
61
|
+
aspect1: false,
|
|
62
|
+
clipRound: false,
|
|
63
|
+
full: false,
|
|
64
|
+
stop: false,
|
|
65
|
+
tooltip: () => ({
|
|
66
|
+
placement: 'bottom',
|
|
67
|
+
disabled: false
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const additionalButtonBindingValues = computed(() => {
|
|
72
|
+
const { type, size } = props
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...attrs,
|
|
76
|
+
size,
|
|
77
|
+
type
|
|
78
|
+
} as object
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const resolvedIconPosition = computed<FlyButtonIconPosition>(() => props.iconPosition || 'left')
|
|
82
|
+
|
|
83
|
+
function handleClick(e: MouseEvent) {
|
|
84
|
+
/**
|
|
85
|
+
* Stop the event propagation if the stop prop is set to true
|
|
86
|
+
*/
|
|
87
|
+
if (props.stop) {
|
|
88
|
+
e.stopPropagation()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
emit('click', e)
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<style lang="scss" scoped>
|
|
96
|
+
.fly-button {
|
|
97
|
+
pointer-events: auto;
|
|
98
|
+
|
|
99
|
+
&.full button {
|
|
100
|
+
width: 100%;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:deep(.el-button) {
|
|
104
|
+
&.active {
|
|
105
|
+
/* 1px ring stile */
|
|
106
|
+
box-shadow: 0 0 0 1px var(--anra-white);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.fly-icon {
|
|
110
|
+
svg {
|
|
111
|
+
width: calc(1em + 2px);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
:deep(.fly-icon.left-icon) {
|
|
117
|
+
padding-inline-end: 0.25rem;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
:deep(.fly-icon.right-icon) {
|
|
121
|
+
padding-inline-start: 0.25rem;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.btn-image {
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
justify-content: center;
|
|
128
|
+
position: absolute;
|
|
129
|
+
top: 0;
|
|
130
|
+
left: 0;
|
|
131
|
+
right: 0;
|
|
132
|
+
bottom: 0;
|
|
133
|
+
|
|
134
|
+
&.clip-round {
|
|
135
|
+
-webkit-box-align: stretch;
|
|
136
|
+
align-items: stretch;
|
|
137
|
+
border-radius: 50%;
|
|
138
|
+
box-sizing: content-box;
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
-webkit-box-pack: center;
|
|
142
|
+
justify-content: center;
|
|
143
|
+
overflow: hidden;
|
|
144
|
+
|
|
145
|
+
img {
|
|
146
|
+
border: 5px solid transparent;
|
|
147
|
+
border-radius: 50%;
|
|
148
|
+
display: flex;
|
|
149
|
+
width: 100%;
|
|
150
|
+
height: 100%;
|
|
151
|
+
flex: 1 1 100%;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
</style>
|
|
157
|
+
|
|
158
|
+
<style lang="scss">
|
|
159
|
+
@use './FlyButton.mixins.scss' as button;
|
|
160
|
+
|
|
161
|
+
.el-button-group {
|
|
162
|
+
display: flex;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
html.dark {
|
|
166
|
+
button.el-button {
|
|
167
|
+
@include button.fly-button-overrides-dark;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
button.el-button {
|
|
172
|
+
position: relative;
|
|
173
|
+
overflow: hidden;
|
|
174
|
+
transition: 0.1s;
|
|
175
|
+
text-wrap: balance;
|
|
176
|
+
@include button.fly-button-overrides;
|
|
177
|
+
}
|
|
178
|
+
</style>
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="fly-collapse-title-renderer">
|
|
3
|
-
<div class="fly-collapse-title-renderer__inner">
|
|
4
|
-
<p class="fly-collapse-title-renderer__title">
|
|
5
|
-
{{ t(title) }}
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
|
-
<slot></slot>
|
|
9
|
-
</div>
|
|
10
|
-
</div>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script lang="ts" setup>
|
|
14
|
-
import { UseLocaleInjector } from '../../../composables/UseLocaleInjector'
|
|
15
|
-
|
|
16
|
-
defineProps<{
|
|
17
|
-
title: string
|
|
18
|
-
}>()
|
|
19
|
-
|
|
20
|
-
const { t } = UseLocaleInjector()
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<style lang="scss" scoped>
|
|
24
|
-
.fly-collapse-title-renderer {
|
|
25
|
-
display: flex;
|
|
26
|
-
gap: 0.25rem;
|
|
27
|
-
align-items: center;
|
|
28
|
-
text-align: left;
|
|
29
|
-
flex-grow: 1;
|
|
30
|
-
|
|
31
|
-
&__inner {
|
|
32
|
-
display: flex;
|
|
33
|
-
padding-left: 0.5rem;
|
|
34
|
-
padding-right: 0.5rem;
|
|
35
|
-
flex-grow: 1;
|
|
36
|
-
align-items: center;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
&__title {
|
|
40
|
-
font-size: 0.875rem;
|
|
41
|
-
line-height: 1.25rem;
|
|
42
|
-
font-weight: 500;
|
|
43
|
-
flex-grow: 1;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="fly-collapse-title-renderer">
|
|
3
|
+
<div class="fly-collapse-title-renderer__inner">
|
|
4
|
+
<p class="fly-collapse-title-renderer__title">
|
|
5
|
+
{{ t(title) }}
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<slot></slot>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" setup>
|
|
14
|
+
import { UseLocaleInjector } from '../../../composables/UseLocaleInjector'
|
|
15
|
+
|
|
16
|
+
defineProps<{
|
|
17
|
+
title: string
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
const { t } = UseLocaleInjector()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style lang="scss" scoped>
|
|
24
|
+
.fly-collapse-title-renderer {
|
|
25
|
+
display: flex;
|
|
26
|
+
gap: 0.25rem;
|
|
27
|
+
align-items: center;
|
|
28
|
+
text-align: left;
|
|
29
|
+
flex-grow: 1;
|
|
30
|
+
|
|
31
|
+
&__inner {
|
|
32
|
+
display: flex;
|
|
33
|
+
padding-left: 0.5rem;
|
|
34
|
+
padding-right: 0.5rem;
|
|
35
|
+
flex-grow: 1;
|
|
36
|
+
align-items: center;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&__title {
|
|
40
|
+
font-size: 0.875rem;
|
|
41
|
+
line-height: 1.25rem;
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
flex-grow: 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
</style>
|