saby-customizer 0.0.0-pre.10

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 ADDED
@@ -0,0 +1,8 @@
1
+ # SABY Customizer [![npm][npmbadge]][npm]
2
+
3
+ SABY Customizer package for use via CDN
4
+
5
+ [npmbadge]: https://img.shields.io/npm/v/saby-customizer?label=saby-customizer
6
+
7
+ [npm]: https://www.npmjs.com/package/saby-customizer
8
+
@@ -0,0 +1,92 @@
1
+ import { oom } from '@notml/core'
2
+ import { toggleDialog, keysMapping } from '../lib'
3
+ import { getListOfOpenCards } from '../saby-lib/edo.js'
4
+
5
+
6
+ /** Карточка со сведениями о задаче для копирования ветки */
7
+ class GitBranchCard extends oom.extends(HTMLElement) {
8
+
9
+ static tagName = 'sc-git-branch-сard'
10
+ static style = oom.style({
11
+ 'display': 'contents',
12
+ '.mdc-card': {
13
+ margin: '16px',
14
+ padding: '12px'
15
+ },
16
+ '.title': {
17
+ fontWeight: 'bold'
18
+ },
19
+ '.link': {
20
+ fontSize: '14px'
21
+ },
22
+ '.description': {
23
+ fontSize: '14px',
24
+ whiteSpace: 'nowrap',
25
+ overflow: 'hidden',
26
+ textOverflow: 'ellipsis'
27
+ }
28
+ })
29
+
30
+ template = oom.div({ class: 'mdc-card' }, oom
31
+ .div({ class: 'title' }, this.getTitle())
32
+ .div({ class: 'link' }, oom.a(this.options.data.url, {
33
+ target: '_blank',
34
+ href: this.options.data.url
35
+ }))
36
+ .div({ class: 'description', title: this.options.data.description }, this.options.data.description))
37
+
38
+ /**
39
+ * @returns {string} Заголовок
40
+ */
41
+ getTitle() {
42
+ const { name } = this.options.data
43
+ const docNumber = ' № ' + this.options.data.number
44
+ const version = ' веха ' + this.options.data.version
45
+ const date = ' от ' + this.options.data.date
46
+ const author = ' ' + this.options.data.author
47
+
48
+ return name + docNumber + version + date + author
49
+ }
50
+
51
+ }
52
+
53
+
54
+ /** Список веток GIT для копирования на основе открытых карточек задач */
55
+ class GitBranchCardList extends oom.extends(HTMLElement) {
56
+
57
+ static tagName = 'sc-git-branch-сard-list'
58
+ static style = oom.style({
59
+ 'display': 'contents',
60
+ '.empty': {
61
+ padding: '100px',
62
+ textAlign: 'center'
63
+ }
64
+ })
65
+
66
+ taskList = getListOfOpenCards({
67
+ names: ['Ошибка', 'Задача'],
68
+ hasVersion: true
69
+ })
70
+ .map(card => new GitBranchCard(card))
71
+
72
+ taskListElement = (this.taskList.length > 0 && oom()(...this.taskList)) || oom
73
+ .div({ class: 'empty' }, 'Открытых задач с вехой не найдено')
74
+
75
+ template = oom()(
76
+ oom
77
+ .mwcTabBar(oom
78
+ .mwcTab({ label: 'Открытые задачи' })
79
+ .mwcTab({ label: 'История задач' })),
80
+ this.taskListElement
81
+ )
82
+
83
+ }
84
+
85
+
86
+ oom.define(GitBranchCard, GitBranchCardList)
87
+
88
+ keysMapping['alt-KeyB'] = () => toggleDialog({
89
+ key: 'git-branch-dialog',
90
+ title: 'Ветки для Git',
91
+ Element: GitBranchCardList
92
+ })
@@ -0,0 +1,55 @@
1
+ import { oom } from '@notml/core'
2
+ import { keysMapping } from './hotkeys.js'
3
+
4
+
5
+ /** Главное окно плагина */
6
+ class SabyCustomizerDashBoard extends oom.extends(HTMLElement) {
7
+
8
+ static tagName = 'sc-dash-board'
9
+
10
+ static style = oom.style({
11
+ 'sc-dash-board': {
12
+ position: 'fixed',
13
+ left: '0',
14
+ top: '0',
15
+ right: '0',
16
+ height: '100%',
17
+ zIndex: '13000',
18
+ backgroundColor: 'rgba(0,0,0,.32)'
19
+ }
20
+ })
21
+
22
+ template = oom
23
+ .header({ class: 'mdc-top-app-bar' }, oom
24
+ .div({ class: 'mdc-top-app-bar__row' }, oom
25
+ .section({ class: 'mdc-top-app-bar__section mdc-top-app-bar__section--align-start' }, oom
26
+ .button({ class: 'material-icons mdc-top-app-bar__navigation-icon mdc-icon-button' }, oom
27
+ .span({ class: 'mdc-icon-button__ripple' })
28
+ .span('menu', { class: 'mdc-button__label' }))
29
+ .span('Page title', { class: 'mdc-top-app-bar__title' }))
30
+ .section({ class: 'mdc-top-app-bar__section mdc-top-app-bar__section--align-end' }, oom
31
+ .button({ class: 'material-icons mdc-top-app-bar__action-item mdc-icon-button' }, oom
32
+ .span({ class: 'mdc-icon-button__ripple' })
33
+ .span('close', {
34
+ class: 'mdc-button__label',
35
+ onclick: () => this.remove()
36
+ }))
37
+ )))
38
+ .main({ class: 'mdc-top-app-bar--fixed-adjust' }, oom
39
+ .span('test'))
40
+
41
+ }
42
+
43
+
44
+ oom.define(SabyCustomizerDashBoard)
45
+
46
+ keysMapping['ctrl-shift-KeyU'] = keysMapping['ctrl-alt-KeyU'] = () => {
47
+ const layout = document.getElementById('saby-customizer-layout').shadowRoot
48
+ const dashboard = layout.getElementById('sc-dash-board')
49
+
50
+ if (dashboard) {
51
+ dashboard.remove()
52
+ } else {
53
+ oom(layout, oom.scDashBoard({ id: 'sc-dash-board' }))
54
+ }
55
+ }
@@ -0,0 +1,9 @@
1
+ import { Dexie } from 'dexie'
2
+
3
+ const db = new Dexie('saby-customizer-database')
4
+
5
+
6
+ db.version(1).stores({ settings: '&key' })
7
+
8
+
9
+ export { db }
package/lib/hotkeys.js ADDED
@@ -0,0 +1,21 @@
1
+ export const keysMapping = {}
2
+
3
+
4
+ document.addEventListener('keydown', (event) => {
5
+ let hKey = ''
6
+
7
+ if (event.ctrlKey) {
8
+ hKey += 'ctrl-'
9
+ }
10
+ if (event.shiftKey) {
11
+ hKey += 'shift-'
12
+ }
13
+ if (event.altKey) {
14
+ hKey += 'alt-'
15
+ }
16
+ hKey += event.code
17
+ if (hKey in keysMapping) {
18
+ keysMapping[hKey]()
19
+ event.stopPropagation()
20
+ }
21
+ }, { capture: true })
package/lib/layout.js ADDED
@@ -0,0 +1,35 @@
1
+ import { oom } from '@notml/core'
2
+
3
+
4
+ /** Подложка в теневым DOM для размещения в ней элементов плагина, для изоляции их от основной верстки */
5
+ oom.define(class SabyCustomizerLayout extends oom.extends(HTMLElement) {
6
+
7
+ static tagName = 'saby-customizer-layout'
8
+ static attachShadow = true
9
+
10
+ template = oom().head(oom
11
+ // Предзагрузка стилей material внутри теневого DOM
12
+ .link({ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap' })
13
+ .link({ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' })
14
+ // https://material.io/resources/color/
15
+ .style({
16
+ ':host': {
17
+ '--mdc-theme-primary': '#0d47a1',
18
+ '--mdc-theme-secondary': '#0d47a1',
19
+ '--mdc-theme-background': '#e1e1e1',
20
+ '--mdc-theme-surface': '#fff',
21
+ '--mdc-theme-on-primary': '#fff',
22
+ '--mdc-theme-on-secondary': '#fff',
23
+ '--mdc-theme-on-surface': '#000'
24
+ }
25
+ }))
26
+
27
+ })
28
+
29
+
30
+ const layoutElement = oom.sabyCustomizerLayout({ id: 'saby-customizer-layout' })
31
+
32
+ oom(document.documentElement, layoutElement)
33
+
34
+
35
+ export const layout = layoutElement.dom.shadowRoot
@@ -0,0 +1,25 @@
1
+ // https://github.com/material-components/material-web
2
+
3
+ // В ожидании правки
4
+ // https://github.com/material-components/material-web/issues/2780
5
+ // import 'https://unpkg.com/@material/mwc-dialog@0.25.1?module'
6
+ // import 'https://unpkg.com/@material/mwc-icon-button@0.25.1?module'
7
+ // import 'https://unpkg.com/@material/mwc-tab-bar@0.25.1?module'
8
+ // import 'https://unpkg.com/@material/mwc-top-app-bar@0.25.1?module'
9
+
10
+ import '@material/mwc-dialog'
11
+ import '@material/mwc-icon-button'
12
+ import '@material/mwc-tab-bar'
13
+ import '@material/mwc-top-app-bar'
14
+ /*
15
+ * PS
16
+ * unpkg не вывозит новый JS:
17
+ * https://github.com/mjackson/unpkg/issues/303
18
+ *
19
+ * jsdelivr не вывозит модульность:
20
+ * https://github.com/jsdelivr/jsdelivr/issues/18263
21
+ * https://github.com/jsdelivr/jsdelivr/issues/18215
22
+ * https://github.com/jsdelivr/jsdelivr/issues/18298
23
+ *
24
+ * Поэтому зависимости разбиты на 2 CDN до решения проблем в любом их них
25
+ */
@@ -0,0 +1,111 @@
1
+ import { oom } from '@notml/core'
2
+ import { layout } from './layout.js'
3
+
4
+ /**
5
+ * @typedef PopupDialogOptions
6
+ * @property {string} [key] Уникальный идентификатор вида диалога
7
+ * @property {string} [title] Текст заголовка диалога
8
+ * @property {typeof HTMLElement|string} Element Элемент с содержимым диалога
9
+ */
10
+ /** @type {PopupDialogOptions} */
11
+ const PopupDialogDefaults = {
12
+ title: 'SABY Customizer',
13
+ Element: ''
14
+ }
15
+ /** @type {PopupDialog} */
16
+ let lastDialog = null
17
+
18
+
19
+ /** Компонент всплывающего диалога */
20
+ export class PopupDialog extends oom.extends(HTMLElement, PopupDialogDefaults) {
21
+
22
+ static tagName = 'sc-popup-dialog'
23
+ // static className = 'mdc-dialog'
24
+ static style = oom.style({
25
+ 'sc-popup-dialog': {
26
+ display: 'contents'
27
+ },
28
+ 'mwc-dialog': {
29
+ '--mdc-dialog-z-index': '10000',
30
+ '--mdc-dialog-max-width': '600px'
31
+ },
32
+ 'header': {
33
+ margin: '-20px -24px 0px -24px',
34
+ display: 'flex',
35
+ alignItems: 'center',
36
+ justifyContent: 'space-between',
37
+ padding: '2px 2px 2px 14px',
38
+ fontSize: '20px',
39
+ backgroundColor: 'var(--mdc-theme-primary, #6200ee)',
40
+ color: 'var(--mdc-theme-on-primary, #fff)',
41
+ overflow: 'hidden'
42
+ },
43
+ 'main': {
44
+ margin: '0px -24px -20px -24px'
45
+ }
46
+ })
47
+
48
+ key = this.options.key
49
+ content = typeof this.options.Element === 'string' ? this.options.Element : new this.options.Element()
50
+
51
+ template = async () => {
52
+ // Открытый диалог может быть только один
53
+ this.id = 'sc-popup-dialog'
54
+ /** @type {import('@material/mwc-dialog').Dialog} */// @ts-ignore
55
+ this.dialog = oom
56
+ .mwcDialog({ hideActions: true }, oom
57
+ .header(oom
58
+ .span(this.options.title)
59
+ .mwcIconButton({ icon: 'close', onclick: () => this.close() }))
60
+ .main(this.content))
61
+ .dom
62
+
63
+ oom(this, this.dialog)
64
+
65
+ this.dialog.addEventListener('closed', () => this.closed())
66
+
67
+ await this.open()
68
+ }
69
+
70
+ /** Функция открытия диалога с асинхронной задержкой, что бы успело построиться дерево компонента */
71
+ async open() {
72
+ lastDialog = this
73
+ await new Promise(resolve => setTimeout(resolve))
74
+ this.dialog.show()
75
+ }
76
+
77
+ /** Функция закрытия диалога */
78
+ close() {
79
+ if (this.dialog) {
80
+ this.dialog.close()
81
+ }
82
+ }
83
+
84
+ /** Обработчик завершения закрытия одиалога */
85
+ closed() {
86
+ this.dialog = lastDialog = null
87
+ this.remove()
88
+ }
89
+
90
+ }
91
+
92
+ oom.define(PopupDialog)
93
+
94
+
95
+ /**
96
+ * Переключает открытый диалог с учетом уникального ключа диалога.
97
+ * Открывает с закрытием другого диалога, или скрывает если открыт тот же диалог
98
+ *
99
+ * @param {PopupDialogOptions} options Опции PopupDialog
100
+ */
101
+ export function toggleDialog(options) {
102
+ const exists = lastDialog && lastDialog.key === options.key
103
+
104
+ if (lastDialog) {
105
+ // Открытый диалог может быть только один
106
+ lastDialog.close()
107
+ }
108
+ if (!exists) {
109
+ oom(layout, new PopupDialog(options))
110
+ }
111
+ }
package/lib.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './lib/database.js'
2
+ export * from './lib/hotkeys.js'
3
+ export * from './lib/layout.js'
4
+ export * from './lib/popup-dialog.js'