@kizmann/nano-ui 1.0.11 → 1.0.13

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,4 +1,4 @@
1
- import { Arr, Any, Dom } from "@kizmann/pico-js";
1
+ import { Arr, Any, Dom, Str, Locale } from "@kizmann/pico-js";
2
2
 
3
3
  export default {
4
4
 
@@ -19,6 +19,30 @@ export default {
19
19
 
20
20
  props: {
21
21
 
22
+ showSearch: {
23
+ default()
24
+ {
25
+ return false;
26
+ },
27
+ type: [Boolean]
28
+ },
29
+
30
+ searchPlaceholder: {
31
+ default()
32
+ {
33
+ return Locale.trans('Search ...');
34
+ },
35
+ type: [String]
36
+ },
37
+
38
+ searchIcon: {
39
+ default()
40
+ {
41
+ return 'fa fa-times';
42
+ },
43
+ type: [String]
44
+ },
45
+
22
46
  kind: {
23
47
  default()
24
48
  {
@@ -27,10 +51,27 @@ export default {
27
51
  type: [String]
28
52
  },
29
53
 
54
+ multiple: {
55
+ default()
56
+ {
57
+ return true;
58
+ },
59
+ type: [Boolean]
60
+ }
61
+
62
+ },
63
+
64
+ data()
65
+ {
66
+ return { search: '' };
30
67
  },
31
68
 
32
69
  mounted()
33
70
  {
71
+ this.$watch('search', () => {
72
+ this.onSearchInput();
73
+ });
74
+
34
75
  this.$nextTick(() => {
35
76
  this.onScrollEvent();
36
77
  });
@@ -44,37 +85,51 @@ export default {
44
85
  Dom.find(el).removeClass('is-visible');
45
86
  });
46
87
 
47
- Dom.inviewMaxY(`[data-group-key]`, (el, attr) => {
88
+ let options = {
89
+ el: `[data-group-key]`, parent: this.$el
90
+ }
91
+
92
+ Dom.inviewMaxY(options, (el) => {
48
93
 
49
- let selector = `[data-menu-key="${attr}"]`;
94
+ let selector = `[data-menu-key="${el.attr}"]`;
50
95
 
51
96
  Dom.find(this.$el).find(selector)
52
97
  .addClass('is-visible');
53
98
 
54
99
  this.$refs.menu.scrollIntoView(selector)
100
+ });
101
+ },
55
102
 
56
- }, this.$el);
57
- }
103
+ handleVisibleItems(els)
104
+ {
58
105
 
59
- },
106
+ },
60
107
 
61
- renderMenu(item)
62
- {
63
- let labelHtml = (
64
- <span>{item.label}</span>
65
- );
108
+ onSearchInput()
109
+ {
110
+ let search = Str.lower(this.search);
66
111
 
67
- let iconHtml = null;
112
+ Dom.find(this.$el).find(`[data-menu-key]`)
113
+ .removeClass('on-search');
68
114
 
69
- if ( item.icon ) {
70
- iconHtml = (<i class={item.icon} />);
71
- }
115
+ if ( Any.isEmpty(search) ) {
116
+ return;
117
+ }
72
118
 
73
- let buttonProps = {
74
- href: '#' + item.key
75
- }
119
+ let groups = Arr.filter(this.NForm.groups, (group) => {
120
+ return Str.lower(group.label).indexOf(search) !== -1;
121
+ });
122
+
123
+ Arr.each(groups, (group) => {
124
+ Dom.find(this.$el).find(`[data-menu-key="${group.key}"]`).addClass('on-search');
125
+ });
126
+ },
76
127
 
77
- buttonProps['onClick'] = () => {
128
+ onClickEvent(item, event = null)
129
+ {
130
+ if ( ! Any.isEmpty(event) ) {
131
+ event.preventDefault();
132
+ }
78
133
 
79
134
  let selector = `[data-group-key="${item.key}"]`
80
135
 
@@ -95,6 +150,55 @@ export default {
95
150
  this.$nextTick(() => {
96
151
  Dom.find(selector).addClass('on-search');
97
152
  });
153
+
154
+ this.$refs.body.scrollIntoView(selector, 0, 100);
155
+ }
156
+
157
+ },
158
+
159
+ renderSearch()
160
+ {
161
+ if ( ! this.showSearch ) {
162
+ return null;
163
+ }
164
+
165
+ let searchProps = {
166
+ placeholder: this.searchPlaceholder
167
+ };
168
+
169
+ if ( ! Any.isEmpty(this.search) ) {
170
+ searchProps.icon = this.searchIcon;
171
+ }
172
+
173
+ searchProps['onIconClick'] = () => {
174
+ this.search = '';
175
+ }
176
+
177
+ return (
178
+ <div class="n-form-frame__search">
179
+ <NInput vModel={this.search} {...searchProps}></NInput>
180
+ </div>
181
+ )
182
+ },
183
+
184
+ renderMenu(item)
185
+ {
186
+ let labelHtml = (
187
+ <span>{item.label}</span>
188
+ );
189
+
190
+ let iconHtml = null;
191
+
192
+ if ( item.icon ) {
193
+ iconHtml = (<i class={item.icon} />);
194
+ }
195
+
196
+ let buttonProps = {
197
+ href: '#' + item.key
198
+ }
199
+
200
+ buttonProps['onClick'] = (e) => {
201
+ this.onClickEvent(item, e)
98
202
  };
99
203
 
100
204
  let classList = [
@@ -117,7 +221,7 @@ export default {
117
221
 
118
222
  return (
119
223
  <n-scrollbar ref="menu" class="n-form-frame__menus">
120
- { items } { this.$slots.menu && this.$slots.menu() }
224
+ { this.ctor('renderSearch')() } { items } { this.$slots.menu && this.$slots.menu() }
121
225
  </n-scrollbar>
122
226
  );
123
227
  },
@@ -146,6 +250,10 @@ export default {
146
250
  'n-form-frame--' + this.NForm.size
147
251
  ];
148
252
 
253
+ if ( ! Any.isEmpty(this.search) ) {
254
+ classList.push('n-form-frame--search')
255
+ }
256
+
149
257
  return (
150
258
  <div class={classList}>
151
259
  {[this.$slots.frame && this.$slots.frame(), this.ctor('renderMenus')(), this.ctor('renderBody')()]}
@@ -20,11 +20,34 @@
20
20
 
21
21
  .n-form-frame__menu {
22
22
  cursor: pointer;
23
+ position: relative;
23
24
  display: flex;
24
25
  align-items: center;
25
26
  width: 100%;
26
27
  border-radius: $md-radius;
27
28
  text-decoration: none;
29
+ transition: opacity 0.3s;
30
+ }
31
+
32
+ .n-form-frame--search .n-form-frame__menu:not(.on-search) {
33
+ opacity: 0.6;
34
+ }
35
+
36
+ .n-form-frame__menu:before {
37
+ content: '\00a0';
38
+ position: absolute;
39
+ top: 50%;
40
+ display: block;
41
+ width: 6px;
42
+ height: 6px;
43
+ margin-top: -3px;
44
+ border-radius: 500px;
45
+ opacity: 0;
46
+ transition: opacity 0.3s;
47
+ }
48
+
49
+ .n-form-frame__menu.on-search:before {
50
+ opacity: 1;
28
51
  }
29
52
 
30
53
  .n-form-frame__menu:not(:last-child) {
@@ -67,10 +90,19 @@
67
90
  padding: $-form-frame-size * 0.5 $-form-frame-size * 0.6;
68
91
  }
69
92
 
93
+ .n-form-frame--#{$suffix} .n-form-frame__search {
94
+ margin-bottom: $-form-frame-size * 0.4;
95
+ }
96
+
70
97
  .n-form-frame--#{$suffix} .n-form-frame__menu {
71
98
  height: $-form-frame-size;
72
99
  font-size: $-form-frame-font - 1;
73
100
  border-radius: $-form-frame-radius;
101
+ padding-right: $-form-frame-size * 0.6;
102
+ }
103
+
104
+ .n-form-frame--#{$suffix} .n-form-frame__menu:before {
105
+ right: $-form-frame-size * 0.3;
74
106
  }
75
107
 
76
108
  .n-form-frame--#{$suffix} .n-form-frame__menu i {
@@ -82,8 +114,4 @@
82
114
  padding: $-form-frame-size * 0.2 $-form-frame-size * 0.6 $-form-frame-size * 0.2 0;
83
115
  }
84
116
 
85
- .n-form-frame--#{$suffix} .n-form-frame__body .n-form-group {
86
- padding: $-form-frame-size * 0.2 $-form-frame-size * 0.6;
87
- }
88
-
89
117
  }
@@ -7,7 +7,7 @@
7
7
 
8
8
  .n-form-group:before {
9
9
  pointer-events: none;
10
- z-index: -1;
10
+ z-index: 0;
11
11
  content: '\00a0';
12
12
  position: absolute;
13
13
  top: 0;
@@ -20,7 +20,11 @@
20
20
  }
21
21
 
22
22
  .n-form-group.on-search:before {
23
- opacity: 0.15;
23
+ opacity: 0.1;
24
+ }
25
+
26
+ .n-form-group--collapse .n-form-group__legend {
27
+ cursor: pointer;
24
28
  }
25
29
 
26
30
  .n-form-group--classic .n-form-group__legend {
@@ -92,6 +96,7 @@
92
96
 
93
97
  .n-form-group--#{$suffix}.n-form-group--fieldset {
94
98
  margin-bottom: $-form-group-size;
99
+ padding: 0 $-form-group-size * 0.6;
95
100
  }
96
101
 
97
102
  .n-form-group--#{$suffix}.n-form-group--fieldset:first-child {
@@ -102,23 +107,23 @@
102
107
  margin-top: $-form-group-size * 1.4;
103
108
  }
104
109
 
105
- .n-form-group--classic.n-form-group--#{$suffix} .n-form-group__legend {
110
+ .n-form-group--#{$suffix}.n-form-group--classic .n-form-group__legend {
106
111
  font-size: $-form-group-font;
107
112
  min-height: $-form-group-size * 1.2;
108
113
  }
109
114
 
110
- .n-form-group--fieldset.n-form-group--#{$suffix} .n-form-group__legend {
115
+ .n-form-group--#{$suffix}.n-form-group--fieldset .n-form-group__legend {
111
116
  min-height: $-form-group-size;
112
117
  border-radius: $-form-group-radius;
113
118
  top: $-form-group-size * -0.5;
114
119
  padding: 0 $-form-group-size * 0.3;
115
120
  }
116
121
 
117
- .n-form-group--classic.n-form-group--#{$suffix} .n-form-group__label span {
122
+ .n-form-group--#{$suffix}.n-form-group--classic .n-form-group__label span {
118
123
  font-size: $-form-group-font + 1;
119
124
  }
120
125
 
121
- .n-form-group--fieldset.n-form-group--#{$suffix} .n-form-group__label span {
126
+ .n-form-group--#{$suffix}.n-form-group--fieldset .n-form-group__label span {
122
127
  font-size: $-form-group-font - 2;
123
128
  }
124
129
 
@@ -127,7 +132,7 @@
127
132
  height: $-form-group-size;
128
133
  }
129
134
 
130
- .n-form-group--fieldset.n-form-group--#{$suffix} .n-form-group__collapse {
135
+ .n-form-group--#{$suffix}.n-form-group--fieldset .n-form-group__collapse {
131
136
  margin-right: $-form-group-size * -0.3;
132
137
  }
133
138
 
@@ -135,12 +140,12 @@
135
140
  margin-right: $-form-group-size * $-form-group-ratio * 0.7;
136
141
  }
137
142
 
138
- .n-form-group--classic.n-form-group--#{$suffix} .n-form-group__body {
143
+ .n-form-group--#{$suffix}.n-form-group--classic .n-form-group__body {
139
144
  padding-top: $-form-group-size * $-form-group-ratio;
140
145
  }
141
146
 
142
- .n-form-group--fieldset.n-form-group--#{$suffix} .n-form-group__body {
143
- padding-top: $-form-group-size * 0.6;
147
+ .n-form-group--#{$suffix}.n-form-group--fieldset .n-form-group__body {
148
+ padding-top: $-form-group-size;
144
149
  }
145
150
 
146
151
  }
@@ -196,12 +196,12 @@ export default {
196
196
  }
197
197
  },
198
198
 
199
- scrollIntoView(selector, delay = 0)
199
+ scrollIntoView(selector, delay = 0, padding = 0)
200
200
  {
201
- Any.delay(() => this.onScrollIntoView(selector), delay);
201
+ Any.delay(() => this.onScrollIntoView(selector, padding), delay);
202
202
  },
203
203
 
204
- onScrollIntoView(selector)
204
+ onScrollIntoView(selector, padding = 0)
205
205
  {
206
206
  let $el = Dom.find(this.$el).find(selector);
207
207
 
@@ -214,11 +214,11 @@ export default {
214
214
  let offsetTop = $el.offsetTop(this.$el);
215
215
 
216
216
  if ( offsetTop < scrollTop ) {
217
- this.$refs.content.scrollTop = offsetTop;
217
+ this.$refs.content.scrollTop = offsetTop - padding;
218
218
  }
219
219
 
220
220
  if ( offsetTop + $el.height() >= scrollTop + outerHeight ) {
221
- this.$refs.content.scrollTop = offsetTop - outerHeight + $el.height();
221
+ this.$refs.content.scrollTop = offsetTop - outerHeight + $el.height() + padding;
222
222
  }
223
223
 
224
224
  let scrollLeft = this.$refs.content
@@ -230,11 +230,11 @@ export default {
230
230
  let offsetLeft = $el.offsetLeft(this.$el);
231
231
 
232
232
  if ( offsetLeft < scrollLeft ) {
233
- this.$refs.content.scrollLeft = offsetLeft;
233
+ this.$refs.content.scrollLeft = offsetLeft - padding;
234
234
  }
235
235
 
236
236
  if ( offsetLeft + $el.width() >= scrollLeft + outerWidth ) {
237
- this.$refs.content.scrollLeft = offsetLeft - outerWidth + $el.width();
237
+ this.$refs.content.scrollLeft = offsetLeft - outerWidth + $el.width() + padding;
238
238
  }
239
239
  },
240
240
 
@@ -15,6 +15,10 @@
15
15
  $-color-light: map.get($values, 'light');
16
16
  $-color-dark: map.get($values, 'dark');
17
17
 
18
+ .n-form-frame__menu--#{$color}.on-search:before {
19
+ background: $-color-base;
20
+ }
21
+
18
22
  .n-form-frame__menu--#{$color}.is-visible {
19
23
  background: rgba($-color-base, 0.15);
20
24
  }
@@ -1,7 +1,7 @@
1
1
  @use "sass:map";
2
2
  @import "../../../root/vars";
3
3
 
4
- .n-form-group--fieldset.n-form-group--collapse {
4
+ .n-form-group--fieldset {
5
5
  border: 1px solid $color-gray-10;
6
6
  }
7
7
 
@@ -36,7 +36,7 @@
36
36
  color: $-color-base;
37
37
  }
38
38
 
39
- .n-form-group--#{$color}.on-search:before {
39
+ .n-form-group--#{$color}:before {
40
40
  background: linear-gradient(135deg, $-color-base 0, transparent 300px);
41
41
  }
42
42