elbe-ui 0.2.5 → 0.2.14

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 (50) hide show
  1. package/dist/index.js +17 -2
  2. package/dist/ui/color_theme.d.ts +5 -0
  3. package/dist/ui/components/badge.d.ts +25 -0
  4. package/dist/ui/components/box.d.ts +1027 -0
  5. package/dist/ui/components/button.d.ts +23 -0
  6. package/dist/ui/components/card.d.ts +14 -0
  7. package/dist/ui/components/dialog.d.ts +8 -0
  8. package/dist/ui/components/flex.d.ts +11 -0
  9. package/dist/ui/components/icon_button.d.ts +19 -0
  10. package/dist/ui/components/input/checkbox.d.ts +6 -0
  11. package/dist/ui/components/input/input_field.d.ts +22 -0
  12. package/dist/ui/components/input/range.d.ts +8 -0
  13. package/dist/ui/components/input/select.d.ts +10 -0
  14. package/dist/ui/components/input/text_area.d.ts +10 -0
  15. package/dist/ui/components/padded.d.ts +25 -0
  16. package/dist/ui/components/text.d.ts +33 -0
  17. package/dist/ui/components/toggle_button.d.ts +12 -0
  18. package/dist/ui/components/util.d.ts +3 -0
  19. package/dist/ui/util/confirm_dialog.d.ts +10 -0
  20. package/dist/ui/util/error_view.d.ts +1 -0
  21. package/dist/ui/util/toast.d.ts +5 -0
  22. package/dist/ui/util/util.d.ts +19 -0
  23. package/elbe.scss +2 -2
  24. package/package.json +5 -2
  25. package/src/index.tsx +24 -0
  26. package/src/ui/color_theme.ts +24 -0
  27. package/src/ui/components/badge.tsx +78 -0
  28. package/src/ui/components/box.tsx +49 -0
  29. package/src/ui/components/button.tsx +61 -0
  30. package/src/ui/components/card.tsx +45 -0
  31. package/src/ui/components/dialog.tsx +51 -0
  32. package/src/ui/components/flex.tsx +64 -0
  33. package/src/ui/components/icon_button.tsx +56 -0
  34. package/src/ui/components/input/checkbox.tsx +32 -0
  35. package/src/ui/components/input/input_field.tsx +57 -0
  36. package/src/ui/components/input/range.tsx +37 -0
  37. package/src/ui/components/input/select.tsx +29 -0
  38. package/src/ui/components/input/text_area.tsx +45 -0
  39. package/src/ui/components/padded.tsx +62 -0
  40. package/src/ui/components/text.tsx +78 -0
  41. package/src/ui/components/toggle_button.tsx +52 -0
  42. package/src/ui/components/util.tsx +3 -0
  43. package/src/ui/util/confirm_dialog.ts +53 -0
  44. package/src/ui/util/error_view.tsx +16 -0
  45. package/src/ui/util/toast.ts +14 -0
  46. package/src/ui/util/util.ts +36 -0
  47. package/style/color_style.scss +148 -0
  48. package/style/components.scss +450 -0
  49. package/style/root.scss +50 -0
  50. package/style/type_style.scss +22 -0
@@ -0,0 +1,148 @@
1
+ @function contrast($colorA, $colorB) {
2
+ $yiqA: calc(
3
+ ((red($colorA) * 299) + (green($colorA) * 587) + (blue($colorA) * 114)) /
4
+ 1000
5
+ );
6
+ $yiqB: calc(
7
+ ((red($colorB) * 299) + (green($colorB) * 587) + (blue($colorB) * 114)) /
8
+ 1000
9
+ );
10
+ @return abs($yiqA - $yiqB);
11
+ }
12
+
13
+ @function mg($map, $value) {
14
+ @return map-get($map, $value);
15
+ }
16
+
17
+ @function ifn($a, $b) {
18
+ @return if($a ==null, $b, $a);
19
+ }
20
+
21
+ @function inter($colorA, $colorB: #888888, $weight: 50%) {
22
+ @return mix($colorA, $colorB, $weight);
23
+ }
24
+
25
+ @mixin colored($back, $front, $border) {
26
+ color: $front;
27
+ background-color: $back;
28
+ border-color: $border;
29
+ }
30
+
31
+ @mixin blinking($length: 1s) {
32
+ animation: blinker $length linear infinite;
33
+ }
34
+
35
+ @keyframes blinker {
36
+ 50% {
37
+ opacity: 0;
38
+ }
39
+ }
40
+
41
+ // SHOW WHEN THE STYLES ARE NOT BEING USED WITHIN A MODE
42
+ @each $style, $s_colors in $c-styles {
43
+ .#{$style} {
44
+ @include blinking();
45
+ @include colored(rgb(255, 55, 0), white, transparent);
46
+ }
47
+ }
48
+
49
+ //COLORS
50
+
51
+ @each $mode, $m_colors in $c-modes {
52
+ .#{$mode} {
53
+ $mode_back: mg($m_colors, back);
54
+ $mode_front: mg($m_colors, front);
55
+ $mode_border: mg($m_colors, border);
56
+ @include colored($mode_back, $mode_front, $mode_border);
57
+
58
+ .plain {
59
+ @include colored(transparent, $mode_front, $mode_border);
60
+ }
61
+
62
+ .plain-opaque {
63
+ @include colored($mode_back, $mode_front, $mode_border);
64
+ }
65
+
66
+ & {
67
+ --c-mode: #{$mode};
68
+ }
69
+
70
+ @each $style, $s_colors in $c-styles {
71
+ $back: mg($s_colors, back);
72
+ $border: ifn(mg($s_colors, border), $back);
73
+
74
+ $effectiveBack: ifn(
75
+ if(mg($s_colors, back) == transparent, $mode_back, mg($s_colors, back)),
76
+ $mode_back
77
+ );
78
+ $front: ifn(
79
+ mg($s_colors, front),
80
+ if(contrast($mode_front, $effectiveBack) > 128, $mode_front, $mode_back)
81
+ );
82
+
83
+ & {
84
+ --c-#{$style}: #{$back};
85
+ }
86
+
87
+ .#{$style} {
88
+ animation: none;
89
+
90
+ @include colored($back, $front, $border);
91
+
92
+ &.minor {
93
+ $mback: inter(mg($s_colors, back), mg($m_colors, back), 25%);
94
+ $mfront: mg($s_colors, back);
95
+ $mborder: ifn(mg($s_colors, border), $mfront);
96
+
97
+ @include colored($mback, $mfront, $mborder);
98
+
99
+ &.hovered {
100
+ $hback: inter($mback, $mfront, 90%);
101
+ @include colored($hback, $mfront, $mborder);
102
+ }
103
+
104
+ &.pressed {
105
+ $pback: inter($mback, $mfront, 75%);
106
+ @include colored($pback, $mfront, $mborder);
107
+ }
108
+
109
+ &.disabled {
110
+ $disback: grayscale($mback);
111
+ $disfront: grayscale($mfront);
112
+ $disborder: if($mborder ==null, null, grayscale($mborder));
113
+
114
+ @include colored($disback, $disfront, $disborder);
115
+ }
116
+ }
117
+
118
+ &.hovered {
119
+ $hback: inter($back, $front, 95%);
120
+ $hborder: if(
121
+ $border ==transparent,
122
+ transparent,
123
+ inter($border, $front, 95%)
124
+ );
125
+ @include colored($hback, $front, $hborder);
126
+ }
127
+
128
+ &.pressed {
129
+ $pback: inter($back, $front, 85%);
130
+ $pborder: if(
131
+ $border ==transparent,
132
+ transparent,
133
+ inter($border, $front, 85%)
134
+ );
135
+ @include colored($pback, $front, $pborder);
136
+ }
137
+
138
+ &.disabled {
139
+ @include colored(
140
+ grayscale($back),
141
+ grayscale($front),
142
+ grayscale($back)
143
+ );
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
@@ -0,0 +1,450 @@
1
+ // =============== MARKUP ===============
2
+
3
+ i, .i {font-style: italic;}
4
+ b, .b {font-weight: bold;}
5
+ .u {text-decoration: underline;}
6
+ .ni {font-style: normal;}
7
+ .nb {font-weight: normal;}
8
+ .nu {text-decoration: none;}
9
+ .striked {text-decoration: line-through;}
10
+ .code {font-family: monospace;}
11
+
12
+ // =============== SPACING ===============
13
+
14
+ .padded {padding: 1rem;}
15
+ .padding-none {padding: 0rem;}
16
+
17
+ .margined {margin: 1rem;}
18
+ .margined-none {margin: 0rem;}
19
+
20
+ // =============== FLEX-Layouts ===============
21
+
22
+ .flex {
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ @for $i from 1 through 12 {
28
+ .flex-#{$i} {
29
+ @extend .flex;
30
+ flex: $i;
31
+ }
32
+ }
33
+
34
+ .centered {
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ }
39
+
40
+ .column {
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ gap: 1rem;
45
+ }
46
+
47
+ .row {
48
+ display: flex;
49
+ flex-direction: row;
50
+ align-items: center;
51
+ gap: 1rem;
52
+
53
+ &.wrap {flex-wrap: wrap;}
54
+ }
55
+
56
+ .row-resp,
57
+ .row-resp-rev {
58
+ display: flex;
59
+ flex-direction: row;
60
+ justify-content: center;
61
+ align-items: start;
62
+ gap: 1rem;
63
+
64
+ @media (max-width: 700px) {
65
+ & {
66
+ flex-direction: column;
67
+ justify-content: start;
68
+ align-items: stretch;
69
+ }
70
+
71
+ &.row-resp-rev {flex-direction: column-reverse;}
72
+ }
73
+ }
74
+
75
+ .gap-none {gap: 0;}
76
+ .gap-quarter {gap: 0.25rem;}
77
+ .gap-half {gap: 0.5rem;}
78
+ .gap {gap: 1rem;}
79
+
80
+ @for $i from 0 through 6 {
81
+ .gap-#{$i} {gap: #{$i}rem;}
82
+ }
83
+
84
+ $cross_modes: (stretch,start,end,center);
85
+ @each $name in $cross_modes {
86
+ .cross-#{$name} {align-items: $name;}
87
+ }
88
+
89
+ $main_modes: (stretch,start,end,center,space-between);
90
+ @each $name in $main_modes {
91
+ .main-#{$name} {justify-content: $name;}
92
+ }
93
+
94
+ // =============== conditionals ===============
95
+
96
+ .if-wide {
97
+ @media (max-width: 700px) {
98
+ & {display: none;}
99
+ }
100
+ }
101
+
102
+ .if-narrow {
103
+ @media (min-width: 700px) {
104
+ & {display: none;}
105
+ }
106
+ }
107
+
108
+ // =============== element style ===============
109
+
110
+ .sharp {border-radius: 0;}
111
+ .rounded {border-radius: $g-radius;}
112
+ .round {border-radius: 50%;}
113
+
114
+ img.round,
115
+ img.rounded {object-fit: cover;}
116
+
117
+ .borderless {border: none;}
118
+ .raised {box-shadow: 0 0.1rem 1rem #00000033;}
119
+
120
+ .scrollbars-none {
121
+ scrollbar-width: none;
122
+ -ms-overflow-style: none;
123
+ &::-webkit-scrollbar {display: none;}
124
+ }
125
+
126
+ .pointer {cursor: pointer;}
127
+
128
+ .text-centered {text-align: center;}
129
+ .text-start {text-align: start;}
130
+ .text-end {text-align: end;}
131
+
132
+ body:has(dialog[open=""]) {overflow: hidden;}
133
+
134
+
135
+ // =============== animations ===============
136
+
137
+ .rotate-box {
138
+ @extend .rotate;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ }
143
+
144
+ .rotate {
145
+ animation: rotation 1.5s infinite linear;
146
+ }
147
+
148
+ @keyframes rotation {
149
+ from {transform: rotate(0deg);}
150
+ to {transform: rotate(359deg);}
151
+ }
152
+
153
+ // =============== COMPONENTS ===============
154
+
155
+ .box {
156
+ @extend .padded;
157
+ @extend .text-m;
158
+ @extend .primary;
159
+
160
+ &.primary {@extend .primary;}
161
+ &.secondary {@extend .secondary;}
162
+ &.inverse {@extend .inverse;}
163
+ }
164
+
165
+ .card {
166
+ @extend .box;
167
+ border-width: 2px;
168
+ border-style: solid;
169
+ border-radius: $g-radius;
170
+ //overflow: hidden;
171
+ }
172
+
173
+
174
+ button {
175
+ @extend .card;
176
+ @extend .accent;
177
+ @extend .row;
178
+ @extend .text-m;
179
+ @extend .b;
180
+ justify-content: center;
181
+ padding: 0.25rem 0.75rem;
182
+ gap: 0.5rem;
183
+ min-height: 3rem;
184
+ cursor: pointer;
185
+
186
+ &:hover:not(&:disabled, .disabled) {
187
+ @extend .hovered;
188
+ }
189
+
190
+ &:active:not(&:disabled, .disabled) {
191
+ @extend .pressed;
192
+ }
193
+
194
+ &:disabled,
195
+ &.disabled {
196
+ @extend .disabled;
197
+ cursor: not-allowed;
198
+
199
+ &.action {
200
+ opacity: 0.7;
201
+ filter: grayscale(1);
202
+ }
203
+ }
204
+
205
+ & > .lucide {
206
+ & + div {
207
+ text-align: center;
208
+ flex: 1;
209
+ text-align: center;
210
+ }
211
+ }
212
+
213
+ &.text-left {
214
+ text-align: left;
215
+ div {
216
+ margin-left: 0.25rem;
217
+ text-align: left;
218
+ }
219
+ }
220
+ }
221
+
222
+ .icon {
223
+ aspect-ratio: 1;
224
+ border-radius: 25%;
225
+ object-fit: cover;
226
+ }
227
+
228
+ .toast {
229
+ @extend .card;
230
+ @extend .inverse;
231
+ @extend .b;
232
+ @extend .raised;
233
+ position: fixed;
234
+ bottom: 1rem;
235
+ right: 1rem;
236
+ z-index: 200;
237
+ left: 50%;
238
+ width: min(40rem, 90%);
239
+ transform: translateX(-50%);
240
+ }
241
+
242
+ select {
243
+ @extend .card;
244
+ padding: 0 0.75rem;
245
+ height: 3rem;
246
+ min-width: 12rem;
247
+ width: 100%;
248
+ }
249
+
250
+ textarea {
251
+ @extend .card;
252
+ height: 6rem;
253
+ padding: 0.6rem 0.75rem;
254
+ resize: vertical;
255
+ min-height: 3rem;
256
+ min-width: 12rem;
257
+ width: 100%;
258
+ }
259
+
260
+
261
+ dialog {
262
+ @extend .column;
263
+ @extend .cross-center;
264
+ @extend .main-center;
265
+
266
+ z-index: 100;
267
+
268
+ position: fixed;
269
+ top: 0;
270
+ left: 0;
271
+ width: 100vw;
272
+ height: 100vh;
273
+
274
+ border: none;
275
+
276
+ pointer-events: none;
277
+
278
+ background-color: transparent;
279
+
280
+ transition: background-color 0.3s ease-in-out;
281
+ transition: backdrop-filter 0.3s ease-in-out;
282
+
283
+ & > * {
284
+ display: none;
285
+ }
286
+
287
+ &[open=""] {
288
+ background-color: rgba(0, 0, 0, 0.2);
289
+ backdrop-filter: blur(5px);
290
+ pointer-events: all;
291
+ & > * {
292
+ display: unset;
293
+ }
294
+ }
295
+ }
296
+
297
+ .expandable {
298
+ max-height: 0px;
299
+ transition: max-height 0.25s ease-out;
300
+ overflow: hidden;
301
+ }
302
+
303
+ .expandable:has(*) {
304
+ max-height: 500px;
305
+ transition: max-height 0.25s ease-in;
306
+ }
307
+
308
+ // =============== INPUTS ===============
309
+
310
+ input[type="text"],
311
+ input[type="number"],
312
+ input[type="password"],
313
+ input[type="email"],
314
+ input[type="date"],
315
+ input[type="time"] {
316
+ @extend .card;
317
+ padding: 0 0.75rem;
318
+ height: 3rem;
319
+ min-width: 12rem;
320
+ width: 100%;
321
+ }
322
+
323
+ input[type="range"] {
324
+ -webkit-appearance: none;
325
+ appearance: none;
326
+ background: transparent;
327
+ cursor: pointer;
328
+ width: 15rem;
329
+
330
+ &::-moz-range-track{
331
+ background-color: #707070;
332
+ border-radius: 100px;
333
+ border: none;
334
+ height: 0.5rem;
335
+ }
336
+
337
+ &::-webkit-slider-runnable-track
338
+ {
339
+ @extend .secondary;
340
+ border-radius: 100px;
341
+ border: none;
342
+ height: 0.5rem;
343
+ }
344
+
345
+ &::-webkit-slider-thumb
346
+ {
347
+ @extend .accent;
348
+ border: none;
349
+ -webkit-appearance: none; // Override default look
350
+ appearance: none;
351
+ margin-top: -6px;
352
+ border-radius: 100px;
353
+ height: 1.2rem;
354
+ width: 1.2rem;
355
+ }
356
+ }
357
+
358
+
359
+ input[type="checkbox"] {
360
+ -webkit-appearance: none;
361
+ appearance: none;
362
+ margin: 0;
363
+
364
+ font: inherit;
365
+ color: black;
366
+ //margin: 0.6rem 0.6rem;
367
+ width: 1.8rem;
368
+ height: 1.8rem;
369
+ border: 0.16em solid black;
370
+ border-radius: 25%;
371
+ transform: translateY(-0.075em);
372
+
373
+ display: grid;
374
+ place-content: center;
375
+ outline: none;
376
+ }
377
+
378
+ input[type="checkbox"]::before {
379
+ content: "";
380
+ width: 0.95rem;
381
+ height: 0.75rem;
382
+ clip-path: polygon(10% 41%, 37% 75%, 91% 0, 100% 13%, 38% 100%, 0 55%);
383
+ // check tick clip path outlined:
384
+ transform: scale(0);
385
+ transform-origin: center;
386
+ transition: 0.2s transform ease-in-out;
387
+ background-color: black;
388
+ //box-shadow: inset 1em 1em green;
389
+ }
390
+
391
+ input[type="checkbox"]:checked {
392
+ @extend .loud;
393
+ @extend .minor;
394
+ border-color: $c-accent !important;
395
+ &::before {
396
+ transform: scale(1);
397
+ background-color: $c-accent;
398
+ }
399
+ }
400
+
401
+ input[type="checkbox"]:focus {
402
+ outline: max(2px, 0.15em) solid blue;
403
+ outline-offset: 0;
404
+ }
405
+
406
+ input[type="checkbox"]:disabled {
407
+ //--form-control-color: var(--form-control-disabled);
408
+
409
+ color: gray;
410
+ cursor: not-allowed;
411
+ }
412
+
413
+ // =============== TOOLTIP ===============
414
+
415
+
416
+ [data-tooltip]:hover:after {
417
+ opacity: 1;
418
+ transition: all 0.1s ease 0.8s;
419
+ visibility: visible;
420
+ }
421
+
422
+ [data-tooltip]:after {
423
+ @extend .inverse;
424
+ content: attr(data-tooltip);
425
+ position: absolute;
426
+ bottom: -1.6em;
427
+ left: 50%;
428
+ transform: translateX(-50%);
429
+ white-space: nowrap;
430
+ box-shadow: 0 0.125rem 0.5rem 0.2rem #00000022;
431
+ padding: 0.25em 0.5em;
432
+ border-radius: 0.25em;
433
+ opacity: 0;
434
+ z-index: 999;
435
+ visibility: hidden;
436
+ pointer-events: none;
437
+ }
438
+ [data-tooltip] {
439
+ position: relative;
440
+ }
441
+
442
+ // =============== LAYOUT ===============
443
+
444
+
445
+ .base-limited {
446
+ @extend .box;
447
+ max-width: 700px;
448
+ width: 100%;
449
+ margin: 0 auto;
450
+ }
@@ -0,0 +1,50 @@
1
+ :root {
2
+ /*font-family: "apple color emoji", "segoe ui emoji", "noto color emoji",
3
+ "android emoji", "emojisymbols", "emojione mozilla", "twemoji mozilla",
4
+ "segoe ui symbol", $t-font-body;*/
5
+ font-family: $t-font-body, "Noto Color Emoji";
6
+ line-height: 1.3;
7
+
8
+ color: #222;
9
+ background-color: #ffffff;
10
+
11
+ font-synthesis: none;
12
+ text-rendering: optimizeLegibility;
13
+ -webkit-font-smoothing: antialiased;
14
+ -moz-osx-font-smoothing: grayscale;
15
+ -webkit-text-size-adjust: 100%;
16
+ box-sizing: border-box;
17
+ font-size: 16px;
18
+ border-collapse: separate;
19
+ }
20
+
21
+ @media (orientation: portrait) {
22
+ :root {
23
+ font-size: 13px;
24
+ }
25
+ }
26
+
27
+ *,
28
+ *:before,
29
+ *:after {
30
+ box-sizing: inherit;
31
+ font-family: inherit;
32
+ font-weight: inherit;
33
+ }
34
+
35
+ body,
36
+ #app,
37
+ .elbe-base {
38
+ margin: 0;
39
+ display: block;
40
+ min-height: 100vh;
41
+ background-color: white;
42
+ }
43
+
44
+ body:has(.no-page-scroll) {
45
+ overflow: hidden;
46
+ }
47
+
48
+ .debug {
49
+ display: none;
50
+ }
@@ -0,0 +1,22 @@
1
+ @each $style, $size in $t-styles {
2
+ .text-#{$style} {
3
+ font-size: $size;
4
+ }
5
+ }
6
+
7
+ @each $name, $size in $t-headers {
8
+ .header-#{$name} {
9
+ @extend .b;
10
+ line-height: 1;
11
+ font-size: $size;
12
+ font-family: $t-font-accent;
13
+ }
14
+
15
+ h#{$name} {
16
+ @extend .header-#{$name};
17
+ }
18
+ }
19
+
20
+ .text-accent {
21
+ font-family: $t-font-accent;
22
+ }