@mptw/skylens-ui 1.4.50 → 1.4.52

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.
@@ -1,57 +1,72 @@
1
1
  <template lang="pug">
2
- .sidebar(:class="{ closure: closuredProxy, dark }")
2
+ .sidebar(:class="{ closure: closuredProxy, dark, introing }")
3
3
  .sidebar-modal(@click="onClickedToggle")
4
- .sidebar-logo
5
- a.logo(href="javascript:;" @click="onClickedLogo")
6
- img.color-big(src="~/assets/images/commons/app-logo-big.svg")
7
- img.white-big(src="~/assets/images/commons/app-logo-big-white.svg")
8
- img.color-small(src='~/assets/images/commons/app-logo-small.svg')
9
- img.white-small(src='~/assets/images/commons/app-logo-small-white.svg')
10
- nav.site-nav
11
- .nav-wrapper.custom-scrollbar-y
12
- template(v-for='item in config')
13
- SLSidebarNavLinkItem(
14
- v-if='item.navType === "link"'
15
- :nav-collapsed='closured'
16
- :item-config='item'
17
- @click:item='onClickedItem'
18
- )
19
- SLSidebarNavSectionItem(
20
- v-else-if='item.navType === "section"'
21
- :nav-collapsed='closured'
22
- :item-config='item'
23
- @click:item='onClickedItem'
24
- )
25
- SLSidebarNavGroupItem(
26
- v-else-if='item.navType === "group"'
27
- :nav-collapsed='closured'
28
- :nav-dark='dark'
29
- :item-config='item'
30
- @click:item='onClickedItem'
31
- )
32
- .sidebar-nav-divide-item(
33
- v-else
34
- )
35
- .sidebar-mode-setting
36
- .sidebar-mode-setting-title 模式
37
- SLIOSSwitch(
38
- :modelValue="dark"
39
- trueLabel="深色"
40
- minTrueLabel=""
41
- falseLabel="淺色"
42
- minFalseLabel=""
43
- :size="closuredProxy ? 'min' : ''"
44
- :color='switchColor'
45
- @update:modelValue="onUpdatedMode"
46
- )
47
- a.sidebar-toggle(href="javascript:;", @click="onClickedToggle")
48
- SLIcon(icon="chevron-left")
49
- SLIcon(icon="chevron-right")
4
+ .sidebar-intro-modal
5
+ .sidebar-wrapper
6
+ .sidebar-logo
7
+ a.logo(href="javascript:;" @click="onClickedLogo")
8
+ img.color-big(src="~/assets/images/commons/app-logo-big.svg", @load='onLogoLoaded')
9
+ img.white-big(src="~/assets/images/commons/app-logo-big-white.svg", @load='onLogoLoaded')
10
+ img.color-small(src='~/assets/images/commons/app-logo-small.svg', @load='onLogoLoaded')
11
+ img.white-small(src='~/assets/images/commons/app-logo-small-white.svg', @load='onLogoLoaded')
12
+ nav.site-nav
13
+ .nav-wrapper.custom-scrollbar-y
14
+ template(v-for='item in config')
15
+ SLSidebarNavLinkItem(
16
+ v-if='item.navType === "link"'
17
+ :nav-collapsed='closured'
18
+ :item-config='item'
19
+ @click:item='onClickedItem'
20
+ )
21
+ SLSidebarNavSectionItem(
22
+ v-else-if='item.navType === "section"'
23
+ :nav-collapsed='closured'
24
+ :item-config='item'
25
+ @click:item='onClickedItem'
26
+ )
27
+ SLSidebarNavGroupItem(
28
+ v-else-if='item.navType === "group"'
29
+ :nav-collapsed='closured'
30
+ :nav-dark='dark'
31
+ :item-config='item'
32
+ @click:item='onClickedItem'
33
+ )
34
+ .sidebar-nav-divide-item(
35
+ v-else
36
+ )
37
+ .sidebar-mode-setting
38
+ .sidebar-mode-setting-title 模式
39
+ SLIOSSwitch(
40
+ :modelValue="dark"
41
+ trueLabel="深色"
42
+ minTrueLabel=""
43
+ falseLabel="淺色"
44
+ minFalseLabel="淺"
45
+ :size="closuredProxy ? 'min' : ''"
46
+ :color='switchColor'
47
+ @update:modelValue="onUpdatedMode"
48
+ )
49
+ a.sidebar-toggle(href="javascript:;", @click="onClickedToggle")
50
+ SLIcon(icon="chevron-left")
51
+ SLIcon(icon="chevron-right")
52
+ .sidebar-nav-intro(ref='introEl')
53
+ .sidebar-nav-intro-header {{ navLinkIntro ? navLinkIntro.title : '' }}
54
+ .sidebar-nav-intro-body {{ navLinkIntro ? navLinkIntro.content : ''}}
55
+ .sidebar-nav-intro-footer
56
+ SLButton(
57
+ title='我知道了',
58
+ color='primary'
59
+ size='sm'
60
+ @click='onClickedCloseIntro'
61
+ )
62
+ .sidebar-nav-intro-arrow
50
63
  </template>
51
64
 
52
65
  <script lang="ts">
53
66
  import type { PropType } from "vue";
54
- import type { NavConfigType } from "~ui/interface/NavConfigType";
67
+ import { createPopper } from '@popperjs/core';
68
+ import type { Instance as PopperInstance } from '@popperjs/core';
69
+ import { NavType, type NavConfigType } from "~/interface/NavConfigType";
55
70
 
56
71
  export default defineComponent({
57
72
  name: "SLSidebarNav",
@@ -68,22 +83,40 @@ export default defineComponent({
68
83
  type: Array as PropType<NavConfigType>,
69
84
  default: () => [],
70
85
  },
86
+ navIntros: {
87
+ type: Array as PropType<{
88
+ code: string;
89
+ title: string;
90
+ content: string;
91
+ targetCode: string;
92
+ }[]>,
93
+ default: () => [],
94
+ },
71
95
  switchColor: {
72
96
  type: String,
73
97
  default: '',
74
98
  validator: (v: string) => ['', 'primary-600', 'primary'].includes(v),
75
99
  },
76
100
  },
77
- emits: ["click:logo", "update:dark", "update:closured", "click:insight"],
101
+ emits: ["click:logo", "update:dark", "update:closured", "click:insight", 'close:intro', 'logo:loaded'],
78
102
  setup(props, { emit }) {
79
- const { closured } = toRefs(props);
103
+ const { closured, navIntros } = toRefs(props);
104
+
105
+ const introEl = ref<HTMLElement | null>(null);
106
+ const introing = ref(false);
80
107
 
81
108
  const closuredProxy = computed({
82
109
  get: () => closured.value,
83
110
  set: (newValue) => emit('update:closured', newValue),
84
111
  });
85
112
 
113
+ let introPopperInstance: PopperInstance | null = null;
114
+
115
+ const navLinkIntro = computed(() => navIntros.value[0]);
116
+
86
117
  function onClickedToggle() {
118
+ if (introing.value) return;
119
+
87
120
  closuredProxy.value = !closuredProxy.value;
88
121
  }
89
122
 
@@ -105,12 +138,98 @@ export default defineComponent({
105
138
  emit("update:dark", isDark);
106
139
  }
107
140
 
141
+ function createIntroPopper() {
142
+ destroyIntroPopper();
143
+
144
+ if (!navLinkIntro.value) return;
145
+
146
+ const navLinkIndexEl = document.getElementById(`nav-link-${navLinkIntro.value.targetCode}`);
147
+
148
+ if (!introEl.value || !navLinkIndexEl) return;
149
+
150
+ introPopperInstance = createPopper(navLinkIndexEl, introEl.value, {
151
+ modifiers: [
152
+ {
153
+ name: 'offset',
154
+ options: {
155
+ offset: [-6, 39],
156
+ },
157
+ },
158
+ ],
159
+ placement: 'right-start',
160
+ });
161
+ }
162
+
163
+ function destroyIntroPopper() {
164
+ if (introPopperInstance) {
165
+ introPopperInstance.destroy();
166
+ }
167
+ introPopperInstance = null;
168
+ }
169
+
170
+ async function showLinkIntro() {
171
+ await nextTick();
172
+
173
+ if (!introEl.value || !introPopperInstance) return;
174
+
175
+ introEl.value.setAttribute('data-show', '');
176
+ introPopperInstance.setOptions((options) => ({
177
+ ...options,
178
+ modifiers: [
179
+ ...(options.modifiers || []),
180
+ { name: 'eventListeners', enabled: true },
181
+ ],
182
+ }));
183
+ introPopperInstance.update();
184
+ introing.value = true;
185
+ }
186
+
187
+ function hideLinkIntro() {
188
+ introing.value = false;
189
+
190
+ if (!introEl.value || !introPopperInstance) return;
191
+
192
+ introEl.value.removeAttribute('data-show');
193
+ introPopperInstance.setOptions((options) => ({
194
+ ...options,
195
+ modifiers: [
196
+ ...(options.modifiers || []),
197
+ { name: 'eventListeners', enabled: false },
198
+ ],
199
+ }));
200
+ }
201
+
202
+ function displayLinkIntro() {
203
+ if (!navLinkIntro.value) return;
204
+
205
+ createIntroPopper();
206
+ showLinkIntro();
207
+ }
208
+
209
+ function onClickedCloseIntro() {
210
+ hideLinkIntro();
211
+
212
+ if (!navLinkIntro.value) return;
213
+
214
+ emit('close:intro', navLinkIntro.value.code);
215
+ }
216
+
217
+ function onLogoLoaded() {
218
+ emit('logo:loaded');
219
+ }
220
+
108
221
  return {
222
+ introEl,
223
+ introing,
109
224
  closuredProxy,
225
+ navLinkIntro,
110
226
  onClickedToggle,
111
227
  onClickedLogo,
112
228
  onClickedItem,
113
229
  onUpdatedMode,
230
+ displayLinkIntro,
231
+ onClickedCloseIntro,
232
+ onLogoLoaded,
114
233
  };
115
234
  },
116
235
  });
@@ -118,10 +237,11 @@ export default defineComponent({
118
237
 
119
238
  <style lang="stylus">
120
239
  .sidebar
121
- @apply relative flex flex-col s('w-[188px]') h-full bg-white rounded-r-lg shadow transition-all
240
+ @apply relative h-full
122
241
 
123
242
  &.dark
124
- @apply bg-primary-800
243
+ .sidebar-wrapper
244
+ @apply bg-primary-800
125
245
 
126
246
  &.closure
127
247
  .sidebar-logo
@@ -176,12 +296,13 @@ export default defineComponent({
176
296
  @apply bg-primary-600
177
297
 
178
298
  &.closure
179
- @apply s('-ml-[188px]')
180
- @apply s('lg:ml-0') s('lg:w-[84px]')
181
-
182
299
  .sidebar-modal
183
300
  @apply hidden
184
301
 
302
+ .sidebar-wrapper
303
+ @apply s('-ml-[188px]')
304
+ @apply s('lg:ml-0') s('lg:w-[84px]')
305
+
185
306
  .sidebar-logo
186
307
  @apply s('lg:py-3') s('lg:px-0')
187
308
  .logo
@@ -216,10 +337,23 @@ export default defineComponent({
216
337
  .ios-switch
217
338
  @apply flex-grow-0 flex-shrink-0
218
339
 
340
+ &.introing
341
+ .sidebar-intro-modal
342
+ @apply block
343
+
344
+ .sidebar-wrapper
345
+ @apply pointer-events-none
346
+
219
347
  &-modal
220
348
  @apply fixed top-0 left-0 w-full h-full bg-white opacity-0
221
349
  @apply s('lg:hidden')
222
350
 
351
+ &-intro-modal
352
+ @apply fixed top-0 left-0 w-full h-full s('bg-mask/80') hidden
353
+
354
+ &-wrapper
355
+ @apply relative flex flex-col s('w-[188px]') h-full bg-white rounded-r-lg shadow transition-all
356
+
223
357
  &-logo
224
358
  @apply flex-grow-0 flex-shrink-0 relative flex justify-center py-4 pr-11 pl-6 transition-all
225
359
 
@@ -261,5 +395,34 @@ export default defineComponent({
261
395
 
262
396
  .icon-chevron-right
263
397
  @apply hidden
398
+
399
+ &-nav-intro
400
+ @apply s('w-[288px]') p-4 bg-white rounded-lg hidden
401
+
402
+ &[data-show]
403
+ @apply block
404
+
405
+ &[data-popper-placement^='right'] > &-arrow
406
+ @apply s('-left-3.75') s('top-4')
407
+
408
+ &-header
409
+ @apply mb-2 text-base font-bold text-primary
410
+
411
+ &-body
412
+ @apply mb-4 text-base text-pgray-2 whitespace-pre-line
413
+
414
+ &-footer
415
+ @apply text-right
416
+
417
+ &-arrow, &-arrow:before
418
+ @apply absolute s('w-[17px]') s('h-[20px]') bg-contain
419
+ background url('~/assets/images/commons/nav-intro-arrow.svg') top left no-repeat
420
+
421
+ &-arrow
422
+ @apply invisible
423
+
424
+ &:before
425
+ content ''
426
+ @apply visible
264
427
  </style>
265
428
 
@@ -1,6 +1,7 @@
1
1
  <template lang="pug">
2
2
  .sidebar-nav-group-item-section(:class='{ collapsed }')
3
3
  .sidebar-nav-group-item-section-header(
4
+ :id='`nav-link-${itemConfig.code}`'
4
5
  :class='{ "router-link-active": isLinkActive, "router-link-exact-active": isLinkExactActive, active: actived }'
5
6
  ref='headerEl'
6
7
  @mouseenter='onIconMouseEnter',
@@ -31,10 +32,20 @@
31
32
  @click='onClickedToggle'
32
33
  )
33
34
  SLIcon(icon='sort-down')
35
+ NuxtLink.sidebar-nav-group-item-section-add-btn(
36
+ v-else-if='itemConfig.status === "plus"'
37
+ :to='itemConfig.to ? itemConfig.to : "javascript:;"',
38
+ :external='!itemConfig.to',
39
+ @mousedown='onMouseDownLink',
40
+ @mouseup='onMouseUpLink',
41
+ @click='onClickedSectionItem'
42
+ )
43
+ SLIcon(icon='add')
34
44
  .sidebar-nav-group-item-section-body(ref='bodyEl')
35
45
  .sidebar-nav-group-item-section-body-wrapper
36
46
  NuxtLink.sidebar-nav-group-item-section-link(
37
47
  v-for='(link, i) in itemConfig.links'
48
+ :id='`nav-link-${link.code}`'
38
49
  :to='link.to ? link.to : "javascript:;"',
39
50
  :external='!link.to',
40
51
  :key='link.code'
@@ -403,9 +414,26 @@ export default defineComponent({
403
414
  @apply flex items-center flex-nowrap py-2 pr-1 pl-2 bg-primary-50 rounded-lg text-base text-primary
404
415
  @apply s('hover:bg-primary-200') s('hover:font-bold')
405
416
 
417
+ &:hover
418
+ .sidebar-nav-group-item-section-header-right
419
+ .sidebar-nav-group-item-section-status
420
+ .sidebar-nav-group-item-section-add-btn
421
+ @apply text-primary
422
+
406
423
  &.active, &.router-link-exact-active
407
424
  @apply bg-primary-600 text-white font-bold
408
425
  @apply s('hover:bg-primary-600') s('hover:text-white') s('hover:font-bold')
426
+
427
+ .sidebar-nav-group-item-section-header-right
428
+ .sidebar-nav-group-item-section-status
429
+ .sidebar-nav-group-item-section-add-btn
430
+ @apply text-white
431
+
432
+ &.router-link-exact-active
433
+ .sidebar-nav-group-item-section-header-right
434
+ .sidebar-nav-group-item-section-status
435
+ .sidebar-nav-group-item-section-add-btn
436
+ @apply hidden
409
437
 
410
438
  &-left
411
439
  @apply flex-grow-0 flex-shrink-0 inline-flex
@@ -422,6 +450,9 @@ export default defineComponent({
422
450
  .sidebar-nav-group-item-section-toggle-btn
423
451
  @apply flex items-center justify-center w-4 h-4 text-sm rotate-180 transition-transform origin-center
424
452
 
453
+ .sidebar-nav-group-item-section-add-btn
454
+ @apply flex items-center justify-center w-4 h-4 text-sm text-primary-400
455
+
425
456
  &-body
426
457
  @apply overflow-hidden transition-height
427
458
 
@@ -1,5 +1,6 @@
1
1
  <template lang="pug">
2
2
  NuxtLink.sidebar-nav-link-item(
3
+ :id='`nav-link-${itemConfig.code}`',
3
4
  :to='itemConfig.to ? itemConfig.to : "javascript:;"',
4
5
  :external='!itemConfig.to',
5
6
  :class='{ "sidebar-nav-link-item--home": itemConfig.to === "/application", "router-link-active": linkActive }'
@@ -35,6 +35,11 @@ export type NavItemLink = {
35
35
  include?: string[];
36
36
  inDev?: boolean;
37
37
  status: NavItemStatus;
38
+ intro?: {
39
+ code: string;
40
+ content: string;
41
+ needShowIntro: boolean;
42
+ };
38
43
  }
39
44
 
40
45
  export type NavItemSection = {
@@ -47,6 +52,11 @@ export type NavItemSection = {
47
52
  preIcon?: string;
48
53
  links?: NavItemLink[];
49
54
  status: NavItemStatus;
55
+ intro?: {
56
+ code: string;
57
+ content: string;
58
+ needShowIntro: boolean;
59
+ };
50
60
  }
51
61
 
52
62
  export type NavItemGroup = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mptw/skylens-ui",
3
3
  "type": "module",
4
- "version": "1.4.50",
4
+ "version": "1.4.52",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground",