@mptw/skylens-ui 1.3.15 → 1.4.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.
@@ -0,0 +1,151 @@
1
+ <template lang="pug">
2
+ Transition(
3
+ @before-enter='onBeforeEnter',
4
+ @enter='onEnter',
5
+ @after-enter='onAfterEnter',
6
+ @enter-cancelled='onAfterEnter',
7
+ @before-leave='onBeforeLeave',
8
+ @leave='onLeave',
9
+ @after-leave='onAfterLeave',
10
+ @leave-cancelled='onAfterLeave',
11
+ )
12
+ .notification(v-if='isShow')
13
+ .notification-wrapper {{ content }}
14
+ </template>
15
+
16
+ <script lang="ts">
17
+ import gsap from 'gsap';
18
+
19
+ export default defineComponent({
20
+ name: 'SLNotification',
21
+ props: {
22
+ isShow: {
23
+ type: Boolean,
24
+ default: false,
25
+ },
26
+ content: {
27
+ type: String,
28
+ default: '',
29
+ },
30
+ },
31
+ emits: ['update:isShow'],
32
+ setup(props, { emit }) {
33
+ const { isShow } = toRefs(props);
34
+
35
+ let timeoutId: any = null;
36
+
37
+ function onBeforeEnter(el: Element) {
38
+ const wrapperEl = el.querySelector('.notification-wrapper');
39
+
40
+ if (wrapperEl) {
41
+ gsap.set(wrapperEl, {
42
+ alpha: 0
43
+ });
44
+ }
45
+ }
46
+
47
+ function onEnter(el: Element, done: () => void) {
48
+ const wrapperEl = el.querySelector('.notification-wrapper');
49
+
50
+ if (wrapperEl) {
51
+ gsap.to(wrapperEl, {
52
+ alpha: 1,
53
+ duration: 0.3,
54
+ onComplete: () => {
55
+ done();
56
+ }
57
+ })
58
+ } else {
59
+ done();
60
+ }
61
+ }
62
+
63
+ function onAfterEnter(el: Element) {
64
+ const wrapperEl = el.querySelector('.notification-wrapper');
65
+
66
+ if (wrapperEl) {
67
+ gsap.set(wrapperEl, {
68
+ alpha: 1
69
+ });
70
+ }
71
+ }
72
+
73
+ function onBeforeLeave(el: Element) {
74
+ const wrapperEl = el.querySelector('.notification-wrapper');
75
+
76
+ if (wrapperEl) {
77
+ gsap.set(wrapperEl, {
78
+ alpha: 1
79
+ });
80
+ }
81
+ }
82
+
83
+ function onLeave(el: Element, done: () => void) {
84
+ const wrapperEl = el.querySelector('.notification-wrapper');
85
+
86
+ if (wrapperEl) {
87
+ gsap.to(wrapperEl, {
88
+ alpha: 0,
89
+ duration: 0.3,
90
+ onComplete: () => {
91
+ done();
92
+ }
93
+ })
94
+ } else {
95
+ done();
96
+ }
97
+ }
98
+
99
+ function onAfterLeave(el: Element) {
100
+ const wrapperEl = el.querySelector('.notification-wrapper');
101
+
102
+ if (wrapperEl) {
103
+ gsap.set(wrapperEl, {
104
+ alpha: 0
105
+ });
106
+ }
107
+ }
108
+
109
+ function delayHide() {
110
+ if (timeoutId) {
111
+ clearTimeout(timeoutId);
112
+ }
113
+ timeoutId = null;
114
+
115
+ timeoutId = setTimeout(() => {
116
+ emit('update:isShow', false);
117
+ }, 2000);
118
+ }
119
+
120
+ watch(isShow, () => {
121
+ if (isShow.value) {
122
+ delayHide();
123
+ }
124
+ });
125
+
126
+ onBeforeUnmount(() => {
127
+ if (timeoutId) {
128
+ clearTimeout(timeoutId);
129
+ }
130
+ timeoutId = null;
131
+ })
132
+
133
+ return {
134
+ onBeforeEnter,
135
+ onEnter,
136
+ onAfterEnter,
137
+ onBeforeLeave,
138
+ onLeave,
139
+ onAfterLeave,
140
+ };
141
+ },
142
+ });
143
+ </script>
144
+
145
+ <style lang="stylus">
146
+ .notification
147
+ @apply s('z-[100]') fixed top-0 left-0 w-full h-full pointer-events-none
148
+
149
+ &-wrapper
150
+ @apply absolute s('top-1/2') s('left-1/2') p-4 s('bg-backdrop/80') rounded text-base text-white s('-translate-x-1/2') s('-translate-y-1/2') shadow-popup-sm
151
+ </style>
@@ -1,428 +1,430 @@
1
1
  <template lang="pug">
2
- SLSitePage.m03-02p-page
3
- ClientOnly
4
- Teleport(to="#app-header-welcome-message") 受眾行為內單元提供單次的資料分析,可隨時查看歷史分析結果
5
- Teleport(to='#header-breadcrumbs')
6
- SLBreadcrumbs(:items='["受眾試算"]' info="依照設定的投放條件,在媒體投放前試算可接觸的受眾數量")
7
- template(#site-page-header)
8
- .site-page-header
9
- .site-page-header-left
10
- .site-page-title 受眾試算
11
- .site-page-desc
12
- span 依照設定的受眾條件,在媒體投放前試算可接觸的受眾數量
13
- a(href='javascript:;')
14
- SLIcon(icon='book')
15
- span 單元導覽
16
- .site-page-actions
17
- SLButton(title='新增受眾包', post-icon='chevron-right', color='primary' class='create-btn')
18
- .site-page-header-right
19
- img(src='~/assets/images/m03/02p/m0302p-page-logo.svg')
20
- SLNewTabs(:type='5')
21
- template(#tabs-nav-right)
22
- .inline-flex.items-center.space-x-4
23
- SLSearchInput(
24
- size='sm',
25
- placeholder='搜尋標題名稱(部分字元即可)',
26
- class='m0302p-search-input'
27
- )
28
- SLTab(title='受眾列表 (125)')
29
- SLCard.audience-package-card
30
- .audience-package
31
- .audience-package-header
32
- .header-left
33
- SLButton(
34
- title='新增受眾包',
35
- color='primary',
36
- size='lg',
37
- @click='onClickedAdd'
38
- )
39
- .header-right
40
- SLPagination(
41
- v-if='totalCount > 0',
42
- :total='totalCount',
43
- :perPage='perPage',
44
- :page='currentPage',
45
- :showInfo='true'
46
- @update:perPage='onUpdatedPerPage'
47
- @update:page='onUpdatedPage'
48
- )
49
- .audience-package-body
50
- template(v-if='tasks.length > 0')
51
- ModuleM12AudiencePackageListItem(
52
- v-for='task in tasks',
53
- :task='task',
54
- :key='task.id',
55
- @delete='onClickedDelete',
56
- @repack='onClickedRepack'
57
- )
58
- template(v-else) 沒有任何受眾包
59
- .audience-package-footer
60
- SLPagination(
61
- v-if='totalCount > 0',
62
- :total='totalCount',
63
- :perPage='perPage',
64
- :page='currentPage',
65
- :showInfo='true'
66
- @update:perPage='onUpdatedPerPage'
67
- @update:page='onUpdatedPage'
68
- )
69
- SLTab(title='投放 (125)')
70
- ClientOnly
71
- Teleport(to="#popup")
72
- SLConfirmModal(
73
- v-model:show='isShowDeleteConfirmModal',
74
- title='刪除受眾包',
75
- confirmButtonTitle='刪除',
76
- confirmButtonColor='danger',
77
- confirmButtonVariant='',
78
- modalClass='m12-delete-confirm-modal',
79
- @confirm='onDeleteApply',
80
- data-cy="delete-confirm-modal"
2
+ .tabs(:class='tabsClass')
3
+ .tabs-nav(
4
+ v-show="!tabItemsOversize"
5
+ :class="{ show: !tabItemsOversize }"
6
+ )
7
+ .tabs-nav-left(ref='tabsNavLeftEl')
8
+ SLDistributor(
9
+ tag='ul',
10
+ :header='true',
11
+ :changeTabTo='changeTabTo',
12
+ ref='navComp'
81
13
  )
82
- SLIcon(icon='exclamation-triangle')
83
- p 確定要刪除此受眾包嗎?
14
+ slot
15
+ .tabs-nav-right(v-if='(type === 1 || type === 5) && $slots["tabs-nav-right"]')
16
+ slot(name='tabs-nav-right')
17
+ .tabs-content
18
+ SLDistributor
19
+ .tabs-content-header(v-show="tabItemsOversize")
20
+ .tabs-content-header-left
21
+ SLDropdown.tabs-dropdown(
22
+ :title='currentTab',
23
+ v-model:showDropdown='showDropdown',
24
+ :class='{ active: showDropdown }',
25
+ )
26
+ SLDropdownItem(
27
+ v-for='(tabTitle, i) in tabTitles',
28
+ :title='tabTitle',
29
+ :class='{ active: i === activeTabIndex }',
30
+ @click='onClickedTab(i)',
31
+ :key='`${tabTitle}-${i}`'
32
+ )
33
+ .tabs-content-header-right(v-if='$slots["tabs-nav-right"]')
34
+ slot(name='tabs-nav-right')
35
+ .tabs-content-body(ref='tabsContentBody')
36
+ slot
84
37
  </template>
85
38
 
86
39
  <script lang="ts">
87
- import uniqueId from 'lodash/uniqueId';
88
- import { format as formatDate } from 'date-fns';
89
- import useAppStore from '~/store/app';
90
- import useM12Store from '~/store/app/m12';
91
- import DomainUnionSubset from '@/models/DomainUnionSubset';
92
- import LatlonUnionSubset from '@/models/LatlonUnionSubset';
93
- import type { IAudTaskResponse, IUnionSubsetSource } from '~/interface/IAudTask';
94
- import type IAudTask from '~/interface/IAudTask';
95
- import { AudTaskStatus, AudTaskCMType } from '~/interface/IAudTask';
96
-
97
- const PER_PAGE = 10;
98
-
99
- function normalizeTask(task: IAudTaskResponse): IAudTask {
100
- let gender = '';
101
-
102
- switch ((task.genders || [])[0]) {
103
- case '0':
104
- gender = '未知';
105
- break;
106
- case '1':
107
- gender = '男性';
108
- break;
109
- case '2':
110
- gender = '女性';
111
- break;
112
- case '3':
113
- gender = '不限';
114
- break;
115
- default:
116
- break;
117
- }
118
-
119
- return {
120
- id: task.task_id || '',
121
- name: task.name || '',
122
- status: task.status || AudTaskStatus.Run,
123
- includeSets: JSON.parse(task.and || '[]').map((includeSets: Array<IUnionSubsetSource>) => {
124
- return {
125
- id: uniqueId(),
126
- sets: includeSets
127
- .map((includeSet) => {
128
- if (includeSet.domains) {
129
- return DomainUnionSubset.normalize(includeSet);
130
- }
131
- if (includeSet.pg_id) {
132
- return LatlonUnionSubset.normalize(includeSet);
133
- }
134
- return null;
135
- })
136
- .filter((includeSet) => !!includeSet),
137
- };
138
- }),
139
- differenceSets: JSON.parse(task.not || '[]').map((differenceSets: Array<IUnionSubsetSource>) => {
140
- return {
141
- id: uniqueId(),
142
- sets: differenceSets
143
- .map((differenceSet) => {
144
- if (differenceSet.domains) {
145
- return DomainUnionSubset.normalize(differenceSet);
146
- }
147
- if (differenceSet.pg_id) {
148
- return LatlonUnionSubset.normalize(differenceSet);
149
- }
150
- return null;
151
- })
152
- .filter((differenceSet) => !!differenceSet),
153
- };
154
- }),
155
- uuid: task.uuid || '',
156
- steps: task.steps || [],
157
- ages: (task.ages || []).map((age) => {
158
- let name = '';
159
- switch (age) {
160
- case 'A':
161
- name = '17以下';
162
- break;
163
- case 'B':
164
- name = '18 - 24';
165
- break;
166
- case 'C':
167
- name = '25 - 34';
168
- break;
169
- case 'D':
170
- name = '35 - 44';
171
- break;
172
- case 'E':
173
- name = '45 - 54';
174
- break;
175
- case 'F':
176
- name = '55 - 64';
177
- break;
178
- case 'G':
179
- name = '65 - 74';
180
- break;
181
- case 'H':
182
- name = '75以上';
183
- break;
184
- default:
185
- break;
186
- }
40
+ import { fromEvent, interval, Subscription } from "rxjs";
41
+ import { debounce, startWith } from "rxjs/operators";
42
+ import { SLDistributor } from "#components";
187
43
 
188
- return {
189
- key: age,
190
- name,
191
- };
192
- }),
193
- gender: {
194
- key: (task.genders || [])[0],
195
- name: gender,
44
+ type SLDistributorType = InstanceType<typeof SLDistributor>;
45
+
46
+ export default defineComponent({
47
+ name: "SLTabs",
48
+ components: {},
49
+ props: {
50
+ size: {
51
+ type: String,
52
+ default: "",
53
+ validator: (value: string) => ["", "xs", "sm"].includes(value),
196
54
  },
197
- workAt: task.workCity || [],
198
- homeAt: task.homeCity || [],
199
- cms: (task.cm || []).map((cm) => {
200
- let name = '';
201
- switch (cm) {
202
- case AudTaskCMType.GID:
203
- name = 'Google瀏覽器受眾';
204
- break;
205
- case AudTaskCMType.IFA:
206
- name = '行動裝置受眾';
207
- break;
208
- default:
209
- break;
55
+ navMode: {
56
+ type: String,
57
+ default: "",
58
+ },
59
+ type: {
60
+ type: Number,
61
+ default: 1,
62
+ validator: (value: number) => [1, 2, 3, 4, 5].includes(value),
63
+ },
64
+ activeTab: {
65
+ type: Number,
66
+ default: 0,
67
+ },
68
+ },
69
+ emits: ["update:activeTab"],
70
+ setup(props, { emit }) {
71
+ const { activeTab, size, type, navMode } = toRefs(props);
72
+
73
+ const tabsContentBody = shallowRef<HTMLElement | null>(null);
74
+ const tabsNavLeftEl = shallowRef<HTMLElement | null>(null);
75
+ const navComp = shallowRef<SLDistributorType | null>(null);
76
+ const activeTabIndex = ref(activeTab.value || 0);
77
+ const tabTitles = ref<Array<string>>([]);
78
+ const showDropdown = ref(false);
79
+ const tabItemsOversizeProxy = ref(false);
80
+
81
+ let observer: MutationObserver | null = null;
82
+ let resizeSubscriber: Subscription | null = null;
83
+
84
+ const tabsClass = computed(() => {
85
+ const classes: Array<string> = [`tabs-type-${type.value}`];
86
+
87
+ if (size.value !== "") {
88
+ classes.push(`tabs-${size.value}`);
210
89
  }
211
- const foundCM = (task.reports?.cm || []).find(
212
- (reportsCM) => reportsCM.name === cm
213
- );
214
90
 
215
- let cmStatus = foundCM?.status || AudTaskStatus.Run;
216
- if (task.status === AudTaskStatus.Warn || task.status === AudTaskStatus.Error) {
217
- cmStatus = AudTaskStatus.Error;
218
- }
91
+ return classes.join(" ");
92
+ });
93
+ const currentTab = computed(() => {
94
+ return tabTitles.value[activeTabIndex.value];
95
+ });
96
+ const tabItemsOversize = computed({
97
+ get: () => {
98
+ return (
99
+ type.value !== 4 &&
100
+ (tabItemsOversizeProxy.value || navMode.value === "dropdown")
101
+ );
102
+ },
103
+ set: (newValue: boolean) => {
104
+ tabItemsOversizeProxy.value = newValue;
105
+ },
106
+ });
219
107
 
220
- const sourceCount = foundCM?.sourceCount || 0;
221
- const targetCount = foundCM?.targetCount || 0;
222
-
223
- return {
224
- key: cm,
225
- name,
226
- status: cmStatus,
227
- sourceCount: numberToLocaleString(sourceCount, { NaNString: '-' }) as string,
228
- targetCount: numberToLocaleString(targetCount, { NaNString: '-' }) as string,
229
- ratio: sourceCount ? toFixed((targetCount / sourceCount) * 100, 2, { NaNString: '-', unit: '%' }) as string : '0.00%',
230
- };
231
- }),
232
- profile: task.reports?.profile || null,
233
- interest: task.reports?.interest || null,
234
- createdAt: formatDate(task.created_at ? new Date(task.created_at) : new Date(), 'yyyy-MM-dd HH:mm:ss'),
235
- updatedAt: formatDate(task.updated_at ? new Date(task.updated_at) : new Date(), 'yyyy-MM-dd HH:mm:ss'),
236
- };
237
- }
108
+ provide("activeTab", readonly(activeTabIndex));
109
+ provide("initialTab", readonly(activeTab));
110
+
111
+ function caculateTabs() {
112
+ nextTick(() => {
113
+ const tabLinks =
114
+ navComp.value?.$el.querySelectorAll(".tab-nav-item-link");
115
+ const tabLinkTitles = [];
116
+ if (tabLinks) {
117
+ for (let i = 0; i < tabLinks.length; i += 1) {
118
+ tabLinkTitles.push((tabLinks[i] as HTMLElement).innerText);
119
+ }
120
+ }
121
+ tabTitles.value = tabLinkTitles;
122
+
123
+ const tabsNavLeftRect = tabsNavLeftEl.value?.getBoundingClientRect();
124
+ const navRect = navComp.value?.$el?.getBoundingClientRect();
125
+
126
+ if (tabsNavLeftRect && navRect) {
127
+ tabItemsOversizeProxy.value = navRect.width > tabsNavLeftRect.width;
128
+ }
129
+ });
130
+ }
238
131
 
239
- export default defineComponent({
240
- name: 'M0302IndexPage',
241
- components: {},
242
- setup() {
243
- definePageMeta({
244
- middleware: ['acl-route'],
132
+ function changeTabTo(newTab: number) {
133
+ activeTabIndex.value = newTab;
134
+ emit("update:activeTab", newTab);
135
+ }
136
+
137
+ function onClickedTab(i: number) {
138
+ changeTabTo(i);
139
+ }
140
+
141
+ watch(activeTab, () => {
142
+ activeTabIndex.value = activeTab.value || 0;
245
143
  });
246
144
 
247
- const router = useRouter();
145
+ onMounted(() => {
146
+ resizeSubscriber = fromEvent(window, "resize")
147
+ .pipe(debounce(() => interval(500)))
148
+ .pipe(startWith(0))
149
+ .subscribe(() => {
150
+ caculateTabs();
151
+ });
248
152
 
249
- const appStore = useAppStore();
250
- const m12Store = useM12Store();
153
+ if (navComp.value) {
154
+ observer = new MutationObserver(caculateTabs);
155
+ observer.observe(navComp.value.$el, {
156
+ characterData: true,
157
+ attributes: false,
158
+ childList: true,
159
+ subtree: true,
160
+ });
161
+ }
162
+ });
251
163
 
252
- const loading = ref(false);
253
- const tasks = ref<Array<IAudTask>>([]);
254
- const search = ref('');
255
- const totalCount = ref(0);
256
- const currentPage = ref(1);
257
- const isShowDeleteConfirmModal = ref(false);
258
- const perPage = ref(PER_PAGE);
164
+ onBeforeUnmount(() => {
165
+ if (resizeSubscriber) {
166
+ resizeSubscriber.unsubscribe();
167
+ }
168
+ if (observer) {
169
+ observer.disconnect();
170
+ }
171
+ resizeSubscriber = null;
172
+ observer = null;
173
+ });
259
174
 
260
- let taskId = '';
175
+ return {
176
+ tabsContentBody,
177
+ tabsNavLeftEl,
178
+ navComp,
179
+ activeTabIndex,
180
+ tabTitles,
181
+ showDropdown,
182
+ tabItemsOversize,
183
+ tabsClass,
184
+ currentTab,
185
+ changeTabTo,
186
+ onClickedTab,
187
+ };
188
+ },
189
+ });
190
+ </script>
261
191
 
262
- const project = computed(() => appStore.project);
192
+ <style lang="stylus">
193
+ .tabs
194
+ &.tabs-sm
195
+ &.tabs-type-1
196
+ & > .tabs-nav
197
+ ul
198
+ .tab-nav-item
199
+ &-link
200
+ @apply text-sm
263
201
 
264
- async function fetch() {
265
- loading.value = true;
202
+ &.tabs-xs
203
+ &.tabs-type-1
204
+ & > .tabs-nav
205
+ ul
206
+ .tab-nav-item
207
+ &.active
208
+ &:before
209
+ @apply hidden
266
210
 
267
- const { data, error } = await m12Store.getTasks({
268
- offset: (currentPage.value - 1) * perPage.value,
269
- limit: perPage.value,
270
- });
271
-
272
- loading.value = false;
273
-
274
- if (error) {
275
- appStore.addAlert({
276
- title: '錯誤',
277
- color: 'danger',
278
- message: error.message,
279
- });
280
- }
211
+ &-link
212
+ @apply s("py-0.75") text-base
281
213
 
282
- totalCount.value = data?.aud_task_list.totalCount || 0;
283
- tasks.value = (data?.aud_task_list.data || []).map((task) => normalizeTask(task));
284
- }
214
+ &.tabs-type-1
215
+ & > .tabs-nav
216
+ @apply flex items-start justify-between h-0 space-x-8 overflow-hidden
217
+ @apply s('lg:space-x-30')
285
218
 
286
- function onClickedAdd() {
287
- router.push('/application/m03/02/create');
288
- }
219
+ &.show
220
+ @apply h-auto s("-mb-1.5")
289
221
 
290
- function onClearedSearch() {
291
- search.value = '';
292
- }
222
+ .tabs-nav-left
223
+ @apply flex-grow overflow-hidden
293
224
 
294
- function onClickedDelete(id: string) {
295
- taskId = id;
296
- isShowDeleteConfirmModal.value = true;
297
- }
225
+ .tabs-nav-right
226
+ @apply flex-grow-0 flex-shrink-0
298
227
 
299
- function onClickedRepack(id: string) {
300
- const foundTask = tasks.value.find((task) => task.id === id);
301
- if (!foundTask) return;
228
+ ul
229
+ @apply inline-flex items-start s("-space-x-px")
302
230
 
303
- m12Store.setTask(foundTask);
304
- router.push(`/application/m03/02/create`);
305
- }
231
+ .tab-nav-item
232
+ @apply relative rounded-t bg-white
306
233
 
307
- async function onDeleteApply() {
308
- isShowDeleteConfirmModal.value = false;
234
+ &:first-child
235
+ .tab-nav-item-link
236
+ &:after
237
+ content ""
238
+ @apply absolute bottom-0 left-0 w-px h-3 s("-mb-3") s("-ml-px") bg-border
309
239
 
310
- const { error } = await m12Store.deleteTask(taskId);
240
+ &.active
241
+ @apply s("pb-1.75")
311
242
 
312
- if (error) {
313
- appStore.addAlert({
314
- color: 'danger',
315
- code: error.code,
316
- message: error.message,
317
- });
318
- }
243
+ &:before
244
+ content ""
245
+ @apply block absolute s("top-0.5") s("right-0.75") s("left-0.75") h-1 bg-secondary-hover
319
246
 
320
- if (tasks.value.length === 1) {
321
- currentPage.value = Math.max(1, currentPage.value - 1);
322
- }
323
- fetch();
324
- }
247
+ .tab-nav-item-link
248
+ @apply text-primary cursor-default
325
249
 
326
- function onUpdatedPerPage(newPerPage: number) {
327
- perPage.value = newPerPage;
328
- currentPage.value = 1;
329
- fetch();
330
- }
250
+ &-link
251
+ @apply relative block s("py-1.75") s("px-3.75") border-t border-r border-l border-border rounded-t text-lg text-primary-light
331
252
 
332
- function onUpdatedPage(newPage: number) {
333
- currentPage.value = newPage;
334
- }
253
+ &-title
254
+ @apply truncate
335
255
 
336
- watch(search, () => {
337
- currentPage.value = 1;
338
- });
339
- watch(currentPage, () => {
340
- fetch();
341
- });
342
- watch(project, () => {
343
- currentPage.value = 1;
344
- fetch();
345
- });
256
+ .tab-pane
257
+ @apply space-y-8
346
258
 
347
- onMounted(() => {
348
- fetch();
349
- });
259
+ & > .tabs-content
260
+ @apply p-4 border border-border rounded-lg bg-white overflow-hidden
350
261
 
351
- return {
352
- tasks,
353
- search,
354
- totalCount,
355
- currentPage,
356
- loading,
357
- isShowDeleteConfirmModal,
358
- perPage,
359
- onClickedAdd,
360
- onClearedSearch,
361
- onClickedDelete,
362
- onClickedRepack,
363
- onDeleteApply,
364
- onUpdatedPerPage,
365
- onUpdatedPage,
366
- };
367
- },
368
- });
369
- </script>
262
+ .tabs-content-header
263
+ @apply flex items-start justify-between mb-4
370
264
 
371
- <style lang="stylus">
372
- .m03-02p-page
373
- .site-page-header
374
- @apply p-6 bg-white rounded-lg shadow
265
+ &.tabs-type-2
266
+ & > .tabs-nav
267
+ @apply mb-0
268
+
269
+ ul
270
+ @apply flex px-8 pb-5 space-x-8
271
+ @apply s('lg:px-6') s('lg:space-x-14')
272
+
273
+ .tab-nav-item
274
+ @apply relative flex-grow s('py-6') rounded bg-bg text-lg text-primary-hover text-center
275
+ @apply s('lg:py-5.5')
276
+
277
+ &:before
278
+ content ""
279
+ @apply absolute s('top-0.5') s('left-0.5') block rounded bg-white
280
+ width calc(100% - theme('spacing.1'))
281
+ height calc(100% - theme('spacing.1'))
282
+
283
+ &:after
284
+ content ""
285
+ @apply absolute left-0 bottom-0 s('-ml-4') s('-mb-5') block w-full h-3 rounded-t bg-primary-lighter opacity-0
286
+ width calc(100% + theme('spacing.4') * 2)
287
+
288
+ &.active
289
+ @apply text-primary font-bold
290
+
291
+ &:after
292
+ @apply opacity-100
293
+
294
+ &:nth-child(odd)
295
+ @apply bg-transparent s('bg-gradient-to-r') s('from-insight-web-title-start') s('to-insight-web-title-end')
296
+
297
+ &:after
298
+ @apply bg-transparent s('bg-gradient-to-r') s('from-insight-web-title-start') s('to-insight-web-title-end')
299
+
300
+ &:nth-child(even)
301
+ @apply bg-transparent s('bg-gradient-to-r') s('from-insight-poi-title-start') s('to-insight-poi-title-end')
302
+
303
+ &:after
304
+ @apply bg-transparent s('bg-gradient-to-r') s('from-insight-poi-title-start') s('to-insight-poi-title-end')
305
+
306
+ .tab-nav-item-link
307
+ @apply cursor-default
308
+
309
+ &-link
310
+ @apply relative
311
+
312
+ &.tabs-type-3
313
+ & > .tabs-nav
314
+ @apply flex items-start justify-between h-0 space-x-8 overflow-hidden
315
+ @apply s('lg:space-x-30')
316
+
317
+ &.show
318
+ @apply h-auto mb-1
319
+
320
+ .tabs-nav-left
321
+ @apply flex-grow overflow-hidden
322
+
323
+ .tabs-nav-right
324
+ @apply flex-grow-0 flex-shrink-0
325
+
326
+ ul
327
+ @apply inline-flex items-start space-x-2
328
+
329
+ .tab-nav-item
330
+ @apply relative rounded-t bg-bg
331
+
332
+ &.active
333
+ @apply bg-primary
334
+
335
+ .tab-nav-item-link
336
+ @apply text-white cursor-default
337
+
338
+ &-link
339
+ @apply relative block py-2 px-8 rounded-t text-base text-primary
340
+
341
+ &-title
342
+ @apply truncate
343
+
344
+ .tab-pane
345
+ @apply space-y-8
346
+
347
+ & > .tabs-content
348
+ @apply p-6 rounded-tr-lg rounded-b-lg bg-white shadow overflow-hidden
349
+
350
+ .tabs-content-header
351
+ @apply flex items-start justify-between
352
+
353
+ .tabs-dropdown
354
+ @apply mb-4
355
+
356
+ &.tabs-type-4
357
+ @apply flex
358
+
359
+ & > .tabs-nav
360
+ @apply flex-grow-0 flex-shrink-0
361
+
362
+ .tabs-nav-left
363
+ ul
364
+ @apply flex flex-col s('space-y-0.5')
365
+
366
+ .tab-nav-item
367
+ @apply flex justify-between s('w-[184px]') py-3 pl-3 pr-5 bg-bg-middle rounded-l-lg text-xs
368
+
369
+ &.active
370
+ @apply bg-primary-hover text-white font-bold shadow-md
371
+
372
+ &-link
373
+ @apply block w-full
374
+
375
+ .tabs-content
376
+ @apply flex-grow s('-ml-2') p-4 bg-white border border-border rounded-lg shadow-md
375
377
 
376
- &-left
377
- .site-page-title
378
- @apply mb-2 s('text-3.33xl') text-primary font-bold
378
+ & > div
379
+ @apply flex min-h-full
379
380
 
380
- .site-page-desc
381
- @apply flex items-center mb-6 space-x-2 text-sm text-gray-2 font-medium
381
+ .tabs-content-body
382
+ @apply w-full
382
383
 
383
- a
384
- @apply inline-flex items-center space-x-1 text-blue-1 font-normal
384
+ &.tabs-type-5
385
+ & > .tabs-nav
386
+ @apply relative flex items-start justify-between h-0 mb-4 space-x-8 overflow-hidden
387
+ @apply s('lg:space-x-30')
385
388
 
386
- .site-page-actions
387
- .create-btn
388
- @apply s('py-1.75') s('pl-[23px]') s('pr-3.75') rounded-lg text-lg
389
+ &.show
390
+ @apply h-auto
389
391
 
390
- .site-page-content
391
- @apply p-0 bg-transparent
392
+ &:before
393
+ content ""
394
+ @apply absolute right-0 bottom-0 left-0 h-px s('rounded-[1px]') bg-primary-lighter
392
395
 
393
- .m0302p-search-input
394
- @apply s('w-[238px]')
396
+ .tabs-nav-left
397
+ @apply flex-grow overflow-hidden
395
398
 
396
- .input-group
397
- .input.input-sm
398
- input
399
- @apply text-sm
399
+ .tabs-nav-right
400
+ @apply flex-grow-0 flex-shrink-0
400
401
 
401
- & > .card
402
- @apply border-0 rounded-lg shadow-none
402
+ ul
403
+ @apply inline-flex items-start
403
404
 
404
- .audience-package-card
405
- .audience-package
406
- @apply space-y-4
405
+ .tab-nav-item
406
+ @apply relative
407
407
 
408
- &-header
409
- @apply flex items-end justify-between
408
+ &.active
409
+ &:after
410
+ content ""
411
+ @apply block absolute right-0 bottom-0 left-0 h-1 s('rounded-[1px]') bg-primary
410
412
 
411
- .header-left
412
- @apply flex-shrink-0 flex-grow-0
413
+ .tab-nav-item-link
414
+ @apply cursor-default
413
415
 
414
- .header-right
415
- @apply flex-grow flex items-end justify-end
416
+ &-link
417
+ @apply relative block px-4 pb-2 text-lg text-gray-2
416
418
 
417
- &-body
418
- @apply space-y-4
419
+ &-title
420
+ @apply truncate
419
421
 
420
- .m12-delete-confirm-modal
421
- .modal-body
422
- &-content
423
- @apply flex flex-col items-center justify-center space-y-6 text-base text-gray-2
422
+ .tab-pane
423
+ @apply space-y-8
424
424
 
425
- .icon
426
- @apply text-16xl text-danger
425
+ & > .tabs-content
426
+ .tabs
427
+ & > .tabs-content
428
+ @apply shadow-md
427
429
  </style>
428
-
430
+
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mptw/skylens-ui",
3
3
  "type": "module",
4
- "version": "1.3.15",
4
+ "version": "1.4.0",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground",