@fiscozen/tab 0.1.11 → 1.0.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/CHANGELOG.md +32 -0
- package/package.json +9 -8
- package/src/FzTabs.vue +101 -57
- package/src/__tests__/FzTabs.spec.ts +851 -571
- package/src/__tests__/__snapshots__/FzTabs.spec.ts.snap +158 -44
- package/src/common.ts +35 -10
- package/src/components/FzTabButton.vue +72 -22
- package/src/components/FzTabPicker.vue +31 -25
- package/src/types.ts +29 -2
- package/dist/index.d.ts +0 -1
- package/dist/src/FzTab.vue.d.ts +0 -20
- package/dist/src/FzTabs.vue.d.ts +0 -45
- package/dist/src/common.d.ts +0 -12
- package/dist/src/components/FzTabButton.vue.d.ts +0 -56
- package/dist/src/components/FzTabPicker.vue.d.ts +0 -19
- package/dist/src/index.d.ts +0 -2
- package/dist/src/types.d.ts +0 -40
- package/dist/style.css +0 -1
- package/dist/tab.js +0 -1108
- package/dist/tab.umd.cjs +0 -1
- package/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @fiscozen/tab
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 98d491d: Updated FzTabs to reflect new design system specs
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
`FzTabs` doesn't automatically handle tab overflow; it is now controlled by the user via the `tabStyle` prop. Now is developer responsibility to handle the overflow of the tabs based on his use cases.
|
|
12
|
+
|
|
13
|
+
### NEW FEATURES
|
|
14
|
+
- New `tabStyle="fullWidth"` variant: the tab container stretches to fill the full available width and each tab expands equally with centered text
|
|
15
|
+
- The `tone` prop (`'neutral' | 'alert'`) is now set on individual `FzTab` components instead of the `FzTabs` container, allowing specific tabs to be highlighted independently
|
|
16
|
+
- New `environment` prop (`'backoffice' | 'frontoffice'`) for sizing, replacing the deprecated `size` prop
|
|
17
|
+
- New `tabStyle` prop (`'scroll' | 'picker' | 'fullWidth'`) to control tab style and overflow behavior
|
|
18
|
+
- The `change` event now also emits the selected button DOM element as a second argument: `(title: string, element: HTMLElement | null)`
|
|
19
|
+
|
|
20
|
+
### DEPRECATED FEATURES
|
|
21
|
+
- The `size` prop is deprecated: use `environment` instead
|
|
22
|
+
- The `horizontalOverflow` prop is deprecated: use `tabStyle` instead
|
|
23
|
+
|
|
24
|
+
### DOCUMENTATION
|
|
25
|
+
- Updated `FzTabs.mdx` documentation to reflect the new specifications
|
|
26
|
+
|
|
27
|
+
## 0.1.12
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 1a2df8c: Move @fiscozen/icons from dependencies to peerDependencies. Consumers now need to install @fiscozen/icons explicitly. This decouples icon updates from component version bumps.
|
|
32
|
+
- Updated dependencies [1a2df8c]
|
|
33
|
+
- @fiscozen/badge@1.0.1
|
|
34
|
+
|
|
3
35
|
## 0.1.11
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiscozen/tab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Design System Tab component",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [],
|
|
8
8
|
"author": "Cristian Barraco",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@fiscozen/
|
|
11
|
-
"@fiscozen/
|
|
12
|
-
"@fiscozen/style": "0.2.0"
|
|
10
|
+
"@fiscozen/badge": "1.0.1",
|
|
11
|
+
"@fiscozen/action": "1.1.1",
|
|
12
|
+
"@fiscozen/style": "0.2.0",
|
|
13
|
+
"@fiscozen/composables": "1.0.1"
|
|
13
14
|
},
|
|
14
15
|
"peerDependencies": {
|
|
15
16
|
"tailwindcss": "^3.4.1",
|
|
16
|
-
"vue": "^3.4.13"
|
|
17
|
+
"vue": "^3.4.13",
|
|
18
|
+
"@fiscozen/icons": "^0.1.37"
|
|
17
19
|
},
|
|
18
20
|
"devDependencies": {
|
|
19
21
|
"@rushstack/eslint-patch": "^1.3.3",
|
|
@@ -31,10 +33,9 @@
|
|
|
31
33
|
"vite-plugin-dts": "^3.8.3",
|
|
32
34
|
"vitest": "^1.2.0",
|
|
33
35
|
"vue-tsc": "^1.8.25",
|
|
34
|
-
"@fiscozen/eslint-config": "^0.1.0",
|
|
35
|
-
"@fiscozen/prettier-config": "^0.1.0",
|
|
36
36
|
"@fiscozen/tsconfig": "^0.1.0",
|
|
37
|
-
"@fiscozen/
|
|
37
|
+
"@fiscozen/eslint-config": "^0.1.0",
|
|
38
|
+
"@fiscozen/prettier-config": "^0.1.0"
|
|
38
39
|
},
|
|
39
40
|
"license": "MIT",
|
|
40
41
|
"scripts": {
|
package/src/FzTabs.vue
CHANGED
|
@@ -2,20 +2,29 @@
|
|
|
2
2
|
<div :class="computedClassWrapper">
|
|
3
3
|
<div :class="['flex', computedClass]">
|
|
4
4
|
<div
|
|
5
|
-
:class="[
|
|
5
|
+
:class="[
|
|
6
|
+
staticTabContainerClass,
|
|
7
|
+
computedClass,
|
|
8
|
+
overflowContainerClass,
|
|
9
|
+
]"
|
|
6
10
|
ref="tabContainer"
|
|
7
|
-
@wheel="onWheel"
|
|
8
11
|
>
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
<FzTabPicker
|
|
13
|
+
v-if="effectiveTabStyle === 'picker'"
|
|
14
|
+
:tabs="tabs"
|
|
15
|
+
:environment="effectiveSize"
|
|
16
|
+
/>
|
|
12
17
|
<template v-else>
|
|
13
18
|
<FzTabButton
|
|
14
19
|
v-for="tab in tabs"
|
|
15
20
|
:tab="tab"
|
|
16
21
|
:key="tab.title"
|
|
17
|
-
:
|
|
22
|
+
:environment="effectiveSize"
|
|
18
23
|
:maxWidth="tab.maxWidth"
|
|
24
|
+
:tone="tab.tone"
|
|
25
|
+
type="tab"
|
|
26
|
+
:readonly="false"
|
|
27
|
+
:fullWidth="effectiveTabStyle === 'fullWidth'"
|
|
19
28
|
/>
|
|
20
29
|
</template>
|
|
21
30
|
<slot name="tabs-container-end" />
|
|
@@ -27,24 +36,18 @@
|
|
|
27
36
|
</template>
|
|
28
37
|
|
|
29
38
|
<script setup lang="ts">
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
ref,
|
|
33
|
-
onMounted,
|
|
34
|
-
provide,
|
|
35
|
-
useSlots,
|
|
36
|
-
watch,
|
|
37
|
-
VNode,
|
|
38
|
-
onBeforeUnmount,
|
|
39
|
-
} from "vue";
|
|
40
|
-
import { FzTabsProps, FzTabProps } from "./types";
|
|
39
|
+
import { computed, ref, onMounted, provide, useSlots, watch, VNode } from "vue";
|
|
40
|
+
import { FzTabsProps, FzTabProps, FzTabStyle } from "./types";
|
|
41
41
|
import FzTabPicker from "./components/FzTabPicker.vue";
|
|
42
42
|
import FzTabButton from "./components/FzTabButton.vue";
|
|
43
43
|
import FzTab from "./FzTab.vue";
|
|
44
|
+
import { debugWarn, mapSizeToEnvironment } from "./common";
|
|
44
45
|
|
|
45
46
|
const props = withDefaults(defineProps<FzTabsProps>(), {
|
|
46
|
-
size: "sm",
|
|
47
47
|
vertical: false,
|
|
48
|
+
horizontalOverflow: undefined,
|
|
49
|
+
tabStyle: "scroll",
|
|
50
|
+
isDebug: false,
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
const emit = defineEmits(["change"]);
|
|
@@ -52,7 +55,6 @@ const emit = defineEmits(["change"]);
|
|
|
52
55
|
const slots = useSlots();
|
|
53
56
|
|
|
54
57
|
const tabContainer = ref<HTMLElement>();
|
|
55
|
-
const isOverflowing = ref(false);
|
|
56
58
|
const selectedTab = ref("");
|
|
57
59
|
provide("selectedTab", selectedTab);
|
|
58
60
|
|
|
@@ -80,8 +82,13 @@ const tabs = computed(() => {
|
|
|
80
82
|
.filter((el): el is FzTabProps => el != null);
|
|
81
83
|
});
|
|
82
84
|
|
|
83
|
-
const staticTabContainerClass =
|
|
84
|
-
"tab-container flex rounded-lg
|
|
85
|
+
const staticTabContainerClass = computed(() => {
|
|
86
|
+
const base = "tab-container flex rounded-lg p-2 bg-grey-100";
|
|
87
|
+
if (effectiveTabStyle.value === "fullWidth") {
|
|
88
|
+
return `${base} w-full`;
|
|
89
|
+
}
|
|
90
|
+
return `${base} w-fit max-w-full w-full sm:w-auto`;
|
|
91
|
+
});
|
|
85
92
|
|
|
86
93
|
const computedClass = computed(() => [
|
|
87
94
|
props.vertical ? "flex-col" : "flex-row",
|
|
@@ -92,24 +99,81 @@ const computedClassWrapper = computed(() => [
|
|
|
92
99
|
!props.vertical ? "flex-col" : "flex-row",
|
|
93
100
|
]);
|
|
94
101
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
102
|
+
const overflowContainerClass = computed(() => {
|
|
103
|
+
if (effectiveTabStyle.value === "scroll") {
|
|
104
|
+
return "overflow-x-auto";
|
|
105
|
+
}
|
|
106
|
+
return "";
|
|
107
|
+
});
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Determines the effective size based on environment or deprecated size prop
|
|
111
|
+
* Priority: environment prop > size prop (deprecated) > default 'sm'
|
|
112
|
+
*/
|
|
113
|
+
const effectiveSize = computed<"frontoffice" | "backoffice">(() => {
|
|
114
|
+
if (props.environment) {
|
|
115
|
+
return props.environment;
|
|
116
|
+
}
|
|
117
|
+
if (props.size) {
|
|
118
|
+
return mapSizeToEnvironment[props.size];
|
|
119
|
+
}
|
|
120
|
+
return "backoffice";
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Determines the effective overflow mode
|
|
125
|
+
* Priority: overflowMode prop > horizontalOverflow prop (deprecated) > default 'scroll'
|
|
126
|
+
*/
|
|
127
|
+
const effectiveTabStyle = computed<FzTabStyle>(() => {
|
|
128
|
+
if (
|
|
129
|
+
props.horizontalOverflow !== undefined &&
|
|
130
|
+
props.horizontalOverflow === false
|
|
131
|
+
)
|
|
132
|
+
return "picker";
|
|
133
|
+
|
|
134
|
+
return props.tabStyle;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Deprecation warning for size prop
|
|
139
|
+
*/
|
|
140
|
+
watch(
|
|
141
|
+
() => props.size,
|
|
142
|
+
(size) => {
|
|
143
|
+
if (size !== undefined) {
|
|
144
|
+
debugWarn(
|
|
145
|
+
`[FzTabs] The "size" prop is deprecated and will be removed in a future version. ` +
|
|
146
|
+
`Please use environment="backoffice" instead of size="${size}".`,
|
|
147
|
+
props.isDebug,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{ immediate: true },
|
|
152
|
+
);
|
|
104
153
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Deprecation warning for horizontalOverflow prop
|
|
156
|
+
*/
|
|
157
|
+
watch(
|
|
158
|
+
() => props.horizontalOverflow,
|
|
159
|
+
(horizontalOverflow) => {
|
|
160
|
+
// Only warn if horizontalOverflow is explicitly set to true
|
|
161
|
+
// (false is treated as not set, since the default behavior is no overflow)
|
|
162
|
+
if (horizontalOverflow !== undefined) {
|
|
163
|
+
debugWarn(
|
|
164
|
+
`[FzTabs] The "horizontalOverflow" prop is deprecated and will be removed in a future version. `,
|
|
165
|
+
props.isDebug,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{ immediate: true },
|
|
170
|
+
);
|
|
108
171
|
|
|
109
172
|
onMounted(() => {
|
|
110
173
|
if (tabs.value.length === 0) {
|
|
111
|
-
|
|
174
|
+
debugWarn(
|
|
112
175
|
"[Fiscozen Design System]: FzTabs must have at least one FzTab child",
|
|
176
|
+
props.isDebug,
|
|
113
177
|
);
|
|
114
178
|
} else {
|
|
115
179
|
const findSelected = tabs.value.find((tab) => tab.initialSelected);
|
|
@@ -124,18 +188,12 @@ onMounted(() => {
|
|
|
124
188
|
.filter((title, index, self) => self.indexOf(title) !== index);
|
|
125
189
|
|
|
126
190
|
if (duplicateTitles.length) {
|
|
127
|
-
|
|
191
|
+
debugWarn(
|
|
128
192
|
`[Fiscozen Design System]: FzTabs has duplicate titles: ${duplicateTitles.join(", ")}, this may cause unexpected behavior.`,
|
|
193
|
+
props.isDebug,
|
|
129
194
|
);
|
|
130
195
|
}
|
|
131
196
|
}
|
|
132
|
-
|
|
133
|
-
updateIsOverflowing();
|
|
134
|
-
window.addEventListener("resize", updateIsOverflowing);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
onBeforeUnmount(() => {
|
|
138
|
-
window.removeEventListener("resize", updateIsOverflowing);
|
|
139
197
|
});
|
|
140
198
|
|
|
141
199
|
watch(
|
|
@@ -148,25 +206,11 @@ watch(
|
|
|
148
206
|
tabs.value[0].title;
|
|
149
207
|
}
|
|
150
208
|
|
|
151
|
-
const selectedTabElement = tabContainer.value
|
|
209
|
+
const selectedTabElement = tabContainer.value?.querySelector(
|
|
152
210
|
`button[title="${selectedTab.value}"]`,
|
|
153
211
|
);
|
|
154
212
|
|
|
155
|
-
|
|
156
|
-
selectedTabElement.scrollIntoView({
|
|
157
|
-
behavior: "smooth",
|
|
158
|
-
block: "nearest",
|
|
159
|
-
inline: "center",
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
emit("change", selectedTab.value);
|
|
213
|
+
emit("change", selectedTab.value, selectedTabElement);
|
|
164
214
|
},
|
|
165
215
|
);
|
|
166
216
|
</script>
|
|
167
|
-
<style scoped>
|
|
168
|
-
.tab-container::-webkit-scrollbar {
|
|
169
|
-
width: 0em;
|
|
170
|
-
height: 0em;
|
|
171
|
-
}
|
|
172
|
-
</style>
|