@it-enterprise/forcebpm-ui-kit 1.0.2-beta.3 → 1.0.2-beta.30
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 +81 -65
- package/index.js +48 -1
- package/package.json +35 -15
- package/plugin.js +117 -0
- package/src/FActionSnackbar.vue +107 -0
- package/src/FAvatar.vue +10 -8
- package/src/{FConfirmModal.vue → FConfirmDialog.vue} +38 -28
- package/src/FContextMenu.vue +87 -0
- package/src/FDialog.vue +264 -0
- package/src/FLangSwitcher.vue +47 -0
- package/src/FNoData.vue +80 -0
- package/src/FNotify.vue +257 -0
- package/src/FPagination.vue +163 -0
- package/src/FPreLoader.vue +105 -0
- package/src/FSearchPanel.vue +191 -0
- package/src/FShare.vue +134 -0
- package/src/FTruncate.vue +121 -0
- package/src/FUserGroupPicker.vue +634 -0
- package/src/FUserRoles.vue +195 -0
- package/src/assets/fonts/ProximaNova-Bold.woff +0 -0
- package/src/assets/fonts/ProximaNova-Bold.woff2 +0 -0
- package/src/assets/fonts/ProximaNova-Regular.woff +0 -0
- package/src/assets/fonts/ProximaNova-Regular.woff2 +0 -0
- package/src/assets/fonts/ProximaNova-Semibold.woff +0 -0
- package/src/assets/fonts/ProximaNova-Semibold.woff2 +0 -0
- package/src/assets/fonts/loadFonts.js +55 -0
- package/src/assets/icons/bell-mute.svg +4 -0
- package/src/assets/icons/bell.svg +3 -0
- package/src/assets/icons/check.svg +3 -0
- package/src/assets/icons/checkbox-false.svg +3 -0
- package/src/assets/icons/checkbox-true.svg +4 -0
- package/src/assets/icons/chevron.svg +3 -0
- package/src/assets/icons/color-radio-active.svg +4 -0
- package/src/assets/icons/color-radio.svg +3 -0
- package/src/assets/icons/ctx-arrow.svg +3 -0
- package/src/assets/icons/ctx-delete.svg +6 -0
- package/src/assets/icons/ctx-link.svg +5 -0
- package/src/assets/icons/ctx-more.svg +5 -0
- package/src/assets/icons/ctx-pen.svg +4 -0
- package/src/assets/icons/delete.svg +6 -0
- package/src/assets/icons/dots.svg +5 -0
- package/src/assets/icons/filter.svg +3 -0
- package/src/assets/icons/folder.svg +3 -0
- package/src/assets/icons/open-envelope.svg +6 -0
- package/src/assets/icons/pass-eye-close.svg +3 -0
- package/src/assets/icons/pass-eye-open.svg +4 -0
- package/src/assets/icons/plus-solid.svg +4 -0
- package/src/assets/icons/plus.svg +4 -0
- package/src/assets/icons/radio-false.svg +3 -0
- package/src/assets/icons/radio-true.svg +4 -0
- package/src/assets/icons/search.svg +3 -0
- package/src/assets/icons/sort-solid.svg +3 -0
- package/src/assets/icons/sort.svg +6 -0
- package/src/assets/icons/star-line.svg +3 -0
- package/src/assets/icons/star.svg +3 -0
- package/src/assets/icons/times.svg +4 -0
- package/src/assets/images/0.gif +0 -0
- package/src/assets/images/0.svg +4 -0
- package/src/assets/images/3.svg +4 -0
- package/src/assets/images/4.svg +4 -0
- package/src/assets/images/5.svg +4 -0
- package/src/assets/scss/buttons.scss +60 -0
- package/src/assets/scss/card.scss +11 -0
- package/src/assets/scss/expansion.scss +45 -0
- package/src/assets/scss/icons.scss +273 -0
- package/src/assets/scss/index.scss +10 -0
- package/src/assets/scss/input.scss +344 -0
- package/src/assets/scss/overlay.scss +69 -0
- package/src/assets/scss/skeleton.scss +22 -0
- package/src/assets/scss/tables.scss +143 -0
- package/src/assets/scss/tabs.scss +42 -0
- package/src/assets/scss/utilities.scss +167 -0
- package/src/f-date-picker/FDatePicker.vue +322 -0
- package/src/f-date-picker/FMenuDatePicker.vue +337 -0
- package/src/f-date-picker/FTextFieldDate.vue +498 -0
- package/src/f-toolbar/FFilterPanel.vue +62 -0
- package/src/f-toolbar/FSortPanel.vue +55 -0
- package/src/f-toolbar/FTabPanel.vue +123 -0
- package/src/f-toolbar/FToolbar.vue +131 -0
- package/src/f-toolbar/FViewerPanel.vue +71 -0
- package/src/forcebpmIcon.js +69 -0
- package/src/locales/en.json +115 -0
- package/src/locales/index.js +7 -0
- package/src/locales/ru.json +116 -0
- package/src/locales/uk.json +116 -0
- package/src/utils/color.js +38 -0
package/README.md
CHANGED
|
@@ -1,93 +1,109 @@
|
|
|
1
|
-
# ForceBPM
|
|
1
|
+
# ForceBPM UI Kit
|
|
2
2
|
|
|
3
|
+
Vue 3 компонентная библиотека для ForceBPM приложений.
|
|
3
4
|
|
|
5
|
+
## Установка
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
|
8
|
-
|
|
9
|
-
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
|
|
10
|
-
|
|
11
|
-
## Add your files
|
|
12
|
-
|
|
13
|
-
* [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
|
|
14
|
-
* [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
cd existing_repo
|
|
18
|
-
git remote add origin https://gitlab.com/it-enterprise/npm-packages/forcebpm-ui-kit.git
|
|
19
|
-
git branch -M main
|
|
20
|
-
git push -uf origin main
|
|
7
|
+
```bash
|
|
8
|
+
npm install @it-enterprise/forcebpm-ui-kit
|
|
21
9
|
```
|
|
22
10
|
|
|
23
|
-
##
|
|
11
|
+
## Требования
|
|
24
12
|
|
|
25
|
-
|
|
13
|
+
- Vue 3.x
|
|
14
|
+
- Vuetify 3.x
|
|
15
|
+
- vue-i18n (опционально, для переводов)
|
|
26
16
|
|
|
27
|
-
##
|
|
17
|
+
## Использование
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
* [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
|
|
31
|
-
* [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
|
32
|
-
* [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
|
|
33
|
-
* [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
|
|
19
|
+
### 1. Как плагин (рекомендуется)
|
|
34
20
|
|
|
35
|
-
|
|
21
|
+
```js
|
|
22
|
+
// main.js
|
|
23
|
+
import { createApp } from 'vue'
|
|
24
|
+
import { createI18n } from 'vue-i18n'
|
|
25
|
+
import { createVuetify } from 'vuetify'
|
|
26
|
+
import ForceBPMUiKit from '@it-enterprise/forcebpm-ui-kit'
|
|
27
|
+
import App from './App.vue'
|
|
36
28
|
|
|
37
|
-
|
|
29
|
+
const i18n = createI18n({
|
|
30
|
+
locale: 'uk',
|
|
31
|
+
fallbackLocale: 'en',
|
|
32
|
+
messages: {}
|
|
33
|
+
})
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
* [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
|
|
41
|
-
* [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
|
|
42
|
-
* [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
|
|
43
|
-
* [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
|
|
35
|
+
const vuetify = createVuetify({})
|
|
44
36
|
|
|
45
|
-
|
|
37
|
+
const app = createApp(App)
|
|
46
38
|
|
|
47
|
-
|
|
39
|
+
app.use(i18n)
|
|
40
|
+
app.use(vuetify)
|
|
41
|
+
app.use(ForceBPMUiKit, {
|
|
42
|
+
i18n, // Интеграция с vue-i18n (добавит переводы автоматически)
|
|
43
|
+
registerGlobal: true, // Регистрация компонентов глобально (по умолчанию true)
|
|
44
|
+
prefix: 'F' // Префикс компонентов (по умолчанию 'F')
|
|
45
|
+
})
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
## Suggestions for a good README
|
|
52
|
-
|
|
53
|
-
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
|
47
|
+
app.mount('#app')
|
|
48
|
+
```
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
Choose a self-explaining name for your project.
|
|
50
|
+
### 2. Использование отдельных компонентов (tree-shaking)
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
```vue
|
|
53
|
+
<script setup>
|
|
54
|
+
import { FAvatar, FNotify, FNoData } from '@it-enterprise/forcebpm-ui-kit'
|
|
55
|
+
</script>
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
<template>
|
|
58
|
+
<FAvatar :full-user="user" />
|
|
59
|
+
<FNoData text="Немає даних" />
|
|
60
|
+
</template>
|
|
61
|
+
```
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
|
|
63
|
+
### 3. Только переводы
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
```js
|
|
66
|
+
import { createI18n } from 'vue-i18n'
|
|
67
|
+
import { defaultMessages } from '@it-enterprise/forcebpm-ui-kit/plugin'
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
const i18n = createI18n({
|
|
70
|
+
locale: 'uk',
|
|
71
|
+
messages: {
|
|
72
|
+
en: { ...myMessages.en, ...defaultMessages.en },
|
|
73
|
+
uk: { ...myMessages.uk, ...defaultMessages.uk }
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
```
|
|
72
77
|
|
|
73
|
-
##
|
|
74
|
-
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
|
|
78
|
+
## Компоненты
|
|
75
79
|
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
| Компонент | Описание |
|
|
81
|
+
|-----------|----------|
|
|
82
|
+
| `FAvatar` | Аватар пользователя с меню информации |
|
|
83
|
+
| `FConfirmModal` | Модальное окно подтверждения |
|
|
84
|
+
| `FContextMenu` | Контекстное меню |
|
|
85
|
+
| `FHtmlContent` | Безопасный рендер HTML контента |
|
|
86
|
+
| `FNoData` | Плейсхолдер "Нет данных" |
|
|
87
|
+
| `FNotify` | Система уведомлений |
|
|
88
|
+
| `FPreLoader` | Прелоадер |
|
|
89
|
+
| `FShare` | Диалог "Поделиться" |
|
|
78
90
|
|
|
79
|
-
##
|
|
80
|
-
State if you are open to contributions and what your requirements are for accepting them.
|
|
91
|
+
## Опции плагина
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
| Опция | Тип | По умолчанию | Описание |
|
|
94
|
+
|-------|-----|--------------|----------|
|
|
95
|
+
| `registerGlobal` | `boolean` | `true` | Регистрировать компоненты глобально |
|
|
96
|
+
| `i18n` | `object` | `null` | Экземпляр vue-i18n для интеграции переводов |
|
|
97
|
+
| `prefix` | `string` | `'F'` | Префикс имён компонентов |
|
|
98
|
+
| `messages` | `object` | `null` | Дополнительные/кастомные переводы |
|
|
83
99
|
|
|
84
|
-
|
|
100
|
+
## Локализация
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
По умолчанию включены переводы для:
|
|
103
|
+
- `en` - English
|
|
104
|
+
- `uk` - Українська
|
|
105
|
+
- `ru` - Русский
|
|
88
106
|
|
|
89
|
-
##
|
|
90
|
-
For open source projects, say how it is licensed.
|
|
107
|
+
## Лицензия
|
|
91
108
|
|
|
92
|
-
|
|
93
|
-
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
|
|
109
|
+
MIT
|
package/index.js
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
// Load fonts
|
|
2
|
+
import './src/assets/fonts/loadFonts.js'
|
|
3
|
+
|
|
4
|
+
// Global styles
|
|
5
|
+
import './src/assets/scss/index.scss'
|
|
6
|
+
|
|
7
|
+
// Components
|
|
1
8
|
export { default as FHtmlContent } from './src/FHtmlContent.vue'
|
|
2
9
|
export { default as FAvatar } from './src/FAvatar.vue'
|
|
3
|
-
export { default as
|
|
10
|
+
export { default as FPreLoader } from './src/FPreLoader.vue'
|
|
11
|
+
export { default as FNoData } from './src/FNoData.vue'
|
|
12
|
+
export { default as FNotify } from './src/FNotify.vue'
|
|
13
|
+
export { default as FShare } from './src/FShare.vue'
|
|
14
|
+
export { default as FContextMenu } from './src/FContextMenu.vue'
|
|
15
|
+
export { default as FSearchPanel } from './src/FSearchPanel.vue'
|
|
16
|
+
export { default as FDialog } from './src/FDialog.vue'
|
|
17
|
+
export { default as FConfirmDialog } from './src/FConfirmDialog.vue'
|
|
18
|
+
export { default as FToolbar } from './src/f-toolbar/FToolbar.vue'
|
|
19
|
+
export { default as FTabPanel } from './src/f-toolbar/FTabPanel.vue'
|
|
20
|
+
export { default as FViewerPanel } from './src/f-toolbar/FViewerPanel.vue'
|
|
21
|
+
export { default as FFilterPanel } from './src/f-toolbar/FFilterPanel.vue'
|
|
22
|
+
export { default as FSortPanel } from './src/f-toolbar/FSortPanel.vue'
|
|
23
|
+
export { default as FTruncate } from './src/FTruncate.vue'
|
|
24
|
+
export { default as FUserRoles } from './src/FUserRoles.vue'
|
|
25
|
+
export { default as FDatePicker } from './src/f-date-picker/FDatePicker.vue'
|
|
26
|
+
export { default as FMenuDatePicker } from './src/f-date-picker/FMenuDatePicker.vue'
|
|
27
|
+
export { default as FTextFieldDate } from './src/f-date-picker/FTextFieldDate.vue'
|
|
28
|
+
export { default as FUserGroupPicker } from './src/FUserGroupPicker.vue'
|
|
29
|
+
export { default as FLangSwitcher } from './src/FLangSwitcher.vue'
|
|
30
|
+
export { default as FActionSnackbar } from './src/FActionSnackbar.vue'
|
|
31
|
+
export { default as FPagination } from './src/FPagination.vue'
|
|
32
|
+
|
|
33
|
+
// Utils
|
|
34
|
+
export { hexToRGBA, createRadialGradient } from './src/utils/color.js'
|
|
35
|
+
|
|
36
|
+
// Images
|
|
37
|
+
export { default as image0Gif } from './src/assets/images/0.gif'
|
|
38
|
+
export { default as image0 } from './src/assets/images/0.svg'
|
|
39
|
+
export { default as image3 } from './src/assets/images/3.svg'
|
|
40
|
+
export { default as image4 } from './src/assets/images/4.svg'
|
|
41
|
+
export { default as image5 } from './src/assets/images/5.svg'
|
|
42
|
+
|
|
43
|
+
// Icon components
|
|
44
|
+
export { FIcon, forcebpmIcon } from './src/forcebpmIcon.js'
|
|
45
|
+
|
|
46
|
+
// Plugin and translations
|
|
47
|
+
export { default as ForceBPMUiKit, defaultMessages } from './plugin.js'
|
|
48
|
+
|
|
49
|
+
// Default export - plugin
|
|
50
|
+
export { default } from './plugin.js'
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
"type": "module",
|
|
2
3
|
"name": "@it-enterprise/forcebpm-ui-kit",
|
|
3
|
-
"version": "1.0.2-beta.
|
|
4
|
+
"version": "1.0.2-beta.30",
|
|
4
5
|
"description": "FBPM UI Kit",
|
|
5
6
|
"author": "it-enterprise",
|
|
6
7
|
"license": "MIT",
|
|
@@ -11,22 +12,19 @@
|
|
|
11
12
|
"import": "./index.js",
|
|
12
13
|
"require": "./index.js"
|
|
13
14
|
},
|
|
14
|
-
"./
|
|
15
|
-
"import": "./
|
|
16
|
-
"require": "./
|
|
15
|
+
"./plugin": {
|
|
16
|
+
"import": "./plugin.js",
|
|
17
|
+
"require": "./plugin.js"
|
|
17
18
|
},
|
|
18
|
-
"./
|
|
19
|
-
"import": "./src/
|
|
20
|
-
"require": "./src/
|
|
21
|
-
},
|
|
22
|
-
"./FConfirmModal": {
|
|
23
|
-
"import": "./src/FConfirmModal.vue",
|
|
24
|
-
"require": "./src/FConfirmModal.vue"
|
|
19
|
+
"./locales": {
|
|
20
|
+
"import": "./src/locales/index.js",
|
|
21
|
+
"require": "./src/locales/index.js"
|
|
25
22
|
}
|
|
26
23
|
},
|
|
27
24
|
"files": [
|
|
28
25
|
"src",
|
|
29
26
|
"index.js",
|
|
27
|
+
"plugin.js",
|
|
30
28
|
"README.md",
|
|
31
29
|
"LICENSE"
|
|
32
30
|
],
|
|
@@ -40,20 +38,42 @@
|
|
|
40
38
|
],
|
|
41
39
|
"dependencies": {
|
|
42
40
|
"dompurify": "^3.0.0",
|
|
41
|
+
"moment": "^2.30.1",
|
|
43
42
|
"vue": "^3.0.0"
|
|
44
43
|
},
|
|
45
44
|
"peerDependencies": {
|
|
46
|
-
"
|
|
45
|
+
"@vueuse/core": "^14.1.0",
|
|
46
|
+
"vue": "^3.0.0",
|
|
47
|
+
"vue-i18n": "^11.2.8",
|
|
48
|
+
"vuetify": "^3.0.0"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@
|
|
51
|
+
"@eslint/js": "^9.39.2",
|
|
52
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
53
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
54
|
+
"@vitest/ui": "^4.0.18",
|
|
50
55
|
"@vue/compiler-sfc": "^3.0.0",
|
|
56
|
+
"@vue/eslint-config-prettier": "^10.2.0",
|
|
57
|
+
"@vue/test-utils": "^2.4.6",
|
|
58
|
+
"eslint": "^9.39.2",
|
|
59
|
+
"eslint-config-prettier": "^10.1.8",
|
|
60
|
+
"eslint-plugin-vue": "^10.7.0",
|
|
61
|
+
"jsdom": "^27.4.0",
|
|
62
|
+
"prettier": "^3.8.1",
|
|
51
63
|
"sass-embedded": "^1.97.2",
|
|
52
|
-
"vite": "^
|
|
64
|
+
"vite": "^7.3.1",
|
|
65
|
+
"vitest": "^4.0.18"
|
|
53
66
|
},
|
|
54
67
|
"scripts": {
|
|
68
|
+
"lint": "eslint --ext .js,.vue src",
|
|
69
|
+
"lint:fix": "eslint --ext .js,.vue src --fix",
|
|
70
|
+
"format": "prettier --write \"src/**/*.{js,vue,json,scss}\"",
|
|
71
|
+
"preview": "vite preview",
|
|
55
72
|
"build": "vite build",
|
|
56
|
-
"test": "
|
|
73
|
+
"test": "vitest",
|
|
74
|
+
"test:run": "vitest run",
|
|
75
|
+
"test:coverage": "vitest run --coverage",
|
|
76
|
+
"test:ui": "vitest --ui"
|
|
57
77
|
},
|
|
58
78
|
"repository": {
|
|
59
79
|
"type": "git",
|
package/plugin.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForceBPM UI Kit Plugin
|
|
3
|
+
* Vue 3 plugin for registering components globally and integrating with i18n
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as components from './index.js'
|
|
7
|
+
import { defaultMessages } from './src/locales/index.js'
|
|
8
|
+
|
|
9
|
+
// Re-export for convenience
|
|
10
|
+
export { defaultMessages }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ForceBPM UI Kit Plugin
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Basic usage with global registration
|
|
17
|
+
* import { createApp } from 'vue'
|
|
18
|
+
* import { ForceBPMUiKit } from '@it-enterprise/forcebpm-ui-kit'
|
|
19
|
+
*
|
|
20
|
+
* const app = createApp(App)
|
|
21
|
+
* app.use(ForceBPMUiKit)
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // With i18n integration
|
|
25
|
+
* import { createApp } from 'vue'
|
|
26
|
+
* import { createI18n } from 'vue-i18n'
|
|
27
|
+
* import { ForceBPMUiKit } from '@it-enterprise/forcebpm-ui-kit'
|
|
28
|
+
*
|
|
29
|
+
* const i18n = createI18n({ locale: 'uk', messages: {} })
|
|
30
|
+
* const app = createApp(App)
|
|
31
|
+
*
|
|
32
|
+
* app.use(i18n)
|
|
33
|
+
* app.use(ForceBPMUiKit, { i18n })
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // Without global registration (tree-shaking friendly)
|
|
37
|
+
* import { createApp } from 'vue'
|
|
38
|
+
* import { ForceBPMUiKit } from '@it-enterprise/forcebpm-ui-kit'
|
|
39
|
+
*
|
|
40
|
+
* const app = createApp(App)
|
|
41
|
+
* app.use(ForceBPMUiKit, { registerGlobal: false })
|
|
42
|
+
*/
|
|
43
|
+
export const ForceBPMUiKit = {
|
|
44
|
+
/**
|
|
45
|
+
* Install the plugin
|
|
46
|
+
* @param {import('vue').App} app - Vue application instance
|
|
47
|
+
* @param {Object} options - Plugin options
|
|
48
|
+
* @param {boolean} [options.registerGlobal=true] - Register components globally
|
|
49
|
+
* @param {Object} [options.i18n=null] - vue-i18n instance for translations
|
|
50
|
+
* @param {string} [options.prefix='F'] - Component name prefix
|
|
51
|
+
* @param {Object} [options.messages=null] - Custom translations to merge
|
|
52
|
+
* @param {Object} [options.emitter=null] - Event bus instance (mitt, tiny-emitter, etc)
|
|
53
|
+
* @param {Object} [options.events={}] - Events map for modal windows
|
|
54
|
+
*/
|
|
55
|
+
install(app, options = {}) {
|
|
56
|
+
const { registerGlobal = true, i18n = null, prefix = 'F', messages = null, emitter = null, events = {} } = options
|
|
57
|
+
|
|
58
|
+
// Provide emitter and events to components
|
|
59
|
+
if (emitter) {
|
|
60
|
+
app.provide('fbpm-emitter', emitter)
|
|
61
|
+
app.provide('fbpm-events', events)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Merge translations into i18n if provided
|
|
65
|
+
if (i18n) {
|
|
66
|
+
const messagesToMerge = messages ? mergeDeep(defaultMessages, messages) : defaultMessages
|
|
67
|
+
|
|
68
|
+
Object.entries(messagesToMerge).forEach(([locale, localeMessages]) => {
|
|
69
|
+
if (i18n.global) {
|
|
70
|
+
// Vue I18n v9+ (Composition API)
|
|
71
|
+
i18n.global.mergeLocaleMessage(locale, localeMessages)
|
|
72
|
+
} else if (typeof i18n.mergeLocaleMessage === 'function') {
|
|
73
|
+
// Vue I18n legacy mode
|
|
74
|
+
i18n.mergeLocaleMessage(locale, localeMessages)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Register components globally
|
|
80
|
+
if (registerGlobal) {
|
|
81
|
+
Object.entries(components).forEach(([name, component]) => {
|
|
82
|
+
// Skip special exports
|
|
83
|
+
if (name === 'default' || name === 'ForceBPMUiKit' || name === 'defaultMessages') return
|
|
84
|
+
// Allow custom prefix (e.g., 'Fbpm' instead of 'F')
|
|
85
|
+
const componentName = prefix === 'F' ? name : name.replace(/^F/, prefix)
|
|
86
|
+
|
|
87
|
+
app.component(componentName, component)
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Provide plugin config for components that may need it
|
|
92
|
+
app.provide('forcebpm-ui-kit', {
|
|
93
|
+
prefix,
|
|
94
|
+
i18n: !!i18n
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Deep merge utility for objects
|
|
101
|
+
*/
|
|
102
|
+
function mergeDeep(target, source) {
|
|
103
|
+
const output = { ...target }
|
|
104
|
+
|
|
105
|
+
for (const key in source) {
|
|
106
|
+
if (source[key] instanceof Object && key in target) {
|
|
107
|
+
output[key] = mergeDeep(target[key], source[key])
|
|
108
|
+
} else {
|
|
109
|
+
output[key] = source[key]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return output
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Default export for convenience
|
|
117
|
+
export default ForceBPMUiKit
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
// FActionSnackbar
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
actions: {
|
|
7
|
+
type: Array,
|
|
8
|
+
default: () => []
|
|
9
|
+
// Example of list item:
|
|
10
|
+
// {
|
|
11
|
+
// text: 'Button Text',
|
|
12
|
+
// action: () => {},
|
|
13
|
+
// icon: 'fire',
|
|
14
|
+
// size: 20, // optional, default is 20
|
|
15
|
+
// hide: false, // optional setting to hide button without removing it from the list
|
|
16
|
+
// disabled: false // optional setting to disable button
|
|
17
|
+
// }
|
|
18
|
+
},
|
|
19
|
+
loading: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false
|
|
22
|
+
},
|
|
23
|
+
tooltipProps: {
|
|
24
|
+
type: Object,
|
|
25
|
+
default: () => ({
|
|
26
|
+
location: 'top'
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const state = defineModel({
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: false
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const loaderItems = computed(() => {
|
|
37
|
+
const visibleCount = props.actions.filter(action => !action.hide).length
|
|
38
|
+
return Array.from({ length: visibleCount }, (_, i) => i)
|
|
39
|
+
})
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<v-snackbar class="f-action-snackbar" position="absolute" :model-value="state" rounded="lg" :timeout="-1">
|
|
44
|
+
<!-- Loading -->
|
|
45
|
+
<div v-if="loading" class="d-flex">
|
|
46
|
+
<v-skeleton-loader v-for="i in loaderItems" :key="i" type="button" height="40" width="60" class="f-skeleton-loader" />
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Actions -->
|
|
50
|
+
<template v-else>
|
|
51
|
+
<v-tooltip v-for="(btn, idx) in props.actions" :key="idx" :text="btn.text" v-bind="tooltipProps">
|
|
52
|
+
<template #activator="{ props: propsTooltip }">
|
|
53
|
+
<v-btn v-if="!btn.hide" v-bind="propsTooltip" variant="text" width="60" :disabled="btn.disabled" @click="btn.action">
|
|
54
|
+
<FIcon :icon="btn.icon" :size="btn.size || 20" color="white" />
|
|
55
|
+
</v-btn>
|
|
56
|
+
</template>
|
|
57
|
+
</v-tooltip>
|
|
58
|
+
</template>
|
|
59
|
+
</v-snackbar>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<style lang="scss" scoped>
|
|
63
|
+
.f-action-snackbar {
|
|
64
|
+
bottom: 8%;
|
|
65
|
+
:deep(.v-snackbar__wrapper) {
|
|
66
|
+
min-height: 0;
|
|
67
|
+
min-width: min-content;
|
|
68
|
+
background-color: rgb(var(--v-theme-title-dark));
|
|
69
|
+
box-shadow: var(--f-box-shadow);
|
|
70
|
+
}
|
|
71
|
+
:deep(.v-snackbar__content) {
|
|
72
|
+
padding: 0;
|
|
73
|
+
.v-btn {
|
|
74
|
+
.v-btn__underlay {
|
|
75
|
+
transition: background-color 0.3s ease-in-out;
|
|
76
|
+
}
|
|
77
|
+
&:hover {
|
|
78
|
+
.v-btn__underlay {
|
|
79
|
+
background-color: rgba(255, 255, 255, 0.08);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
.v-skeleton-loader:first-child {
|
|
84
|
+
border-top-right-radius: 0;
|
|
85
|
+
border-bottom-right-radius: 0;
|
|
86
|
+
.v-skeleton-loader__button {
|
|
87
|
+
border-top-right-radius: 0;
|
|
88
|
+
border-bottom-right-radius: 0;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
.v-skeleton-loader:last-child {
|
|
92
|
+
border-top-left-radius: 0;
|
|
93
|
+
border-bottom-left-radius: 0;
|
|
94
|
+
.v-skeleton-loader__button {
|
|
95
|
+
border-top-left-radius: 0;
|
|
96
|
+
border-bottom-left-radius: 0;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
.v-skeleton-loader:not(.v-skeleton-loader:first-child, .v-skeleton-loader:last-child) {
|
|
100
|
+
border-radius: 0;
|
|
101
|
+
.v-skeleton-loader__button {
|
|
102
|
+
border-radius: 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
</style>
|
package/src/FAvatar.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
// FAvatar
|
|
3
|
-
import { computed
|
|
3
|
+
import { computed } from 'vue'
|
|
4
4
|
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
activeUserId: {
|
|
@@ -9,7 +9,8 @@ const props = defineProps({
|
|
|
9
9
|
},
|
|
10
10
|
fullUser: {
|
|
11
11
|
type: Object,
|
|
12
|
-
default: null
|
|
12
|
+
default: null,
|
|
13
|
+
validator: value => value && 'userId' in value && 'name' in value
|
|
13
14
|
},
|
|
14
15
|
group: {
|
|
15
16
|
type: Object,
|
|
@@ -37,12 +38,12 @@ const props = defineProps({
|
|
|
37
38
|
const emit = defineEmits(['clearUserPhoto'])
|
|
38
39
|
|
|
39
40
|
const getInitialsByName = name => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
const splitter = name.split(' ')
|
|
42
|
+
const result = splitter.reduce((sum, current) => {
|
|
43
|
+
return sum + current.substr(0, 1)
|
|
44
|
+
}, '')
|
|
45
|
+
return result.slice(0, 2)
|
|
46
|
+
}
|
|
46
47
|
|
|
47
48
|
const userPhoto = computed(() => props.fullUser?.photo)
|
|
48
49
|
|
|
@@ -91,6 +92,7 @@ const errorHandler = () => {
|
|
|
91
92
|
close-delay="100"
|
|
92
93
|
open-delay="500"
|
|
93
94
|
location="bottom right"
|
|
95
|
+
z-index="2700"
|
|
94
96
|
:disabled="disabled || !fullUser?.name"
|
|
95
97
|
:close-on-content-click="false"
|
|
96
98
|
>
|