basefn 1.2.0 → 1.4.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/package.json +3 -3
- package/src/Basefn.res +50 -0
- package/src/Basefn.res.mjs +40 -0
- package/src/Basefn__Utils.res.mjs +1 -1
- package/src/components/Basefn__AlertDialog.css +119 -0
- package/src/components/Basefn__AlertDialog.res +80 -0
- package/src/components/Basefn__AlertDialog.res.mjs +106 -0
- package/src/components/Basefn__AppLayout.css +10 -0
- package/src/components/Basefn__AspectRatio.css +16 -0
- package/src/components/Basefn__AspectRatio.res +26 -0
- package/src/components/Basefn__AspectRatio.res.mjs +33 -0
- package/src/components/Basefn__ButtonGroup.css +58 -0
- package/src/components/Basefn__ButtonGroup.res +33 -0
- package/src/components/Basefn__ButtonGroup.res.mjs +38 -0
- package/src/components/Basefn__Card.css +15 -0
- package/src/components/Basefn__ContextMenu.css +78 -0
- package/src/components/Basefn__ContextMenu.res +98 -0
- package/src/components/Basefn__ContextMenu.res.mjs +93 -0
- package/src/components/Basefn__Drawer.css +31 -0
- package/src/components/Basefn__Dropdown.res +3 -1
- package/src/components/Basefn__Dropdown.res.mjs +22 -43
- package/src/components/Basefn__HoverCard.css +93 -0
- package/src/components/Basefn__HoverCard.res +99 -0
- package/src/components/Basefn__HoverCard.res.mjs +109 -0
- package/src/components/Basefn__Modal.css +38 -0
- package/src/components/Basefn__Popover.css +98 -0
- package/src/components/Basefn__Popover.res +95 -0
- package/src/components/Basefn__Popover.res.mjs +107 -0
- package/src/components/Basefn__ScrollArea.css +76 -0
- package/src/components/Basefn__ScrollArea.res +60 -0
- package/src/components/Basefn__ScrollArea.res.mjs +63 -0
- package/src/components/Basefn__Skeleton.css +83 -0
- package/src/components/Basefn__Skeleton.res +55 -0
- package/src/components/Basefn__Skeleton.res.mjs +62 -0
- package/src/components/Basefn__Stepper.css +36 -0
- package/src/components/Basefn__Tabs.css +18 -0
- package/src/components/Basefn__Toggle.css +87 -0
- package/src/components/Basefn__Toggle.res +65 -0
- package/src/components/Basefn__Toggle.res.mjs +71 -0
- package/src/components/Basefn__ToggleGroup.css +110 -0
- package/src/components/Basefn__ToggleGroup.res +106 -0
- package/src/components/Basefn__ToggleGroup.res.mjs +89 -0
- package/src/components/Basefn__Topbar.css +44 -3
- package/src/components/Basefn__Topbar.res +1 -13
- package/src/components/Basefn__Topbar.res.mjs +1 -11
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Xote from "xote/src/Xote.res.mjs";
|
|
4
|
+
import * as Xote__JSX from "xote/src/Xote__JSX.res.mjs";
|
|
5
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
6
|
+
|
|
7
|
+
import './Basefn__HoverCard.css'
|
|
8
|
+
;
|
|
9
|
+
|
|
10
|
+
function positionToString(position) {
|
|
11
|
+
switch (position) {
|
|
12
|
+
case "Top" :
|
|
13
|
+
return "top";
|
|
14
|
+
case "Bottom" :
|
|
15
|
+
return "bottom";
|
|
16
|
+
case "Left" :
|
|
17
|
+
return "left";
|
|
18
|
+
case "Right" :
|
|
19
|
+
return "right";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function alignToString(align) {
|
|
24
|
+
switch (align) {
|
|
25
|
+
case "Start" :
|
|
26
|
+
return "start";
|
|
27
|
+
case "Center" :
|
|
28
|
+
return "center";
|
|
29
|
+
case "End" :
|
|
30
|
+
return "end";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function Basefn__HoverCard(props) {
|
|
35
|
+
let className = props.className;
|
|
36
|
+
let __closeDelay = props.closeDelay;
|
|
37
|
+
let __openDelay = props.openDelay;
|
|
38
|
+
let __align = props.align;
|
|
39
|
+
let __position = props.position;
|
|
40
|
+
let content = props.content;
|
|
41
|
+
let position = __position !== undefined ? __position : "Bottom";
|
|
42
|
+
let align = __align !== undefined ? __align : "Center";
|
|
43
|
+
let openDelay = __openDelay !== undefined ? __openDelay : 200;
|
|
44
|
+
let closeDelay = __closeDelay !== undefined ? __closeDelay : 100;
|
|
45
|
+
let isOpen = Xote.Signal.make(false, undefined, undefined);
|
|
46
|
+
let timeoutId = {
|
|
47
|
+
contents: undefined
|
|
48
|
+
};
|
|
49
|
+
let clearExistingTimeout = () => {
|
|
50
|
+
let id = timeoutId.contents;
|
|
51
|
+
if (id !== undefined) {
|
|
52
|
+
clearTimeout(Primitive_option.valFromOption(id));
|
|
53
|
+
timeoutId.contents = undefined;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
let handleMouseEnter = param => {
|
|
58
|
+
clearExistingTimeout();
|
|
59
|
+
let id = setTimeout(() => Xote.Signal.set(isOpen, true), openDelay);
|
|
60
|
+
timeoutId.contents = Primitive_option.some(id);
|
|
61
|
+
};
|
|
62
|
+
let handleMouseLeave = param => {
|
|
63
|
+
clearExistingTimeout();
|
|
64
|
+
let id = setTimeout(() => Xote.Signal.set(isOpen, false), closeDelay);
|
|
65
|
+
timeoutId.contents = Primitive_option.some(id);
|
|
66
|
+
};
|
|
67
|
+
let getHoverCardClassName = () => {
|
|
68
|
+
let customClass = className !== undefined ? " " + className : "";
|
|
69
|
+
return "basefn-hover-card" + customClass;
|
|
70
|
+
};
|
|
71
|
+
let getContentClassName = () => {
|
|
72
|
+
let positionClass = " basefn-hover-card__content--" + positionToString(position);
|
|
73
|
+
let alignClass = " basefn-hover-card__content--align-" + alignToString(align);
|
|
74
|
+
return "basefn-hover-card__content" + positionClass + alignClass;
|
|
75
|
+
};
|
|
76
|
+
let hoverCardContent = Xote.Computed.make(() => {
|
|
77
|
+
if (Xote.Signal.get(isOpen)) {
|
|
78
|
+
return [Xote__JSX.Elements.jsx("div", {
|
|
79
|
+
class: getContentClassName(),
|
|
80
|
+
onMouseEnter: handleMouseEnter,
|
|
81
|
+
onMouseLeave: handleMouseLeave,
|
|
82
|
+
children: content
|
|
83
|
+
})];
|
|
84
|
+
} else {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
}, undefined);
|
|
88
|
+
return Xote__JSX.Elements.jsxs("div", {
|
|
89
|
+
class: getHoverCardClassName(),
|
|
90
|
+
onMouseEnter: handleMouseEnter,
|
|
91
|
+
onMouseLeave: handleMouseLeave,
|
|
92
|
+
children: Xote__JSX.array([
|
|
93
|
+
Xote__JSX.Elements.jsx("div", {
|
|
94
|
+
class: "basefn-hover-card__trigger",
|
|
95
|
+
children: props.trigger
|
|
96
|
+
}),
|
|
97
|
+
Xote.Component.signalFragment(hoverCardContent)
|
|
98
|
+
])
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let make = Basefn__HoverCard;
|
|
103
|
+
|
|
104
|
+
export {
|
|
105
|
+
positionToString,
|
|
106
|
+
alignToString,
|
|
107
|
+
make,
|
|
108
|
+
}
|
|
109
|
+
/* Not a pure module */
|
|
@@ -98,3 +98,41 @@
|
|
|
98
98
|
transform: scale(1) translateY(0);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
/* Mobile responsiveness */
|
|
103
|
+
@media (max-width: 768px) {
|
|
104
|
+
.basefn-modal-backdrop {
|
|
105
|
+
align-items: flex-end;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.basefn-modal {
|
|
109
|
+
max-width: 100vw;
|
|
110
|
+
max-height: 85vh;
|
|
111
|
+
width: 100% !important;
|
|
112
|
+
border-radius: 0.75rem 0.75rem 0 0;
|
|
113
|
+
animation: basefn-modal-slide-up 0.3s ease-out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.basefn-modal__header {
|
|
117
|
+
padding: 1rem;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.basefn-modal__body {
|
|
121
|
+
padding: 1rem;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.basefn-modal__footer {
|
|
125
|
+
padding: 1rem;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@keyframes basefn-modal-slide-up {
|
|
129
|
+
from {
|
|
130
|
+
opacity: 0;
|
|
131
|
+
transform: translateY(100%);
|
|
132
|
+
}
|
|
133
|
+
to {
|
|
134
|
+
opacity: 1;
|
|
135
|
+
transform: translateY(0);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
@import '../styles/variables.css';
|
|
2
|
+
|
|
3
|
+
.basefn-popover {
|
|
4
|
+
position: relative;
|
|
5
|
+
display: inline-block;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.basefn-popover__trigger {
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.basefn-popover__backdrop {
|
|
13
|
+
position: fixed;
|
|
14
|
+
inset: 0;
|
|
15
|
+
z-index: 49;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.basefn-popover__content {
|
|
19
|
+
position: absolute;
|
|
20
|
+
z-index: 50;
|
|
21
|
+
background: var(--basefn-surface-elevated);
|
|
22
|
+
border: var(--basefn-border-width) solid var(--basefn-border-primary);
|
|
23
|
+
border-radius: var(--basefn-radius-lg);
|
|
24
|
+
box-shadow: var(--basefn-shadow-lg);
|
|
25
|
+
padding: var(--basefn-spacing-lg);
|
|
26
|
+
min-width: 200px;
|
|
27
|
+
animation: basefn-popover-fade-in var(--basefn-transition-fast);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@keyframes basefn-popover-fade-in {
|
|
31
|
+
from {
|
|
32
|
+
opacity: 0;
|
|
33
|
+
transform: scale(0.95);
|
|
34
|
+
}
|
|
35
|
+
to {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
transform: scale(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Position: Bottom */
|
|
42
|
+
.basefn-popover__content--bottom {
|
|
43
|
+
top: 100%;
|
|
44
|
+
margin-top: var(--basefn-spacing-sm);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Position: Top */
|
|
48
|
+
.basefn-popover__content--top {
|
|
49
|
+
bottom: 100%;
|
|
50
|
+
margin-bottom: var(--basefn-spacing-sm);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Position: Left */
|
|
54
|
+
.basefn-popover__content--left {
|
|
55
|
+
right: 100%;
|
|
56
|
+
top: 50%;
|
|
57
|
+
transform: translateY(-50%);
|
|
58
|
+
margin-right: var(--basefn-spacing-sm);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Position: Right */
|
|
62
|
+
.basefn-popover__content--right {
|
|
63
|
+
left: 100%;
|
|
64
|
+
top: 50%;
|
|
65
|
+
transform: translateY(-50%);
|
|
66
|
+
margin-left: var(--basefn-spacing-sm);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Alignment for top/bottom positions */
|
|
70
|
+
.basefn-popover__content--bottom.basefn-popover__content--align-start,
|
|
71
|
+
.basefn-popover__content--top.basefn-popover__content--align-start {
|
|
72
|
+
left: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.basefn-popover__content--bottom.basefn-popover__content--align-center,
|
|
76
|
+
.basefn-popover__content--top.basefn-popover__content--align-center {
|
|
77
|
+
left: 50%;
|
|
78
|
+
transform: translateX(-50%);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.basefn-popover__content--bottom.basefn-popover__content--align-end,
|
|
82
|
+
.basefn-popover__content--top.basefn-popover__content--align-end {
|
|
83
|
+
right: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Alignment for left/right positions */
|
|
87
|
+
.basefn-popover__content--left.basefn-popover__content--align-start,
|
|
88
|
+
.basefn-popover__content--right.basefn-popover__content--align-start {
|
|
89
|
+
top: 0;
|
|
90
|
+
transform: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.basefn-popover__content--left.basefn-popover__content--align-end,
|
|
94
|
+
.basefn-popover__content--right.basefn-popover__content--align-end {
|
|
95
|
+
top: auto;
|
|
96
|
+
bottom: 0;
|
|
97
|
+
transform: none;
|
|
98
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
%%raw(`import './Basefn__Popover.css'`)
|
|
2
|
+
|
|
3
|
+
open Xote
|
|
4
|
+
|
|
5
|
+
type position = Top | Bottom | Left | Right
|
|
6
|
+
|
|
7
|
+
type align = Start | Center | End
|
|
8
|
+
|
|
9
|
+
let positionToString = (position: position) => {
|
|
10
|
+
switch position {
|
|
11
|
+
| Top => "top"
|
|
12
|
+
| Bottom => "bottom"
|
|
13
|
+
| Left => "left"
|
|
14
|
+
| Right => "right"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let alignToString = (align: align) => {
|
|
19
|
+
switch align {
|
|
20
|
+
| Start => "start"
|
|
21
|
+
| Center => "center"
|
|
22
|
+
| End => "end"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@jsx.component
|
|
27
|
+
let make = (
|
|
28
|
+
~trigger: Component.node,
|
|
29
|
+
~content: Component.node,
|
|
30
|
+
~isOpen: Signal.t<bool>,
|
|
31
|
+
~onOpenChange: option<bool => unit>=?,
|
|
32
|
+
~position: position=Bottom,
|
|
33
|
+
~align: align=Center,
|
|
34
|
+
~closeOnClickOutside: bool=true,
|
|
35
|
+
~className: option<string>=?,
|
|
36
|
+
) => {
|
|
37
|
+
let handleTriggerClick = _ => {
|
|
38
|
+
let newValue = !Signal.get(isOpen)
|
|
39
|
+
Signal.set(isOpen, newValue)
|
|
40
|
+
switch onOpenChange {
|
|
41
|
+
| Some(callback) => callback(newValue)
|
|
42
|
+
| None => ()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let handleClose = () => {
|
|
47
|
+
Signal.set(isOpen, false)
|
|
48
|
+
switch onOpenChange {
|
|
49
|
+
| Some(callback) => callback(false)
|
|
50
|
+
| None => ()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let handleBackdropClick = _ => {
|
|
55
|
+
if closeOnClickOutside {
|
|
56
|
+
handleClose()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let getPopoverClassName = () => {
|
|
61
|
+
let baseClass = "basefn-popover"
|
|
62
|
+
let customClass = switch className {
|
|
63
|
+
| Some(c) => " " ++ c
|
|
64
|
+
| None => ""
|
|
65
|
+
}
|
|
66
|
+
baseClass ++ customClass
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let getContentClassName = () => {
|
|
70
|
+
let baseClass = "basefn-popover__content"
|
|
71
|
+
let positionClass = " basefn-popover__content--" ++ positionToString(position)
|
|
72
|
+
let alignClass = " basefn-popover__content--align-" ++ alignToString(align)
|
|
73
|
+
baseClass ++ positionClass ++ alignClass
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let popoverContent = Computed.make(() => {
|
|
77
|
+
if Signal.get(isOpen) {
|
|
78
|
+
[
|
|
79
|
+
<div class="basefn-popover__backdrop" onClick={handleBackdropClick} />,
|
|
80
|
+
<div class={getContentClassName()}>
|
|
81
|
+
{content}
|
|
82
|
+
</div>,
|
|
83
|
+
]
|
|
84
|
+
} else {
|
|
85
|
+
[]
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
<div class={getPopoverClassName()}>
|
|
90
|
+
<div class="basefn-popover__trigger" onClick={handleTriggerClick}>
|
|
91
|
+
{trigger}
|
|
92
|
+
</div>
|
|
93
|
+
{Component.signalFragment(popoverContent)}
|
|
94
|
+
</div>
|
|
95
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Xote from "xote/src/Xote.res.mjs";
|
|
4
|
+
import * as Xote__JSX from "xote/src/Xote__JSX.res.mjs";
|
|
5
|
+
|
|
6
|
+
import './Basefn__Popover.css'
|
|
7
|
+
;
|
|
8
|
+
|
|
9
|
+
function positionToString(position) {
|
|
10
|
+
switch (position) {
|
|
11
|
+
case "Top" :
|
|
12
|
+
return "top";
|
|
13
|
+
case "Bottom" :
|
|
14
|
+
return "bottom";
|
|
15
|
+
case "Left" :
|
|
16
|
+
return "left";
|
|
17
|
+
case "Right" :
|
|
18
|
+
return "right";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function alignToString(align) {
|
|
23
|
+
switch (align) {
|
|
24
|
+
case "Start" :
|
|
25
|
+
return "start";
|
|
26
|
+
case "Center" :
|
|
27
|
+
return "center";
|
|
28
|
+
case "End" :
|
|
29
|
+
return "end";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function Basefn__Popover(props) {
|
|
34
|
+
let className = props.className;
|
|
35
|
+
let __closeOnClickOutside = props.closeOnClickOutside;
|
|
36
|
+
let __align = props.align;
|
|
37
|
+
let __position = props.position;
|
|
38
|
+
let onOpenChange = props.onOpenChange;
|
|
39
|
+
let isOpen = props.isOpen;
|
|
40
|
+
let content = props.content;
|
|
41
|
+
let position = __position !== undefined ? __position : "Bottom";
|
|
42
|
+
let align = __align !== undefined ? __align : "Center";
|
|
43
|
+
let closeOnClickOutside = __closeOnClickOutside !== undefined ? __closeOnClickOutside : true;
|
|
44
|
+
let handleTriggerClick = param => {
|
|
45
|
+
let newValue = !Xote.Signal.get(isOpen);
|
|
46
|
+
Xote.Signal.set(isOpen, newValue);
|
|
47
|
+
if (onOpenChange !== undefined) {
|
|
48
|
+
return onOpenChange(newValue);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
let handleClose = () => {
|
|
52
|
+
Xote.Signal.set(isOpen, false);
|
|
53
|
+
if (onOpenChange !== undefined) {
|
|
54
|
+
return onOpenChange(false);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
let handleBackdropClick = param => {
|
|
58
|
+
if (closeOnClickOutside) {
|
|
59
|
+
return handleClose();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
let getPopoverClassName = () => {
|
|
63
|
+
let customClass = className !== undefined ? " " + className : "";
|
|
64
|
+
return "basefn-popover" + customClass;
|
|
65
|
+
};
|
|
66
|
+
let getContentClassName = () => {
|
|
67
|
+
let positionClass = " basefn-popover__content--" + positionToString(position);
|
|
68
|
+
let alignClass = " basefn-popover__content--align-" + alignToString(align);
|
|
69
|
+
return "basefn-popover__content" + positionClass + alignClass;
|
|
70
|
+
};
|
|
71
|
+
let popoverContent = Xote.Computed.make(() => {
|
|
72
|
+
if (Xote.Signal.get(isOpen)) {
|
|
73
|
+
return [
|
|
74
|
+
Xote__JSX.Elements.jsx("div", {
|
|
75
|
+
class: "basefn-popover__backdrop",
|
|
76
|
+
onClick: handleBackdropClick
|
|
77
|
+
}),
|
|
78
|
+
Xote__JSX.Elements.jsx("div", {
|
|
79
|
+
class: getContentClassName(),
|
|
80
|
+
children: content
|
|
81
|
+
})
|
|
82
|
+
];
|
|
83
|
+
} else {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}, undefined);
|
|
87
|
+
return Xote__JSX.Elements.jsxs("div", {
|
|
88
|
+
class: getPopoverClassName(),
|
|
89
|
+
children: Xote__JSX.array([
|
|
90
|
+
Xote__JSX.Elements.jsx("div", {
|
|
91
|
+
class: "basefn-popover__trigger",
|
|
92
|
+
onClick: handleTriggerClick,
|
|
93
|
+
children: props.trigger
|
|
94
|
+
}),
|
|
95
|
+
Xote.Component.signalFragment(popoverContent)
|
|
96
|
+
])
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let make = Basefn__Popover;
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
positionToString,
|
|
104
|
+
alignToString,
|
|
105
|
+
make,
|
|
106
|
+
}
|
|
107
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
@import '../styles/variables.css';
|
|
2
|
+
|
|
3
|
+
.basefn-scroll-area {
|
|
4
|
+
position: relative;
|
|
5
|
+
scrollbar-color: var(--basefn-border-secondary) transparent;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Orientation */
|
|
9
|
+
.basefn-scroll-area--vertical {
|
|
10
|
+
overflow-y: auto;
|
|
11
|
+
overflow-x: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.basefn-scroll-area--horizontal {
|
|
15
|
+
overflow-x: auto;
|
|
16
|
+
overflow-y: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.basefn-scroll-area--both {
|
|
20
|
+
overflow: auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Webkit scrollbar styling */
|
|
24
|
+
.basefn-scroll-area::-webkit-scrollbar {
|
|
25
|
+
background: transparent;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.basefn-scroll-area::-webkit-scrollbar-track {
|
|
29
|
+
background: transparent;
|
|
30
|
+
border-radius: var(--basefn-radius-full);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.basefn-scroll-area::-webkit-scrollbar-thumb {
|
|
34
|
+
background-color: var(--basefn-border-secondary);
|
|
35
|
+
border-radius: var(--basefn-radius-full);
|
|
36
|
+
border: 2px solid transparent;
|
|
37
|
+
background-clip: content-box;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.basefn-scroll-area::-webkit-scrollbar-thumb:hover {
|
|
41
|
+
background-color: var(--basefn-text-muted);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Scrollbar sizes */
|
|
45
|
+
.basefn-scroll-area--scrollbar-sm::-webkit-scrollbar {
|
|
46
|
+
width: 6px;
|
|
47
|
+
height: 6px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.basefn-scroll-area--scrollbar-md::-webkit-scrollbar {
|
|
51
|
+
width: 10px;
|
|
52
|
+
height: 10px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.basefn-scroll-area--scrollbar-lg::-webkit-scrollbar {
|
|
56
|
+
width: 14px;
|
|
57
|
+
height: 14px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Firefox scrollbar sizes */
|
|
61
|
+
.basefn-scroll-area--scrollbar-sm {
|
|
62
|
+
scrollbar-width: thin;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.basefn-scroll-area--scrollbar-md {
|
|
66
|
+
scrollbar-width: auto;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.basefn-scroll-area--scrollbar-lg {
|
|
70
|
+
scrollbar-width: auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Corner styling for both scrollbars */
|
|
74
|
+
.basefn-scroll-area::-webkit-scrollbar-corner {
|
|
75
|
+
background: transparent;
|
|
76
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
%%raw(`import './Basefn__ScrollArea.css'`)
|
|
2
|
+
|
|
3
|
+
open Xote
|
|
4
|
+
|
|
5
|
+
type orientation = Vertical | Horizontal | Both
|
|
6
|
+
|
|
7
|
+
type scrollbarSize = Sm | Md | Lg
|
|
8
|
+
|
|
9
|
+
let orientationToString = (orientation: orientation) => {
|
|
10
|
+
switch orientation {
|
|
11
|
+
| Vertical => "vertical"
|
|
12
|
+
| Horizontal => "horizontal"
|
|
13
|
+
| Both => "both"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let scrollbarSizeToString = (size: scrollbarSize) => {
|
|
18
|
+
switch size {
|
|
19
|
+
| Sm => "sm"
|
|
20
|
+
| Md => "md"
|
|
21
|
+
| Lg => "lg"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@jsx.component
|
|
26
|
+
let make = (
|
|
27
|
+
~orientation: orientation=Vertical,
|
|
28
|
+
~scrollbarSize: scrollbarSize=Md,
|
|
29
|
+
~maxHeight: option<string>=?,
|
|
30
|
+
~maxWidth: option<string>=?,
|
|
31
|
+
~className: option<string>=?,
|
|
32
|
+
~children: Component.node,
|
|
33
|
+
) => {
|
|
34
|
+
let getClassName = () => {
|
|
35
|
+
let baseClass = "basefn-scroll-area"
|
|
36
|
+
let orientationClass = " basefn-scroll-area--" ++ orientationToString(orientation)
|
|
37
|
+
let sizeClass = " basefn-scroll-area--scrollbar-" ++ scrollbarSizeToString(scrollbarSize)
|
|
38
|
+
let customClass = switch className {
|
|
39
|
+
| Some(c) => " " ++ c
|
|
40
|
+
| None => ""
|
|
41
|
+
}
|
|
42
|
+
baseClass ++ orientationClass ++ sizeClass ++ customClass
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let getStyle = () => {
|
|
46
|
+
let maxHeightStyle = switch maxHeight {
|
|
47
|
+
| Some(h) => "max-height: " ++ h ++ ";"
|
|
48
|
+
| None => ""
|
|
49
|
+
}
|
|
50
|
+
let maxWidthStyle = switch maxWidth {
|
|
51
|
+
| Some(w) => "max-width: " ++ w ++ ";"
|
|
52
|
+
| None => ""
|
|
53
|
+
}
|
|
54
|
+
maxHeightStyle ++ maxWidthStyle
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
<div class={getClassName()} style={getStyle()}>
|
|
58
|
+
{children}
|
|
59
|
+
</div>
|
|
60
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Xote__JSX from "xote/src/Xote__JSX.res.mjs";
|
|
4
|
+
|
|
5
|
+
import './Basefn__ScrollArea.css'
|
|
6
|
+
;
|
|
7
|
+
|
|
8
|
+
function orientationToString(orientation) {
|
|
9
|
+
switch (orientation) {
|
|
10
|
+
case "Vertical" :
|
|
11
|
+
return "vertical";
|
|
12
|
+
case "Horizontal" :
|
|
13
|
+
return "horizontal";
|
|
14
|
+
case "Both" :
|
|
15
|
+
return "both";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function scrollbarSizeToString(size) {
|
|
20
|
+
switch (size) {
|
|
21
|
+
case "Sm" :
|
|
22
|
+
return "sm";
|
|
23
|
+
case "Md" :
|
|
24
|
+
return "md";
|
|
25
|
+
case "Lg" :
|
|
26
|
+
return "lg";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function Basefn__ScrollArea(props) {
|
|
31
|
+
let className = props.className;
|
|
32
|
+
let maxWidth = props.maxWidth;
|
|
33
|
+
let maxHeight = props.maxHeight;
|
|
34
|
+
let __scrollbarSize = props.scrollbarSize;
|
|
35
|
+
let __orientation = props.orientation;
|
|
36
|
+
let orientation = __orientation !== undefined ? __orientation : "Vertical";
|
|
37
|
+
let scrollbarSize = __scrollbarSize !== undefined ? __scrollbarSize : "Md";
|
|
38
|
+
let getClassName = () => {
|
|
39
|
+
let orientationClass = " basefn-scroll-area--" + orientationToString(orientation);
|
|
40
|
+
let sizeClass = " basefn-scroll-area--scrollbar-" + scrollbarSizeToString(scrollbarSize);
|
|
41
|
+
let customClass = className !== undefined ? " " + className : "";
|
|
42
|
+
return "basefn-scroll-area" + orientationClass + sizeClass + customClass;
|
|
43
|
+
};
|
|
44
|
+
let getStyle = () => {
|
|
45
|
+
let maxHeightStyle = maxHeight !== undefined ? "max-height: " + maxHeight + ";" : "";
|
|
46
|
+
let maxWidthStyle = maxWidth !== undefined ? "max-width: " + maxWidth + ";" : "";
|
|
47
|
+
return maxHeightStyle + maxWidthStyle;
|
|
48
|
+
};
|
|
49
|
+
return Xote__JSX.Elements.jsx("div", {
|
|
50
|
+
class: getClassName(),
|
|
51
|
+
style: getStyle(),
|
|
52
|
+
children: props.children
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let make = Basefn__ScrollArea;
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
orientationToString,
|
|
60
|
+
scrollbarSizeToString,
|
|
61
|
+
make,
|
|
62
|
+
}
|
|
63
|
+
/* Not a pure module */
|