@nuvoui/core 1.1.7 → 1.2.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/README.md +90 -35
- package/dist/nuvoui.css +28531 -0
- package/dist/nuvoui.css.map +1 -0
- package/dist/nuvoui.min.css +2 -1
- package/dist/nuvoui.min.css.map +1 -0
- package/package.json +48 -27
- package/src/styles/abstracts/_config.scss +157 -0
- package/src/styles/abstracts/_functions.scss +81 -0
- package/src/styles/abstracts/_index.scss +2 -0
- package/src/styles/base/_base.scss +2 -2
- package/src/styles/base/_index.scss +2 -0
- package/src/styles/base/_reset.scss +8 -6
- package/src/styles/index.scss +11 -28
- package/src/styles/layouts/_container.scss +14 -22
- package/src/styles/layouts/_flex.scss +60 -18
- package/src/styles/layouts/_grid.scss +36 -28
- package/src/styles/layouts/_index.scss +3 -0
- package/src/styles/mixins-map.scss +877 -1225
- package/src/styles/themes/_index.scss +1 -0
- package/src/styles/themes/_theme.scss +175 -57
- package/src/styles/utilities/_alignment.scss +20 -0
- package/src/styles/utilities/_animations.scss +65 -61
- package/src/styles/utilities/_borders.scss +280 -16
- package/src/styles/utilities/_colors.scss +68 -49
- package/src/styles/utilities/_container-queries.scss +46 -7
- package/src/styles/utilities/_display.scss +57 -3
- package/src/styles/utilities/_helpers.scss +110 -108
- package/src/styles/utilities/_index.scss +19 -0
- package/src/styles/utilities/_media-queries.scss +54 -19
- package/src/styles/utilities/_opacity.scss +110 -8
- package/src/styles/utilities/_position.scss +177 -71
- package/src/styles/utilities/_shadows.scss +194 -67
- package/src/styles/utilities/_sizing.scss +62 -57
- package/src/styles/utilities/_spacing.scss +331 -64
- package/src/styles/utilities/_tooltips.scss +153 -105
- package/src/styles/utilities/_transitions.scss +152 -0
- package/src/styles/utilities/_typography.scss +113 -89
- package/src/styles/utilities/_functions.scss +0 -84
- package/src/styles/utilities/_variables.scss +0 -98
|
@@ -1,128 +1,130 @@
|
|
|
1
|
-
@use
|
|
2
|
-
@use
|
|
3
|
-
@use
|
|
4
|
-
@use
|
|
5
|
-
@use
|
|
6
|
-
|
|
1
|
+
@use "sass:string";
|
|
2
|
+
@use "sass:math";
|
|
3
|
+
@use "sass:map";
|
|
4
|
+
@use "sass:list";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
|
|
7
|
+
@use "../abstracts/config" as *;
|
|
7
8
|
|
|
8
9
|
@if $enable-debuger {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
.NuvoUI-Debugger-Wrapper {
|
|
11
|
+
color: #fff;
|
|
12
|
+
font-family: Arial, sans-serif;
|
|
13
|
+
position: fixed;
|
|
14
|
+
z-index: 999999;
|
|
15
|
+
inset: 10px auto auto 10px;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
|
|
18
|
+
&.top-left {
|
|
19
|
+
inset: 10px auto auto 10px;
|
|
20
|
+
text-align: left;
|
|
21
|
+
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
&.top-right {
|
|
24
|
+
inset: 10px 10px auto auto;
|
|
25
|
+
text-align: right;
|
|
26
|
+
}
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
&.bottom-left {
|
|
29
|
+
inset: auto auto 10px 10px;
|
|
30
|
+
text-align: left;
|
|
31
|
+
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
&.bottom-right {
|
|
34
|
+
inset: auto 10px 10px auto;
|
|
35
|
+
text-align: right;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
.NuvoUI-Debugger-Main,
|
|
39
|
+
.NuvoUI-Debugger {
|
|
40
|
+
padding: 10px;
|
|
41
|
+
background-color: rgb(0 0 0 / 80%);
|
|
42
|
+
border-radius: 5px;
|
|
43
|
+
border: 1px solid green;
|
|
44
|
+
box-shadow: 0 0 2px 0 #fff;
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
.NuvoUI-Debugger-Main {
|
|
49
|
+
$breakpoint-keys: map.keys($breakpoints);
|
|
50
|
+
$total: list.length($breakpoint-keys);
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
&::before,
|
|
53
|
+
&::after {
|
|
54
|
+
font-family: "Courier New", Courier, monospace;
|
|
55
|
+
font-size: 0.8em;
|
|
56
|
+
display: block;
|
|
57
|
+
}
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
&::before {
|
|
60
|
+
font-weight: bold;
|
|
61
|
+
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
} @else {
|
|
72
|
-
$prev: list.nth($breakpoint-keys, $i - 1);
|
|
73
|
-
$prev-width: map.get($breakpoints, $prev);
|
|
74
|
-
|
|
75
|
-
@media (min-width: #{$prev-width}) and (max-width: (#{$current-width} - 1)) {
|
|
76
|
-
&::before {
|
|
77
|
-
content: "Screen: #{$current}";
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
63
|
+
@for $i from 1 through $total {
|
|
64
|
+
$current: list.nth($breakpoint-keys, $i);
|
|
65
|
+
$current-width: map.get($breakpoints, $current);
|
|
66
|
+
|
|
67
|
+
@if $i == 1 {
|
|
68
|
+
@media (max-width: #{$current-width}) {
|
|
69
|
+
&::before {
|
|
70
|
+
content: "Screen: #{$current}";
|
|
81
71
|
}
|
|
72
|
+
}
|
|
73
|
+
} @else {
|
|
74
|
+
$prev: list.nth($breakpoint-keys, $i - 1);
|
|
75
|
+
$prev-width: map.get($breakpoints, $prev);
|
|
82
76
|
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
@media (min-width: #{$prev-width}) and (max-width: (#{$current-width} - 1)) {
|
|
78
|
+
&::before {
|
|
79
|
+
content: "Screen: #{$current}";
|
|
85
80
|
}
|
|
81
|
+
}
|
|
86
82
|
}
|
|
83
|
+
}
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
&::after {
|
|
86
|
+
content: attr(data-size);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
font-family: 'Courier New', Courier, monospace;
|
|
94
|
-
font-size: 0.8em;
|
|
95
|
-
display: block;
|
|
96
|
-
}
|
|
90
|
+
.NuvoUI-Debugger {
|
|
91
|
+
margin-top: 10px;
|
|
97
92
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
&::before,
|
|
94
|
+
&::after {
|
|
95
|
+
font-family: "Courier New", Courier, monospace;
|
|
96
|
+
font-size: 0.8em;
|
|
97
|
+
display: block;
|
|
98
|
+
}
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
&::before {
|
|
101
|
+
font-weight: bold;
|
|
102
|
+
content: attr(data-element);
|
|
103
|
+
}
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
105
|
+
&::after {
|
|
106
|
+
content: attr(data-size);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.NuvoUI-Debugger-Close {
|
|
111
|
+
color: #fff;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
font-size: 14px;
|
|
114
|
+
pointer-events: auto;
|
|
115
|
+
position: absolute;
|
|
116
|
+
right: 0;
|
|
117
|
+
top: 0;
|
|
118
|
+
background: #00800199;
|
|
119
|
+
border-radius: 20px;
|
|
120
|
+
height: 14px;
|
|
121
|
+
width: 14px;
|
|
122
|
+
line-height: 14px;
|
|
123
|
+
text-align: center;
|
|
124
|
+
|
|
125
|
+
&:hover {
|
|
126
|
+
background: #008001;
|
|
127
|
+
}
|
|
127
128
|
}
|
|
128
|
-
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@use "../abstracts/config" as cfg;
|
|
2
|
+
|
|
3
|
+
// Forward all utility files
|
|
4
|
+
@forward "alignment";
|
|
5
|
+
@forward "animations";
|
|
6
|
+
@forward "borders";
|
|
7
|
+
@forward "colors";
|
|
8
|
+
@forward "container-queries";
|
|
9
|
+
@forward "display";
|
|
10
|
+
@forward "helpers";
|
|
11
|
+
@forward "media-queries";
|
|
12
|
+
@forward "opacity";
|
|
13
|
+
@forward "position";
|
|
14
|
+
@forward "shadows";
|
|
15
|
+
@forward "sizing";
|
|
16
|
+
@forward "spacing";
|
|
17
|
+
@forward "tooltips";
|
|
18
|
+
@forward "transitions";
|
|
19
|
+
@forward "typography";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// Section: Utilities
|
|
2
2
|
// Module: Media Queries
|
|
3
3
|
|
|
4
|
-
@use
|
|
5
|
-
@use
|
|
6
|
-
@use
|
|
7
|
-
@use
|
|
8
|
-
|
|
4
|
+
@use "sass:map";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
@use "../abstracts" as *;
|
|
7
|
+
@use "../abstracts/functions" as FN;
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* @description Media query mixins.
|
|
@@ -13,38 +12,39 @@
|
|
|
13
12
|
* @param {string} $type - The media query type (e.g. 'lg', 'md').
|
|
14
13
|
*/
|
|
15
14
|
@mixin media-up($breakpoint) {
|
|
16
|
-
@media screen and (min-width:
|
|
15
|
+
@media screen and (min-width: FN.get-breakpoint-value($breakpoint)) {
|
|
17
16
|
@content;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
@mixin media-down($breakpoint) {
|
|
22
|
-
|
|
21
|
+
$val: FN.get-breakpoint-value($breakpoint) - 0.01rm;
|
|
22
|
+
@media screen and (max-width: #{$val}) {
|
|
23
23
|
@content;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
@mixin media-between($lower, $upper) {
|
|
28
28
|
$lower-val: FN.get-breakpoint-value($lower);
|
|
29
|
-
$upper-val: FN.get-breakpoint-value($upper);
|
|
30
|
-
@media screen and (min-width: #{$lower-val}) and (max-width:
|
|
29
|
+
$upper-val: FN.get-breakpoint-value($upper) - 0.01rm;
|
|
30
|
+
@media screen and (min-width: #{$lower-val}) and (max-width: #{$upper-val}) {
|
|
31
31
|
@content;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Only at specific breakpoint
|
|
36
|
-
@mixin media-only($breakpoint) {
|
|
36
|
+
@mixin media-only($breakpoint) {
|
|
37
37
|
$min: FN.get-breakpoint-value($breakpoint);
|
|
38
38
|
$next-breakpoint: null;
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
@each $name, $width in $breakpoints {
|
|
41
|
-
@if $width > $min and (
|
|
42
|
-
$next-breakpoint:
|
|
41
|
+
@if $width > $min and (meta.type-of($next-breakpoint) == "null" or $width < $next-breakpoint) {
|
|
42
|
+
$next-breakpoint: $width;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
@if $next-breakpoint {
|
|
47
|
-
@media (min-width: #{$min}) and (max-width:
|
|
47
|
+
@media (min-width: #{$min}) and (max-width: #{$next-breakpoint - 0.02px}) {
|
|
48
48
|
@content;
|
|
49
49
|
}
|
|
50
50
|
} @else {
|
|
@@ -75,12 +75,26 @@
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
//
|
|
79
|
-
|
|
78
|
+
// System preference only
|
|
79
|
+
@mixin prefers-dark {
|
|
80
|
+
@media (prefers-color-scheme: dark) {
|
|
81
|
+
@content;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// User preference takes precedence
|
|
80
86
|
@mixin dark-mode {
|
|
81
|
-
|
|
87
|
+
// Apply when user explicitly chooses dark
|
|
88
|
+
[data-theme="dark"] & {
|
|
82
89
|
@content;
|
|
83
90
|
}
|
|
91
|
+
|
|
92
|
+
// Apply when system is dark AND user hasn't made a choice
|
|
93
|
+
@media (prefers-color-scheme: dark) {
|
|
94
|
+
[data-theme="system"] & {
|
|
95
|
+
@content;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
// Device orientation
|
|
@@ -106,7 +120,7 @@
|
|
|
106
120
|
@supports (height: 100dvh) {
|
|
107
121
|
height: 100dvh;
|
|
108
122
|
}
|
|
109
|
-
|
|
123
|
+
|
|
110
124
|
@supports not (height: 100dvh) {
|
|
111
125
|
height: 100vh;
|
|
112
126
|
}
|
|
@@ -123,6 +137,27 @@
|
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
|
|
140
|
+
// Data-saving mode
|
|
141
|
+
@mixin save-data {
|
|
142
|
+
@media (prefers-reduced-data: reduce) {
|
|
143
|
+
@content;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Mouse precision detection
|
|
148
|
+
@mixin fine-pointer {
|
|
149
|
+
@media (pointer: fine) {
|
|
150
|
+
@content;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Display mode for PWAs
|
|
155
|
+
@mixin display-mode($mode: "standalone") {
|
|
156
|
+
@media (display-mode: #{$mode}) {
|
|
157
|
+
@content;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
126
161
|
// High contrast mode
|
|
127
162
|
@mixin high-contrast {
|
|
128
163
|
@media (forced-colors: active) {
|
|
@@ -1,20 +1,122 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Section: Presentation
|
|
2
|
+
// Module: Opacity
|
|
2
3
|
|
|
3
|
-
@use
|
|
4
|
-
@use
|
|
4
|
+
@use "sass:math";
|
|
5
|
+
@use "../abstracts" as *;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @component Opacity
|
|
9
|
+
* @description Controls element transparency with customizable opacity values and interactive states
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <!-- Basic opacity -->
|
|
13
|
+
* <div class="opacity-50">This element has 50% opacity</div>
|
|
14
|
+
*
|
|
15
|
+
* <!-- Responsive opacity -->
|
|
16
|
+
* <div class="opacity-100 opacity-50@md">
|
|
17
|
+
* 100% opacity by default, 50% on medium screens and up
|
|
18
|
+
* </div>
|
|
19
|
+
*
|
|
20
|
+
* <!-- Interactive states -->
|
|
21
|
+
* <div class="opacity-50 hover:opacity-100">
|
|
22
|
+
* 50% opacity, becomes fully visible on hover
|
|
23
|
+
* </div>
|
|
24
|
+
*
|
|
25
|
+
* <button class="opacity-70 focus:opacity-100">
|
|
26
|
+
* 70% opacity, fully visible when focused
|
|
27
|
+
* </button>
|
|
28
|
+
*
|
|
29
|
+
* <div class="opacity-75 active:opacity-100">
|
|
30
|
+
* 75% opacity, fully visible when clicked/active
|
|
31
|
+
* </div>
|
|
32
|
+
*
|
|
33
|
+
* <!-- Group hover effect -->
|
|
34
|
+
* <div class="group">
|
|
35
|
+
* <h3>Parent element with "group" class</h3>
|
|
36
|
+
* <div class="opacity-0 group-hover:opacity-100">
|
|
37
|
+
* Hidden by default, visible when parent is hovered
|
|
38
|
+
* </div>
|
|
39
|
+
* </div>
|
|
40
|
+
*
|
|
41
|
+
* <!-- With transition -->
|
|
42
|
+
* <div class="opacity-50 hover:opacity-100 transition-opacity">
|
|
43
|
+
* Smooth opacity transition on hover
|
|
44
|
+
* </div>
|
|
45
|
+
*
|
|
46
|
+
* @classes
|
|
47
|
+
* Base:
|
|
48
|
+
* - opacity-{value}: Sets element opacity (0-100%)
|
|
49
|
+
* Values: 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80, 90, 100
|
|
50
|
+
*
|
|
51
|
+
* Interactive States:
|
|
52
|
+
* - hover:opacity-{value}: Changes opacity on mouse hover
|
|
53
|
+
* - focus:opacity-{value}: Changes opacity when element receives focus
|
|
54
|
+
* - active:opacity-{value}: Changes opacity when element is active/pressed
|
|
55
|
+
* - group-hover:opacity-{value}: Changes opacity when parent with .group class is hovered
|
|
56
|
+
*
|
|
57
|
+
* Animation:
|
|
58
|
+
* - transition-opacity: Adds smooth transition when opacity changes
|
|
59
|
+
*
|
|
60
|
+
* @responsive
|
|
61
|
+
* All opacity classes support responsive variants using @breakpoint suffix:
|
|
62
|
+
* - opacity-50@sm: 50% opacity on small screens and up
|
|
63
|
+
* - hover:opacity-100@md: Full opacity on hover for medium screens and up
|
|
64
|
+
*
|
|
65
|
+
* Available breakpoints: xs, sm, md, lg, xl, xxl
|
|
66
|
+
*
|
|
67
|
+
* @customization
|
|
68
|
+
* Opacity values are defined in the $percentages variable
|
|
69
|
+
* Transition timing can be customized via CSS variables
|
|
70
|
+
*
|
|
71
|
+
* @see transitions
|
|
72
|
+
*/
|
|
5
73
|
|
|
6
74
|
// Opacity Utilities
|
|
7
75
|
@each $i in $percentages {
|
|
8
|
-
.opacity-#{$i} {
|
|
9
|
-
|
|
76
|
+
.opacity-#{$i} {
|
|
77
|
+
opacity: math.div($i, 100);
|
|
78
|
+
}
|
|
79
|
+
.hover\:opacity-#{$i}:hover {
|
|
80
|
+
opacity: math.div($i, 100);
|
|
81
|
+
}
|
|
82
|
+
.focus\:opacity-#{$i}:focus {
|
|
83
|
+
opacity: math.div($i, 100);
|
|
84
|
+
}
|
|
85
|
+
.active\:opacity-#{$i}:active {
|
|
86
|
+
opacity: math.div($i, 100);
|
|
87
|
+
}
|
|
88
|
+
.group:hover .group-hover\:opacity-#{$i} {
|
|
89
|
+
opacity: math.div($i, 100);
|
|
90
|
+
}
|
|
10
91
|
}
|
|
11
92
|
|
|
12
93
|
// Responsive Variants for Opacity
|
|
13
94
|
@each $breakpoint, $width in $breakpoints {
|
|
14
95
|
@media (min-width: #{$width}) {
|
|
15
96
|
@each $i in $percentages {
|
|
16
|
-
.opacity-#{$i}\@#{$breakpoint} {
|
|
17
|
-
|
|
97
|
+
.opacity-#{$i}\@#{$breakpoint} {
|
|
98
|
+
opacity: math.div($i, 100);
|
|
99
|
+
}
|
|
100
|
+
.hover\:opacity-#{$i}\@#{$breakpoint}:hover {
|
|
101
|
+
opacity: math.div($i, 100);
|
|
102
|
+
}
|
|
103
|
+
.focus\:opacity-#{$i}\@#{$breakpoint}:focus {
|
|
104
|
+
opacity: math.div($i, 100);
|
|
105
|
+
}
|
|
106
|
+
.active\:opacity-#{$i}\@#{$breakpoint}:active {
|
|
107
|
+
opacity: math.div($i, 100);
|
|
108
|
+
}
|
|
109
|
+
.group:hover .group-hover\:opacity-#{$i}\@#{$breakpoint} {
|
|
110
|
+
opacity: math.div($i, 100);
|
|
111
|
+
}
|
|
18
112
|
}
|
|
19
113
|
}
|
|
20
|
-
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Transition Opacity
|
|
117
|
+
// TODO move to transitons may be?
|
|
118
|
+
.transition-opacity {
|
|
119
|
+
transition-property: opacity;
|
|
120
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
121
|
+
transition-duration: 150ms;
|
|
122
|
+
}
|