@neovici/cosmoz-tabs 7.6.0 → 8.1.0
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/package.json +13 -14
- package/src/cosmoz-tab-card.js +76 -21
- package/src/cosmoz-tab.js +1 -1
- package/src/cosmoz-tabs.js +1 -1
- package/src/next/cosmoz-tab.js +1 -1
- package/src/next/cosmoz-tabs.js +1 -1
- package/src/next/use-tabs.js +1 -1
- package/src/render.js +39 -26
- package/src/use-tab.js +1 -1
- package/src/use-tabs.js +1 -1
- package/src/utils.js +26 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-tabs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "A multi views container element that allow navigation between the views using tabs or an accordion.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components"
|
|
@@ -68,29 +68,28 @@
|
|
|
68
68
|
"./next/*": "./src/next/*"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@neovici/cosmoz-
|
|
72
|
-
"@neovici/cosmoz-
|
|
71
|
+
"@neovici/cosmoz-collapse": "^1.3.0",
|
|
72
|
+
"@neovici/cosmoz-router": "^11.0.0",
|
|
73
|
+
"@neovici/cosmoz-utils": "^6.0.0",
|
|
74
|
+
"@pionjs/pion": "^2.0.0",
|
|
73
75
|
"@polymer/iron-icon": "^3.0.0",
|
|
74
76
|
"@polymer/iron-icons": "^3.0.0",
|
|
75
77
|
"compute-scroll-into-view": "^1.0.17",
|
|
76
|
-
"
|
|
77
|
-
"lit-html": "^2.0.0"
|
|
78
|
+
"lit-html": "^2.0.0 || ^3.0.0"
|
|
78
79
|
},
|
|
79
80
|
"devDependencies": {
|
|
80
|
-
"@commitlint/cli": "^
|
|
81
|
-
"@commitlint/config-conventional": "^
|
|
81
|
+
"@commitlint/cli": "^18.0.0",
|
|
82
|
+
"@commitlint/config-conventional": "^18.0.0",
|
|
82
83
|
"@neovici/cfg": "^1.11.0",
|
|
83
|
-
"@open-wc/testing": "^
|
|
84
|
+
"@open-wc/testing": "^4.0.0",
|
|
84
85
|
"@polymer/iron-list": "^3.1.0",
|
|
85
86
|
"@semantic-release/changelog": "^6.0.0",
|
|
86
87
|
"@semantic-release/git": "^10.0.0",
|
|
87
88
|
"@storybook/storybook-deployer": "^2.8.0",
|
|
88
|
-
"@web/dev-server-storybook": "^0.
|
|
89
|
-
"@web/test-runner": "^0.15.0",
|
|
90
|
-
"eslint-import-resolver-typescript": "^3.2.7",
|
|
89
|
+
"@web/dev-server-storybook": "^2.0.0",
|
|
91
90
|
"husky": "^8.0.0",
|
|
92
|
-
"semantic-release": "^
|
|
93
|
-
"sinon": "^
|
|
94
|
-
"typescript": "^
|
|
91
|
+
"semantic-release": "^22.0.0",
|
|
92
|
+
"sinon": "^17.0.0",
|
|
93
|
+
"typescript": "^5.0.0"
|
|
95
94
|
}
|
|
96
95
|
}
|
package/src/cosmoz-tab-card.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
// @license Copyright (C) 2015 Neovici AB - Apache 2 License
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from '
|
|
2
|
+
import { html, component, useState, useEffect } from '@pionjs/pion';
|
|
3
|
+
import '@neovici/cosmoz-collapse';
|
|
4
|
+
import { when } from 'lit-html/directives/when.js';
|
|
5
|
+
import { css } from './utils';
|
|
6
|
+
|
|
7
|
+
const collapseIcon = html`<svg
|
|
8
|
+
width="16"
|
|
9
|
+
height="16"
|
|
10
|
+
viewBox="0 0 16 16"
|
|
11
|
+
fill="none"
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
>
|
|
14
|
+
<path d="M5 1L10 8L5 15" stroke="#101010" stroke-width="1.5" />
|
|
15
|
+
</svg>`;
|
|
6
16
|
|
|
7
17
|
/**
|
|
8
18
|
|
|
@@ -22,8 +32,40 @@ Custom property | Description | Default
|
|
|
22
32
|
`--cosmoz-tab-card-content-line-height` | Card content line height | `initial`
|
|
23
33
|
`--cosmoz-tab-card-content-padding` | Card content padding | `initial`
|
|
24
34
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
|
|
36
|
+
const CosmozTabCard = (host) => {
|
|
37
|
+
const { heading, collapsable, collapsed: isCollapsed } = host,
|
|
38
|
+
[collapsed, setCollapsed] = useState(Boolean(isCollapsed)),
|
|
39
|
+
toggleCollapsed = () => {
|
|
40
|
+
if (!collapsable) return;
|
|
41
|
+
return setCollapsed((c) => !c);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
host.toggleAttribute('collapsed', collapsed);
|
|
46
|
+
}, [collapsed]);
|
|
47
|
+
|
|
48
|
+
return html`<div id="header" part="header">
|
|
49
|
+
${when(
|
|
50
|
+
collapsable,
|
|
51
|
+
() => html`
|
|
52
|
+
<div @click=${toggleCollapsed} part="collapse-icon">
|
|
53
|
+
<slot name="collapse-icon">${collapseIcon}</slot>
|
|
54
|
+
</div>
|
|
55
|
+
`,
|
|
56
|
+
)}
|
|
57
|
+
<h1 class="heading" @click=${toggleCollapsed} part="heading">
|
|
58
|
+
${heading}<slot name="after-title"></slot>
|
|
59
|
+
</h1>
|
|
60
|
+
<slot name="card-actions"></slot>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div id="content" part="content">
|
|
64
|
+
<cosmoz-collapse ?opened=${!collapsed}><slot></slot></cosmoz-collapse>
|
|
65
|
+
</div>`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const style = css`
|
|
27
69
|
:host {
|
|
28
70
|
display: block;
|
|
29
71
|
position: relative;
|
|
@@ -34,7 +76,10 @@ const CosmozTabCard = ({ heading }) => html`
|
|
|
34
76
|
align-self: flex-start;
|
|
35
77
|
padding: var(--cosmoz-tab-card-padding, 0);
|
|
36
78
|
width: var(--cosmoz-tab-card-width, 300px);
|
|
37
|
-
box-shadow: var(
|
|
79
|
+
box-shadow: var(
|
|
80
|
+
--cosmoz-shadow-2dp,
|
|
81
|
+
var(--shadow-elevation-2dp_-_box-shadow, 0 2px 4px 0 #e5e5e5)
|
|
82
|
+
);
|
|
38
83
|
}
|
|
39
84
|
|
|
40
85
|
#content {
|
|
@@ -45,9 +90,9 @@ const CosmozTabCard = ({ heading }) => html`
|
|
|
45
90
|
#header {
|
|
46
91
|
display: flex;
|
|
47
92
|
align-items: center;
|
|
93
|
+
gap: 8px;
|
|
48
94
|
background-color: #fff;
|
|
49
|
-
|
|
50
|
-
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
95
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
51
96
|
}
|
|
52
97
|
|
|
53
98
|
.heading {
|
|
@@ -55,19 +100,29 @@ const CosmozTabCard = ({ heading }) => html`
|
|
|
55
100
|
font-size: 17px;
|
|
56
101
|
font-weight: 400;
|
|
57
102
|
flex: 1;
|
|
58
|
-
margin: 0.67em 0 0;
|
|
59
103
|
}
|
|
60
|
-
</style>
|
|
61
104
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
105
|
+
[part='collapse-icon'] {
|
|
106
|
+
order: var(--cosmoz-tab-card-collapse-icon-order);
|
|
107
|
+
transition: transform 250ms linear;
|
|
108
|
+
transform: rotate(90deg);
|
|
109
|
+
}
|
|
66
110
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
111
|
+
:host([collapsed]) [part='collapse-icon'] {
|
|
112
|
+
transform: rotate(0deg);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:host([collapsable]) [part='collapse-icon'],
|
|
116
|
+
:host([collapsable]) .heading {
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
user-select: none;
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
70
121
|
|
|
71
|
-
customElements.define(
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
customElements.define(
|
|
123
|
+
'cosmoz-tab-card',
|
|
124
|
+
component(CosmozTabCard, {
|
|
125
|
+
observedAttributes: ['heading', 'collapsable', 'collapsed'],
|
|
126
|
+
styleSheets: [style],
|
|
127
|
+
}),
|
|
128
|
+
);
|
package/src/cosmoz-tab.js
CHANGED
package/src/cosmoz-tabs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @license Copyright (C) 2015 Neovici AB - Apache 2 License
|
|
2
|
-
import { html, component } from '
|
|
2
|
+
import { html, component } from '@pionjs/pion';
|
|
3
3
|
import { useTabs } from './use-tabs';
|
|
4
4
|
import { style, renderTab } from './render';
|
|
5
5
|
import './cosmoz-tab.js';
|
package/src/next/cosmoz-tab.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { component, useEffect, useLayoutEffect } from '
|
|
1
|
+
import { component, useEffect, useLayoutEffect } from '@pionjs/pion';
|
|
2
2
|
import { html, nothing } from 'lit-html';
|
|
3
3
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
4
4
|
import computeScroll from 'compute-scroll-into-view';
|
package/src/next/cosmoz-tabs.js
CHANGED
package/src/next/use-tabs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable import/group-exports */
|
|
2
|
-
import { html, useMemo, useCallback, useRef } from '
|
|
2
|
+
import { html, useMemo, useCallback, useRef } from '@pionjs/pion';
|
|
3
3
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
4
4
|
/* eslint-disable-next-line import/no-unresolved */
|
|
5
5
|
import { useHashParam } from '@neovici/cosmoz-router/use-hash-param';
|
package/src/render.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html } from '
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
2
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
3
3
|
import { getIcon, getIconStyle } from './utils';
|
|
4
4
|
|
|
@@ -100,29 +100,42 @@ const style = `
|
|
|
100
100
|
color: #ffffff;
|
|
101
101
|
text-align: center;
|
|
102
102
|
}`,
|
|
103
|
+
renderTab =
|
|
104
|
+
({ selectedTab, onSelect, href }) =>
|
|
105
|
+
(tab, i, tabs) => {
|
|
106
|
+
const isSelected = selectedTab === tab,
|
|
107
|
+
icon = getIcon(tab, isSelected);
|
|
108
|
+
return html`<a
|
|
109
|
+
class="tab"
|
|
110
|
+
tabindex="-1"
|
|
111
|
+
role="tab"
|
|
112
|
+
part=${[
|
|
113
|
+
'tab',
|
|
114
|
+
i === 0 && 'first-tab',
|
|
115
|
+
i === tabs.length - 1 && 'last-tab',
|
|
116
|
+
isSelected && 'selected-tab',
|
|
117
|
+
]
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.join(' ')}
|
|
120
|
+
?hidden=${tab.hidden}
|
|
121
|
+
?disabled=${tab.disabled}
|
|
122
|
+
?aria-selected=${isSelected}
|
|
123
|
+
@click=${onSelect}
|
|
124
|
+
.tab=${tab}
|
|
125
|
+
href=${ifDefined(href(tab))}
|
|
126
|
+
>
|
|
127
|
+
${icon
|
|
128
|
+
? html`<iron-icon
|
|
129
|
+
class="icon"
|
|
130
|
+
icon=${icon}
|
|
131
|
+
style=${getIconStyle(tab)}
|
|
132
|
+
></iron-icon>`
|
|
133
|
+
: ''}
|
|
134
|
+
<span>${tab.heading}</span>
|
|
135
|
+
${tab.badge
|
|
136
|
+
? html`<div class="badge" title=${tab.badge}>${tab.badge}</div>`
|
|
137
|
+
: ''}
|
|
138
|
+
</a>`;
|
|
139
|
+
};
|
|
103
140
|
|
|
104
|
-
|
|
105
|
-
selectedTab,
|
|
106
|
-
onSelect,
|
|
107
|
-
href
|
|
108
|
-
}) => (tab, i, tabs) => {
|
|
109
|
-
const isSelected = selectedTab === tab,
|
|
110
|
-
icon = getIcon(tab, isSelected);
|
|
111
|
-
return html`<a class="tab" tabindex="-1" role="tab"
|
|
112
|
-
part=${ ['tab', i === 0 && 'first-tab', i === tabs.length - 1 && 'last-tab', isSelected && 'selected-tab'].filter(Boolean).join(' ') }
|
|
113
|
-
?hidden=${ tab.hidden } ?disabled=${ tab.disabled }
|
|
114
|
-
?aria-selected=${ isSelected }
|
|
115
|
-
@click=${ onSelect }
|
|
116
|
-
.tab=${ tab }
|
|
117
|
-
href=${ ifDefined(href(tab)) }
|
|
118
|
-
>
|
|
119
|
-
${ icon ? html `<iron-icon class="icon" icon=${ icon } style=${ getIconStyle(tab) }></iron-icon>` : '' }
|
|
120
|
-
<span>${ tab.heading }</span>
|
|
121
|
-
${ tab.badge ? html`<div class="badge" title=${ tab.badge }>${ tab.badge }</div>` : '' }
|
|
122
|
-
</a>`;
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
style,
|
|
127
|
-
renderTab
|
|
128
|
-
};
|
|
141
|
+
export { style, renderTab };
|
package/src/use-tab.js
CHANGED
package/src/use-tabs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo, useCallback } from '
|
|
1
|
+
import { useState, useEffect, useMemo, useCallback } from '@pionjs/pion';
|
|
2
2
|
import { notifyProperty } from '@neovici/cosmoz-utils/hooks/use-notify-property';
|
|
3
3
|
/* eslint-disable-next-line import/no-unresolved */
|
|
4
4
|
import { useHashParam, link } from '@neovici/cosmoz-router/use-hash-param';
|
package/src/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { tagged } from '@neovici/cosmoz-utils';
|
|
2
2
|
|
|
3
|
+
const isValid = (tab) => !tab.hidden && !tab.disabled,
|
|
3
4
|
/**
|
|
4
5
|
* Gets the element icon name.
|
|
5
6
|
*
|
|
@@ -7,10 +8,9 @@ const isValid = tab => !tab.hidden && !tab.disabled,
|
|
|
7
8
|
* @param {boolean} isSelected Is the tab selected
|
|
8
9
|
* @returns {string} Name of the element icon.
|
|
9
10
|
*/
|
|
10
|
-
getIcon = (tab, isSelected) =>
|
|
11
|
-
|
|
12
|
-
getName = tab => tab.getAttribute('name'),
|
|
13
|
-
|
|
11
|
+
getIcon = (tab, isSelected) =>
|
|
12
|
+
isSelected ? tab.selectedIcon ?? tab.icon : tab.icon,
|
|
13
|
+
getName = (tab) => tab.getAttribute('name'),
|
|
14
14
|
/**
|
|
15
15
|
* Gets the element icon style property and value if icon color is
|
|
16
16
|
* set, otherwise return nothing.
|
|
@@ -18,19 +18,16 @@ const isValid = tab => !tab.hidden && !tab.disabled,
|
|
|
18
18
|
* @param {HTMLElement} tab The tab to compute icon stype for
|
|
19
19
|
* @returns {string/void} Style color property and value for the icon.
|
|
20
20
|
*/
|
|
21
|
-
getIconStyle = tab => {
|
|
21
|
+
getIconStyle = (tab) => {
|
|
22
22
|
const iconColor = tab.iconColor ?? '#15b0d3';
|
|
23
|
-
return ['color: ' + iconColor, tab.iconStyle]
|
|
24
|
-
.join(';');
|
|
23
|
+
return ['color: ' + iconColor, tab.iconStyle].join(';');
|
|
25
24
|
},
|
|
26
|
-
|
|
27
|
-
valid = tabs => tabs.find(isValid),
|
|
28
|
-
|
|
25
|
+
valid = (tabs) => tabs.find(isValid),
|
|
29
26
|
choose = (tabs, selected) => {
|
|
30
27
|
if (selected == null) {
|
|
31
28
|
return valid(tabs);
|
|
32
29
|
}
|
|
33
|
-
const selectedTab = tabs.find(tab => getName(tab) === selected);
|
|
30
|
+
const selectedTab = tabs.find((tab) => getName(tab) === selected);
|
|
34
31
|
if (selectedTab == null) {
|
|
35
32
|
return valid(tabs);
|
|
36
33
|
}
|
|
@@ -44,21 +41,21 @@ const isValid = tab => !tab.hidden && !tab.disabled,
|
|
|
44
41
|
}
|
|
45
42
|
return fallback;
|
|
46
43
|
},
|
|
47
|
-
collect = slot
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
collect = (slot) =>
|
|
45
|
+
slot.assignedElements().flatMap((el) => {
|
|
46
|
+
if (el.matches('cosmoz-tab')) {
|
|
47
|
+
return [el];
|
|
48
|
+
}
|
|
49
|
+
if (el.matches('slot')) {
|
|
50
|
+
return collect(el);
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
}),
|
|
54
|
+
sheet = (...styles) => {
|
|
55
|
+
const cs = new CSSStyleSheet();
|
|
56
|
+
cs.replaceSync(styles.join(''));
|
|
57
|
+
return cs;
|
|
58
|
+
},
|
|
59
|
+
css = (strings, ...values) => sheet(tagged(strings, ...values));
|
|
56
60
|
|
|
57
|
-
export {
|
|
58
|
-
choose,
|
|
59
|
-
collect,
|
|
60
|
-
isValid,
|
|
61
|
-
getIcon,
|
|
62
|
-
getIconStyle,
|
|
63
|
-
getName
|
|
64
|
-
};
|
|
61
|
+
export { choose, collect, isValid, getIcon, getIconStyle, getName, sheet, css };
|