@justin_evo/evo-ui 1.1.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 (80) hide show
  1. package/README.md +3 -3
  2. package/dist/TopNav/TopNav.d.ts +19 -0
  3. package/dist/declarations.d.ts +6 -6
  4. package/dist/evo-ui.css +1 -1
  5. package/dist/index.cjs.js +1 -1
  6. package/dist/index.es.js +3301 -3197
  7. package/package.json +52 -52
  8. package/src/Alert/Alert.tsx +49 -49
  9. package/src/AutoComplete/AutoComplete.tsx +810 -810
  10. package/src/Badge/Badge.tsx +53 -53
  11. package/src/Breadcrumb/Breadcrumb.tsx +53 -53
  12. package/src/Button/Button.tsx +125 -125
  13. package/src/Card/Card.tsx +257 -257
  14. package/src/Checkbox/Checkbox.tsx +59 -59
  15. package/src/CommandPalette/CommandPalette.tsx +185 -185
  16. package/src/Container/Container.tsx +31 -31
  17. package/src/Divider/Divider.tsx +31 -31
  18. package/src/Form/Form.tsx +185 -185
  19. package/src/Grid/Grid.tsx +66 -66
  20. package/src/ImageCropper/ImageCropper.tsx +911 -911
  21. package/src/Input/Input.tsx +74 -74
  22. package/src/Modal/Modal.tsx +77 -77
  23. package/src/Nav/Nav.tsx +708 -708
  24. package/src/Notification/Notification.tsx +1503 -1503
  25. package/src/Pagination/Pagination.tsx +76 -76
  26. package/src/Radio/Radio.tsx +69 -69
  27. package/src/RichTextArea/RichTextArea.tsx +886 -869
  28. package/src/Select/Select.tsx +515 -515
  29. package/src/Skeleton/Skeleton.tsx +70 -70
  30. package/src/Stack/Stack.tsx +52 -52
  31. package/src/Table/Table.tsx +335 -335
  32. package/src/Tabs/Tabs.tsx +90 -90
  33. package/src/Theme/ThemeProvider.tsx +253 -253
  34. package/src/Theme/ThemeToggle.tsx +79 -79
  35. package/src/Toggle/Toggle.tsx +48 -48
  36. package/src/Tooltip/Tooltip.tsx +38 -38
  37. package/src/TopNav/TopNav.tsx +1163 -994
  38. package/src/TreeSelect/TreeSelect.tsx +825 -825
  39. package/src/css/alert.module.scss +93 -93
  40. package/src/css/autocomplete.module.scss +416 -416
  41. package/src/css/badge.module.scss +82 -82
  42. package/src/css/base/_color.scss +159 -159
  43. package/src/css/base/_theme.scss +237 -237
  44. package/src/css/base/_variables.scss +161 -161
  45. package/src/css/breadcrumb.module.scss +50 -50
  46. package/src/css/button.module.scss +385 -385
  47. package/src/css/card.module.scss +217 -217
  48. package/src/css/checkbox.module.scss +123 -120
  49. package/src/css/commandpalette.module.scss +211 -211
  50. package/src/css/container.module.scss +18 -18
  51. package/src/css/divider.module.scss +41 -41
  52. package/src/css/form.module.scss +245 -245
  53. package/src/css/imagecropper.module.scss +397 -397
  54. package/src/css/input.module.scss +89 -89
  55. package/src/css/modal.module.scss +105 -105
  56. package/src/css/nav.module.scss +494 -494
  57. package/src/css/notification.module.scss +691 -691
  58. package/src/css/pagination.module.scss +63 -63
  59. package/src/css/radio.module.scss +89 -89
  60. package/src/css/richtextarea.module.scss +307 -307
  61. package/src/css/select.module.scss +525 -525
  62. package/src/css/skeleton.module.scss +30 -30
  63. package/src/css/table.module.scss +386 -386
  64. package/src/css/tabs.module.scss +63 -63
  65. package/src/css/theme-toggle.module.scss +83 -83
  66. package/src/css/toggle.module.scss +54 -54
  67. package/src/css/tooltip.module.scss +97 -97
  68. package/src/css/topnav.module.scss +568 -396
  69. package/src/css/treeselect.module.scss +558 -558
  70. package/src/css/utilities/_borders.scss +111 -111
  71. package/src/css/utilities/_colors.scss +66 -66
  72. package/src/css/utilities/_effects.scss +216 -216
  73. package/src/css/utilities/_layout.scss +181 -181
  74. package/src/css/utilities/_position.scss +75 -75
  75. package/src/css/utilities/_sizing.scss +138 -138
  76. package/src/css/utilities/_spacing.scss +99 -99
  77. package/src/css/utilities/_typography.scss +121 -121
  78. package/src/css/utilities/index.scss +24 -24
  79. package/src/declarations.d.ts +6 -6
  80. 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,120 +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: 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: 0px;
98
- left: 3px;
99
- width: 5px;
100
- height: 8px;
101
- border: 2px solid $evo-primary-fg;
102
- border-top: none;
103
- border-left: none;
104
- opacity: 0;
105
- transform: rotate(45deg) scale(0.5);
106
- transition: opacity $transition-fast, transform $transition-fast;
107
- }
108
- }
109
-
110
- .labelText {
111
- font-size: $text-sm;
112
- color: $color-text-primary;
113
- }
114
-
115
- .helperText {
116
- font-size: $text-xs;
117
- color: $color-text-muted;
118
- padding-left: 1.5rem;
119
- margin: 0;
120
- }
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
+ }