@justin_evo/evo-ui 1.2.0 → 1.2.1

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.
Files changed (77) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +70 -70
  3. package/dist/declarations.d.ts +6 -6
  4. package/package.json +52 -52
  5. package/src/Alert/Alert.tsx +49 -49
  6. package/src/AutoComplete/AutoComplete.tsx +810 -810
  7. package/src/Badge/Badge.tsx +53 -53
  8. package/src/Breadcrumb/Breadcrumb.tsx +53 -53
  9. package/src/Button/Button.tsx +125 -125
  10. package/src/Card/Card.tsx +257 -257
  11. package/src/Checkbox/Checkbox.tsx +59 -59
  12. package/src/CommandPalette/CommandPalette.tsx +185 -185
  13. package/src/Container/Container.tsx +31 -31
  14. package/src/Divider/Divider.tsx +31 -31
  15. package/src/Form/Form.tsx +185 -185
  16. package/src/Grid/Grid.tsx +66 -66
  17. package/src/ImageCropper/ImageCropper.tsx +911 -911
  18. package/src/Input/Input.tsx +74 -74
  19. package/src/Modal/Modal.tsx +77 -77
  20. package/src/Nav/Nav.tsx +708 -708
  21. package/src/Notification/Notification.tsx +1503 -1503
  22. package/src/Pagination/Pagination.tsx +76 -76
  23. package/src/Radio/Radio.tsx +69 -69
  24. package/src/RichTextArea/RichTextArea.tsx +886 -886
  25. package/src/Select/Select.tsx +515 -515
  26. package/src/Skeleton/Skeleton.tsx +70 -70
  27. package/src/Stack/Stack.tsx +52 -52
  28. package/src/Table/Table.tsx +335 -335
  29. package/src/Tabs/Tabs.tsx +90 -90
  30. package/src/Theme/ThemeProvider.tsx +253 -253
  31. package/src/Theme/ThemeToggle.tsx +79 -79
  32. package/src/Toggle/Toggle.tsx +48 -48
  33. package/src/Tooltip/Tooltip.tsx +38 -38
  34. package/src/TopNav/TopNav.tsx +1163 -1163
  35. package/src/TreeSelect/TreeSelect.tsx +825 -825
  36. package/src/css/alert.module.scss +93 -93
  37. package/src/css/autocomplete.module.scss +416 -416
  38. package/src/css/badge.module.scss +82 -82
  39. package/src/css/base/_color.scss +159 -159
  40. package/src/css/base/_theme.scss +237 -237
  41. package/src/css/base/_variables.scss +161 -161
  42. package/src/css/breadcrumb.module.scss +50 -50
  43. package/src/css/button.module.scss +385 -385
  44. package/src/css/card.module.scss +217 -217
  45. package/src/css/checkbox.module.scss +123 -123
  46. package/src/css/commandpalette.module.scss +211 -211
  47. package/src/css/container.module.scss +18 -18
  48. package/src/css/divider.module.scss +41 -41
  49. package/src/css/form.module.scss +245 -245
  50. package/src/css/imagecropper.module.scss +397 -397
  51. package/src/css/input.module.scss +89 -89
  52. package/src/css/modal.module.scss +105 -105
  53. package/src/css/nav.module.scss +494 -494
  54. package/src/css/notification.module.scss +691 -691
  55. package/src/css/pagination.module.scss +63 -63
  56. package/src/css/radio.module.scss +89 -89
  57. package/src/css/richtextarea.module.scss +307 -307
  58. package/src/css/select.module.scss +525 -525
  59. package/src/css/skeleton.module.scss +30 -30
  60. package/src/css/table.module.scss +386 -386
  61. package/src/css/tabs.module.scss +63 -63
  62. package/src/css/theme-toggle.module.scss +83 -83
  63. package/src/css/toggle.module.scss +54 -54
  64. package/src/css/tooltip.module.scss +97 -97
  65. package/src/css/topnav.module.scss +568 -568
  66. package/src/css/treeselect.module.scss +558 -558
  67. package/src/css/utilities/_borders.scss +111 -111
  68. package/src/css/utilities/_colors.scss +66 -66
  69. package/src/css/utilities/_effects.scss +216 -216
  70. package/src/css/utilities/_layout.scss +181 -181
  71. package/src/css/utilities/_position.scss +75 -75
  72. package/src/css/utilities/_sizing.scss +138 -138
  73. package/src/css/utilities/_spacing.scss +99 -99
  74. package/src/css/utilities/_typography.scss +121 -121
  75. package/src/css/utilities/index.scss +24 -24
  76. package/src/declarations.d.ts +6 -6
  77. package/src/index.ts +60 -60
@@ -1,217 +1,217 @@
1
- @use './base/variables' as *;
2
-
3
- // ============================================================
4
- // EvoCard
5
- // ------------------------------------------------------------
6
- // Three orthogonal axes:
7
- // 1. variant — elevated / outlined / ghost
8
- // 2. orientation — vertical / horizontal / responsive
9
- // 3. interactive — adds hover / focus / press states for
10
- // when the root is a <button> or <a>
11
- //
12
- // All colours / shadows come from semantic tokens so the same
13
- // rules render correctly under data-theme="light" and "dark".
14
- // ============================================================
15
-
16
- .root {
17
- display: flex;
18
- flex-direction: column;
19
- background-color: $color-surface-elevated;
20
- color: $color-text-primary;
21
- border: 1px solid transparent;
22
- border-radius: $evo-border-radius-lg;
23
- overflow: hidden;
24
- text-align: left;
25
- text-decoration: none;
26
- font-family: inherit;
27
- transition:
28
- box-shadow $transition-fast,
29
- transform $transition-fast,
30
- border-color $transition-fast,
31
- background-color $transition-fast;
32
- }
33
-
34
- // ----- Variants ---------------------------------------------
35
-
36
- .elevated {
37
- background-color: $color-surface-elevated;
38
- box-shadow: $shadow-md;
39
- }
40
-
41
- .outlined {
42
- background-color: $color-surface;
43
- border-color: $color-border;
44
- box-shadow: none;
45
- }
46
-
47
- .ghost {
48
- background-color: transparent;
49
- border-color: transparent;
50
- box-shadow: none;
51
- }
52
-
53
- // ----- Orientation ------------------------------------------
54
- //
55
- // Horizontal layouts use CSS grid: a fixed-ish media column on
56
- // the left and content stacked on the right. `:has(> .media)`
57
- // gates the two-column grid so cards without a media slot stay
58
- // single-column even in horizontal/responsive mode.
59
-
60
- .orient-vertical {
61
- flex-direction: column;
62
- }
63
-
64
- .orient-horizontal {
65
- display: grid;
66
- grid-template-columns: minmax(0, 1fr);
67
-
68
- &:has(> .media) {
69
- grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
70
- }
71
-
72
- > .media {
73
- grid-row: 1 / -1;
74
- grid-column: 1;
75
- }
76
-
77
- > :not(.media) {
78
- grid-column: -2;
79
- }
80
- }
81
-
82
- .orient-responsive {
83
- flex-direction: column;
84
-
85
- @media (min-width: 768px) {
86
- display: grid;
87
- flex-direction: initial;
88
- grid-template-columns: minmax(0, 1fr);
89
-
90
- &:has(> .media) {
91
- grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
92
- }
93
-
94
- > .media {
95
- grid-row: 1 / -1;
96
- grid-column: 1;
97
- }
98
-
99
- > :not(.media) {
100
- grid-column: -2;
101
- }
102
- }
103
- }
104
-
105
- // ----- Interactive (real <button> / <a>) --------------------
106
-
107
- .interactive {
108
- cursor: pointer;
109
- user-select: none;
110
- appearance: none;
111
- width: 100%;
112
- font: inherit;
113
- -webkit-tap-highlight-color: transparent;
114
- touch-action: manipulation;
115
- // a11y: cards used as buttons can be short — guarantee a 44px
116
- // touch target so they stay tappable on mobile.
117
- min-height: 2.75rem;
118
-
119
- &:hover:not(:disabled) {
120
- transform: translateY(-2px);
121
- box-shadow: $shadow-lg;
122
- }
123
-
124
- &.outlined:hover:not(:disabled) {
125
- border-color: $color-border-strong;
126
- }
127
-
128
- &.ghost:hover:not(:disabled) {
129
- background-color: $color-surface-hover;
130
- }
131
-
132
- &:active:not(:disabled) {
133
- transform: translateY(0);
134
- box-shadow: $shadow-sm;
135
- }
136
-
137
- &:focus-visible {
138
- outline: 2px solid $evo-primary-focus;
139
- outline-offset: 2px;
140
- }
141
-
142
- &:disabled,
143
- &[aria-disabled='true'] {
144
- opacity: 0.5;
145
- cursor: not-allowed;
146
- pointer-events: none;
147
- }
148
- }
149
-
150
- // ----- Slots ------------------------------------------------
151
-
152
- .media {
153
- display: block;
154
- overflow: hidden;
155
- background-color: $color-surface-sunken;
156
- }
157
-
158
- .mediaImg {
159
- display: block;
160
- width: 100%;
161
- height: 100%;
162
- object-fit: cover;
163
- }
164
-
165
- .header {
166
- display: flex;
167
- flex-direction: column;
168
- gap: 0.25rem;
169
- padding: 1rem 1.25rem 0.5rem;
170
- }
171
-
172
- .body {
173
- flex: 1 1 auto;
174
- min-width: 0;
175
- padding: 0.5rem 1.25rem 1rem;
176
- }
177
-
178
- .footer {
179
- padding: 0.75rem 1.25rem;
180
- border-top: 1px solid $color-border-subtle;
181
- }
182
-
183
- // When the card has only a body (no header/footer), pad the body
184
- // like a full block so content doesn't look cramped.
185
- .root > .body:only-child {
186
- padding: 1.25rem;
187
- }
188
-
189
- // ----- Typography -------------------------------------------
190
-
191
- .title {
192
- margin: 0;
193
- font-size: $text-lg;
194
- font-weight: 700;
195
- line-height: 1.3;
196
- color: $color-text-primary;
197
- }
198
-
199
- .description {
200
- margin: 0;
201
- font-size: $text-sm;
202
- line-height: 1.55;
203
- color: $color-text-secondary;
204
- }
205
-
206
- // ----- Motion preferences -----------------------------------
207
-
208
- @media (prefers-reduced-motion: reduce) {
209
- .root,
210
- .interactive {
211
- transition: none;
212
-
213
- &:hover:not(:disabled) {
214
- transform: none;
215
- }
216
- }
217
- }
1
+ @use './base/variables' as *;
2
+
3
+ // ============================================================
4
+ // EvoCard
5
+ // ------------------------------------------------------------
6
+ // Three orthogonal axes:
7
+ // 1. variant — elevated / outlined / ghost
8
+ // 2. orientation — vertical / horizontal / responsive
9
+ // 3. interactive — adds hover / focus / press states for
10
+ // when the root is a <button> or <a>
11
+ //
12
+ // All colours / shadows come from semantic tokens so the same
13
+ // rules render correctly under data-theme="light" and "dark".
14
+ // ============================================================
15
+
16
+ .root {
17
+ display: flex;
18
+ flex-direction: column;
19
+ background-color: $color-surface-elevated;
20
+ color: $color-text-primary;
21
+ border: 1px solid transparent;
22
+ border-radius: $evo-border-radius-lg;
23
+ overflow: hidden;
24
+ text-align: left;
25
+ text-decoration: none;
26
+ font-family: inherit;
27
+ transition:
28
+ box-shadow $transition-fast,
29
+ transform $transition-fast,
30
+ border-color $transition-fast,
31
+ background-color $transition-fast;
32
+ }
33
+
34
+ // ----- Variants ---------------------------------------------
35
+
36
+ .elevated {
37
+ background-color: $color-surface-elevated;
38
+ box-shadow: $shadow-md;
39
+ }
40
+
41
+ .outlined {
42
+ background-color: $color-surface;
43
+ border-color: $color-border;
44
+ box-shadow: none;
45
+ }
46
+
47
+ .ghost {
48
+ background-color: transparent;
49
+ border-color: transparent;
50
+ box-shadow: none;
51
+ }
52
+
53
+ // ----- Orientation ------------------------------------------
54
+ //
55
+ // Horizontal layouts use CSS grid: a fixed-ish media column on
56
+ // the left and content stacked on the right. `:has(> .media)`
57
+ // gates the two-column grid so cards without a media slot stay
58
+ // single-column even in horizontal/responsive mode.
59
+
60
+ .orient-vertical {
61
+ flex-direction: column;
62
+ }
63
+
64
+ .orient-horizontal {
65
+ display: grid;
66
+ grid-template-columns: minmax(0, 1fr);
67
+
68
+ &:has(> .media) {
69
+ grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
70
+ }
71
+
72
+ > .media {
73
+ grid-row: 1 / -1;
74
+ grid-column: 1;
75
+ }
76
+
77
+ > :not(.media) {
78
+ grid-column: -2;
79
+ }
80
+ }
81
+
82
+ .orient-responsive {
83
+ flex-direction: column;
84
+
85
+ @media (min-width: 768px) {
86
+ display: grid;
87
+ flex-direction: initial;
88
+ grid-template-columns: minmax(0, 1fr);
89
+
90
+ &:has(> .media) {
91
+ grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
92
+ }
93
+
94
+ > .media {
95
+ grid-row: 1 / -1;
96
+ grid-column: 1;
97
+ }
98
+
99
+ > :not(.media) {
100
+ grid-column: -2;
101
+ }
102
+ }
103
+ }
104
+
105
+ // ----- Interactive (real <button> / <a>) --------------------
106
+
107
+ .interactive {
108
+ cursor: pointer;
109
+ user-select: none;
110
+ appearance: none;
111
+ width: 100%;
112
+ font: inherit;
113
+ -webkit-tap-highlight-color: transparent;
114
+ touch-action: manipulation;
115
+ // a11y: cards used as buttons can be short — guarantee a 44px
116
+ // touch target so they stay tappable on mobile.
117
+ min-height: 2.75rem;
118
+
119
+ &:hover:not(:disabled) {
120
+ transform: translateY(-2px);
121
+ box-shadow: $shadow-lg;
122
+ }
123
+
124
+ &.outlined:hover:not(:disabled) {
125
+ border-color: $color-border-strong;
126
+ }
127
+
128
+ &.ghost:hover:not(:disabled) {
129
+ background-color: $color-surface-hover;
130
+ }
131
+
132
+ &:active:not(:disabled) {
133
+ transform: translateY(0);
134
+ box-shadow: $shadow-sm;
135
+ }
136
+
137
+ &:focus-visible {
138
+ outline: 2px solid $evo-primary-focus;
139
+ outline-offset: 2px;
140
+ }
141
+
142
+ &:disabled,
143
+ &[aria-disabled='true'] {
144
+ opacity: 0.5;
145
+ cursor: not-allowed;
146
+ pointer-events: none;
147
+ }
148
+ }
149
+
150
+ // ----- Slots ------------------------------------------------
151
+
152
+ .media {
153
+ display: block;
154
+ overflow: hidden;
155
+ background-color: $color-surface-sunken;
156
+ }
157
+
158
+ .mediaImg {
159
+ display: block;
160
+ width: 100%;
161
+ height: 100%;
162
+ object-fit: cover;
163
+ }
164
+
165
+ .header {
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: 0.25rem;
169
+ padding: 1rem 1.25rem 0.5rem;
170
+ }
171
+
172
+ .body {
173
+ flex: 1 1 auto;
174
+ min-width: 0;
175
+ padding: 0.5rem 1.25rem 1rem;
176
+ }
177
+
178
+ .footer {
179
+ padding: 0.75rem 1.25rem;
180
+ border-top: 1px solid $color-border-subtle;
181
+ }
182
+
183
+ // When the card has only a body (no header/footer), pad the body
184
+ // like a full block so content doesn't look cramped.
185
+ .root > .body:only-child {
186
+ padding: 1.25rem;
187
+ }
188
+
189
+ // ----- Typography -------------------------------------------
190
+
191
+ .title {
192
+ margin: 0;
193
+ font-size: $text-lg;
194
+ font-weight: 700;
195
+ line-height: 1.3;
196
+ color: $color-text-primary;
197
+ }
198
+
199
+ .description {
200
+ margin: 0;
201
+ font-size: $text-sm;
202
+ line-height: 1.55;
203
+ color: $color-text-secondary;
204
+ }
205
+
206
+ // ----- Motion preferences -----------------------------------
207
+
208
+ @media (prefers-reduced-motion: reduce) {
209
+ .root,
210
+ .interactive {
211
+ transition: none;
212
+
213
+ &:hover:not(:disabled) {
214
+ transform: none;
215
+ }
216
+ }
217
+ }
@@ -1,123 +1,123 @@
1
- @use 'base/variables' as *;
2
- @use 'base/color' as *;
3
-
4
- .group {
5
- border: none;
6
- padding: 0;
7
- margin: 0;
8
- display: flex;
9
- flex-direction: column;
10
- gap: 0.5rem;
11
- }
12
-
13
- .groupLabel {
14
- font-size: $text-sm;
15
- font-weight: 600;
16
- color: $color-text-primary;
17
- margin-bottom: 0.125rem;
18
- font-family: $font-sans;
19
- }
20
-
21
- .checkbox {
22
- display: flex;
23
- flex-direction: column;
24
- gap: 0.25rem;
25
-
26
- &.disabled {
27
- opacity: 0.5;
28
- pointer-events: none;
29
- }
30
- }
31
-
32
- .input {
33
- position: absolute;
34
- opacity: 0;
35
- width: 0;
36
- height: 0;
37
- pointer-events: none;
38
-
39
- &:checked + .label .checkmark {
40
- background-color: $evo-primary-color;
41
- border-color: $evo-primary-color;
42
-
43
- &::after {
44
- opacity: 1;
45
- transform: translate(-50%, -60%) rotate(45deg) scale(1);
46
- }
47
- }
48
-
49
- &:indeterminate + .label .checkmark {
50
- background-color: $evo-primary-color;
51
- border-color: $evo-primary-color;
52
-
53
- &::after {
54
- content: '';
55
- position: absolute;
56
- top: 50%;
57
- left: 50%;
58
- transform: translate(-50%, -50%) !important;
59
- width: 8px;
60
- height: 2px;
61
- background: $evo-primary-fg;
62
- border: none;
63
- opacity: 1;
64
- }
65
- }
66
-
67
- &:focus-visible + .label .checkmark {
68
- outline: 2px solid $evo-primary-focus;
69
- outline-offset: 2px;
70
- }
71
- }
72
-
73
- .label {
74
- display: flex;
75
- align-items: center;
76
- gap: 0.5rem;
77
- cursor: pointer;
78
- font-family: $font-sans;
79
- }
80
-
81
- .checkmark {
82
- position: relative;
83
- display: inline-flex;
84
- align-items: center;
85
- justify-content: center;
86
- width: 1rem;
87
- height: 1rem;
88
- border: 2px solid $color-border;
89
- border-radius: $radius-sm;
90
- background: $color-surface;
91
- transition: background-color $transition-fast, border-color $transition-fast;
92
- flex-shrink: 0;
93
-
94
- &::after {
95
- content: '';
96
- position: absolute;
97
- top: 50%;
98
- left: 50%;
99
- width: 5px;
100
- height: 9px;
101
- border: 2px solid $evo-primary-fg;
102
- border-top: none;
103
- border-left: none;
104
- opacity: 0;
105
- // Centered via translate (parent's flex-centering can't reach an absolute
106
- // child). -60% Y nudges the rotated "L" optically into the middle. The
107
- // centering translate is folded into both states so the scale stays put.
108
- transform: translate(-50%, -60%) rotate(45deg) scale(0.5);
109
- transition: opacity $transition-fast, transform $transition-fast;
110
- }
111
- }
112
-
113
- .labelText {
114
- font-size: $text-sm;
115
- color: $color-text-primary;
116
- }
117
-
118
- .helperText {
119
- font-size: $text-xs;
120
- color: $color-text-muted;
121
- padding-left: 1.5rem;
122
- margin: 0;
123
- }
1
+ @use 'base/variables' as *;
2
+ @use 'base/color' as *;
3
+
4
+ .group {
5
+ border: none;
6
+ padding: 0;
7
+ margin: 0;
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: 0.5rem;
11
+ }
12
+
13
+ .groupLabel {
14
+ font-size: $text-sm;
15
+ font-weight: 600;
16
+ color: $color-text-primary;
17
+ margin-bottom: 0.125rem;
18
+ font-family: $font-sans;
19
+ }
20
+
21
+ .checkbox {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 0.25rem;
25
+
26
+ &.disabled {
27
+ opacity: 0.5;
28
+ pointer-events: none;
29
+ }
30
+ }
31
+
32
+ .input {
33
+ position: absolute;
34
+ opacity: 0;
35
+ width: 0;
36
+ height: 0;
37
+ pointer-events: none;
38
+
39
+ &:checked + .label .checkmark {
40
+ background-color: $evo-primary-color;
41
+ border-color: $evo-primary-color;
42
+
43
+ &::after {
44
+ opacity: 1;
45
+ transform: translate(-50%, -60%) rotate(45deg) scale(1);
46
+ }
47
+ }
48
+
49
+ &:indeterminate + .label .checkmark {
50
+ background-color: $evo-primary-color;
51
+ border-color: $evo-primary-color;
52
+
53
+ &::after {
54
+ content: '';
55
+ position: absolute;
56
+ top: 50%;
57
+ left: 50%;
58
+ transform: translate(-50%, -50%) !important;
59
+ width: 8px;
60
+ height: 2px;
61
+ background: $evo-primary-fg;
62
+ border: none;
63
+ opacity: 1;
64
+ }
65
+ }
66
+
67
+ &:focus-visible + .label .checkmark {
68
+ outline: 2px solid $evo-primary-focus;
69
+ outline-offset: 2px;
70
+ }
71
+ }
72
+
73
+ .label {
74
+ display: flex;
75
+ align-items: center;
76
+ gap: 0.5rem;
77
+ cursor: pointer;
78
+ font-family: $font-sans;
79
+ }
80
+
81
+ .checkmark {
82
+ position: relative;
83
+ display: inline-flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ width: 1rem;
87
+ height: 1rem;
88
+ border: 2px solid $color-border;
89
+ border-radius: $radius-sm;
90
+ background: $color-surface;
91
+ transition: background-color $transition-fast, border-color $transition-fast;
92
+ flex-shrink: 0;
93
+
94
+ &::after {
95
+ content: '';
96
+ position: absolute;
97
+ top: 50%;
98
+ left: 50%;
99
+ width: 5px;
100
+ height: 9px;
101
+ border: 2px solid $evo-primary-fg;
102
+ border-top: none;
103
+ border-left: none;
104
+ opacity: 0;
105
+ // Centered via translate (parent's flex-centering can't reach an absolute
106
+ // child). -60% Y nudges the rotated "L" optically into the middle. The
107
+ // centering translate is folded into both states so the scale stays put.
108
+ transform: translate(-50%, -60%) rotate(45deg) scale(0.5);
109
+ transition: opacity $transition-fast, transform $transition-fast;
110
+ }
111
+ }
112
+
113
+ .labelText {
114
+ font-size: $text-sm;
115
+ color: $color-text-primary;
116
+ }
117
+
118
+ .helperText {
119
+ font-size: $text-xs;
120
+ color: $color-text-muted;
121
+ padding-left: 1.5rem;
122
+ margin: 0;
123
+ }