basefn 1.1.6 → 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/package.json
CHANGED
package/src/Basefn.res
CHANGED
|
@@ -41,6 +41,7 @@ type sidebarNavSection = Basefn__Sidebar.navSection
|
|
|
41
41
|
type topbarSize = Basefn__Topbar.size
|
|
42
42
|
type topbarNavItem = Basefn__Topbar.navItem
|
|
43
43
|
type appLayoutContentWidth = Basefn__AppLayout.contentWidth
|
|
44
|
+
type appLayoutTopbarPosition = Basefn__AppLayout.topbarPosition
|
|
44
45
|
type iconName = Basefn__Icon.name
|
|
45
46
|
type iconSize = Basefn__Icon.size
|
|
46
47
|
type gridColumns = Basefn__Grid.columns
|
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
width: 100%;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
.basefn-app-layout__body {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex: 1;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
width: 100%;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* When topbar is above, adjust layout direction */
|
|
15
|
+
.basefn-app-layout--topbar-above {
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.basefn-app-layout--topbar-above .basefn-app-layout__body {
|
|
20
|
+
flex: 1;
|
|
21
|
+
min-height: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
.basefn-app-layout__sidebar {
|
|
8
25
|
position: fixed;
|
|
9
26
|
left: 0;
|
|
@@ -12,6 +29,19 @@
|
|
|
12
29
|
z-index: 200;
|
|
13
30
|
}
|
|
14
31
|
|
|
32
|
+
/* When topbar is above, sidebar starts below topbar */
|
|
33
|
+
.basefn-app-layout--topbar-above .basefn-app-layout__sidebar {
|
|
34
|
+
top: 64px; /* Default topbar height (md) */
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.basefn-app-layout--topbar-above.basefn-app-layout--topbar-sm .basefn-app-layout__sidebar {
|
|
38
|
+
top: 56px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.basefn-app-layout--topbar-above.basefn-app-layout--topbar-lg .basefn-app-layout__sidebar {
|
|
42
|
+
top: 72px;
|
|
43
|
+
}
|
|
44
|
+
|
|
15
45
|
.basefn-app-layout__main-wrapper {
|
|
16
46
|
flex: 1;
|
|
17
47
|
display: flex;
|
|
@@ -43,6 +73,14 @@
|
|
|
43
73
|
z-index: 100;
|
|
44
74
|
}
|
|
45
75
|
|
|
76
|
+
/* When topbar is above all content */
|
|
77
|
+
.basefn-app-layout__topbar--above {
|
|
78
|
+
position: sticky;
|
|
79
|
+
top: 0;
|
|
80
|
+
width: 100%;
|
|
81
|
+
z-index: 201; /* Above sidebar */
|
|
82
|
+
}
|
|
83
|
+
|
|
46
84
|
.basefn-app-layout__content {
|
|
47
85
|
flex: 1;
|
|
48
86
|
display: flex;
|
|
@@ -97,4 +135,17 @@
|
|
|
97
135
|
.basefn-app-layout--sidebar-open .basefn-app-layout__sidebar-backdrop {
|
|
98
136
|
display: block;
|
|
99
137
|
}
|
|
138
|
+
|
|
139
|
+
/* When topbar is above, adjust sidebar and backdrop position */
|
|
140
|
+
.basefn-app-layout--topbar-above .basefn-app-layout__sidebar-backdrop {
|
|
141
|
+
top: 64px; /* Start below topbar (md) */
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.basefn-app-layout--topbar-above.basefn-app-layout--topbar-sm .basefn-app-layout__sidebar-backdrop {
|
|
145
|
+
top: 56px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.basefn-app-layout--topbar-above.basefn-app-layout--topbar-lg .basefn-app-layout__sidebar-backdrop {
|
|
149
|
+
top: 72px;
|
|
150
|
+
}
|
|
100
151
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
open Xote
|
|
4
4
|
|
|
5
5
|
type contentWidth = FullWidth | Contained
|
|
6
|
+
type topbarPosition = Inline | AboveAll
|
|
6
7
|
|
|
7
8
|
@jsx.component
|
|
8
9
|
let make = (
|
|
@@ -13,6 +14,8 @@ let make = (
|
|
|
13
14
|
~noPadding: bool=false,
|
|
14
15
|
~sidebarSize: option<string>=?, // "sm" | "md" | "lg"
|
|
15
16
|
~sidebarCollapsed: bool=false,
|
|
17
|
+
~topbarPosition: topbarPosition=Inline,
|
|
18
|
+
~topbarSize: option<string>=?, // "sm" | "md" | "lg"
|
|
16
19
|
) => {
|
|
17
20
|
let sidebarOpen = Signal.make(false)
|
|
18
21
|
|
|
@@ -24,10 +27,24 @@ let make = (
|
|
|
24
27
|
| _ => ""
|
|
25
28
|
}
|
|
26
29
|
let collapsedClass = sidebarCollapsed ? " basefn-app-layout--sidebar-collapsed" : ""
|
|
30
|
+
let topbarPositionClass = switch topbarPosition {
|
|
31
|
+
| AboveAll => " basefn-app-layout--topbar-above"
|
|
32
|
+
| Inline => ""
|
|
33
|
+
}
|
|
34
|
+
let topbarSizeClass = switch (topbarPosition, topbarSize) {
|
|
35
|
+
| (AboveAll, Some("sm")) => " basefn-app-layout--topbar-sm"
|
|
36
|
+
| (AboveAll, Some("lg")) => " basefn-app-layout--topbar-lg"
|
|
37
|
+
| _ => ""
|
|
38
|
+
}
|
|
27
39
|
let sidebarOpenClass = Computed.make(() =>
|
|
28
40
|
Signal.get(sidebarOpen) ? " basefn-app-layout--sidebar-open" : ""
|
|
29
41
|
)
|
|
30
|
-
"basefn-app-layout" ++
|
|
42
|
+
"basefn-app-layout" ++
|
|
43
|
+
hasSidebar ++
|
|
44
|
+
sidebarSizeClass ++
|
|
45
|
+
collapsedClass ++
|
|
46
|
+
topbarPositionClass ++
|
|
47
|
+
topbarSizeClass
|
|
31
48
|
}
|
|
32
49
|
|
|
33
50
|
let getContentClass = () => {
|
|
@@ -51,24 +68,35 @@ let make = (
|
|
|
51
68
|
)
|
|
52
69
|
})}
|
|
53
70
|
>
|
|
54
|
-
{switch
|
|
55
|
-
| Some(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/>
|
|
61
|
-
</>
|
|
62
|
-
| None => <> </>
|
|
71
|
+
{switch (topbarPosition, topbar) {
|
|
72
|
+
| (AboveAll, Some(topbarContent)) =>
|
|
73
|
+
<div class="basefn-app-layout__topbar basefn-app-layout__topbar--above">
|
|
74
|
+
{topbarContent}
|
|
75
|
+
</div>
|
|
76
|
+
| _ => <> </>
|
|
63
77
|
}}
|
|
64
|
-
<div class="basefn-app-
|
|
65
|
-
{switch
|
|
66
|
-
| Some(
|
|
78
|
+
<div class="basefn-app-layout__body">
|
|
79
|
+
{switch sidebar {
|
|
80
|
+
| Some(sidebarContent) =>
|
|
81
|
+
<>
|
|
82
|
+
<div class="basefn-app-layout__sidebar"> {sidebarContent} </div>
|
|
83
|
+
<div
|
|
84
|
+
class="basefn-app-layout__sidebar-backdrop"
|
|
85
|
+
onClick={_ => Signal.set(sidebarOpen, false)}
|
|
86
|
+
/>
|
|
87
|
+
</>
|
|
67
88
|
| None => <> </>
|
|
68
89
|
}}
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
<div class="basefn-app-layout__main-wrapper">
|
|
91
|
+
{switch (topbarPosition, topbar) {
|
|
92
|
+
| (Inline, Some(topbarContent)) =>
|
|
93
|
+
<div class="basefn-app-layout__topbar"> {topbarContent} </div>
|
|
94
|
+
| _ => <> </>
|
|
95
|
+
}}
|
|
96
|
+
<main class="basefn-app-layout__content">
|
|
97
|
+
<div class={getContentClass()}> {children} </div>
|
|
98
|
+
</main>
|
|
99
|
+
</div>
|
|
72
100
|
</div>
|
|
73
101
|
</div>
|
|
74
102
|
}
|
|
@@ -8,6 +8,8 @@ import './Basefn__AppLayout.css'
|
|
|
8
8
|
;
|
|
9
9
|
|
|
10
10
|
function Basefn__AppLayout(props) {
|
|
11
|
+
let topbarSize = props.topbarSize;
|
|
12
|
+
let __topbarPosition = props.topbarPosition;
|
|
11
13
|
let __sidebarCollapsed = props.sidebarCollapsed;
|
|
12
14
|
let sidebarSize = props.sidebarSize;
|
|
13
15
|
let __noPadding = props.noPadding;
|
|
@@ -17,6 +19,7 @@ function Basefn__AppLayout(props) {
|
|
|
17
19
|
let contentWidth = __contentWidth !== undefined ? __contentWidth : "FullWidth";
|
|
18
20
|
let noPadding = __noPadding !== undefined ? __noPadding : false;
|
|
19
21
|
let sidebarCollapsed = __sidebarCollapsed !== undefined ? __sidebarCollapsed : false;
|
|
22
|
+
let topbarPosition = __topbarPosition !== undefined ? __topbarPosition : "Inline";
|
|
20
23
|
let sidebarOpen = Xote.Signal.make(false, undefined, undefined);
|
|
21
24
|
let getLayoutClass = () => {
|
|
22
25
|
let hasSidebar = Core__Option.isSome(sidebar) ? " basefn-app-layout--has-sidebar" : "";
|
|
@@ -36,6 +39,23 @@ function Basefn__AppLayout(props) {
|
|
|
36
39
|
sidebarSizeClass = "";
|
|
37
40
|
}
|
|
38
41
|
let collapsedClass = sidebarCollapsed ? " basefn-app-layout--sidebar-collapsed" : "";
|
|
42
|
+
let topbarPositionClass;
|
|
43
|
+
topbarPositionClass = topbarPosition === "Inline" ? "" : " basefn-app-layout--topbar-above";
|
|
44
|
+
let topbarSizeClass;
|
|
45
|
+
if (topbarPosition === "Inline" || topbarSize === undefined) {
|
|
46
|
+
topbarSizeClass = "";
|
|
47
|
+
} else {
|
|
48
|
+
switch (topbarSize) {
|
|
49
|
+
case "lg" :
|
|
50
|
+
topbarSizeClass = " basefn-app-layout--topbar-lg";
|
|
51
|
+
break;
|
|
52
|
+
case "sm" :
|
|
53
|
+
topbarSizeClass = " basefn-app-layout--topbar-sm";
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
topbarSizeClass = "";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
39
59
|
Xote.Computed.make(() => {
|
|
40
60
|
if (Xote.Signal.get(sidebarOpen)) {
|
|
41
61
|
return " basefn-app-layout--sidebar-open";
|
|
@@ -43,7 +63,7 @@ function Basefn__AppLayout(props) {
|
|
|
43
63
|
return "";
|
|
44
64
|
}
|
|
45
65
|
}, undefined);
|
|
46
|
-
return "basefn-app-layout" + hasSidebar + sidebarSizeClass + collapsedClass;
|
|
66
|
+
return "basefn-app-layout" + hasSidebar + sidebarSizeClass + collapsedClass + topbarPositionClass + topbarSizeClass;
|
|
47
67
|
};
|
|
48
68
|
let getContentClass = () => {
|
|
49
69
|
let widthClass;
|
|
@@ -51,6 +71,16 @@ function Basefn__AppLayout(props) {
|
|
|
51
71
|
let paddingClass = noPadding ? " basefn-app-layout__content-inner--no-padding" : "";
|
|
52
72
|
return "basefn-app-layout__content-inner" + widthClass + paddingClass;
|
|
53
73
|
};
|
|
74
|
+
let tmp;
|
|
75
|
+
tmp = topbarPosition === "Inline" || topbar === undefined ? Xote__JSX.jsx(Xote__JSX.jsxFragment, {}) : Xote__JSX.Elements.jsx("div", {
|
|
76
|
+
class: "basefn-app-layout__topbar basefn-app-layout__topbar--above",
|
|
77
|
+
children: topbar
|
|
78
|
+
});
|
|
79
|
+
let tmp$1;
|
|
80
|
+
tmp$1 = topbarPosition === "Inline" && topbar !== undefined ? Xote__JSX.Elements.jsx("div", {
|
|
81
|
+
class: "basefn-app-layout__topbar",
|
|
82
|
+
children: topbar
|
|
83
|
+
}) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {});
|
|
54
84
|
return Xote__JSX.Elements.jsxs("div", {
|
|
55
85
|
class: Xote.Computed.make(() => getLayoutClass() + Xote.Signal.get(Xote.Computed.make(() => {
|
|
56
86
|
if (Xote.Signal.get(sidebarOpen)) {
|
|
@@ -60,31 +90,34 @@ function Basefn__AppLayout(props) {
|
|
|
60
90
|
}
|
|
61
91
|
}, undefined)), undefined),
|
|
62
92
|
children: Xote__JSX.array([
|
|
63
|
-
|
|
64
|
-
children: Xote__JSX.array([
|
|
65
|
-
Xote__JSX.Elements.jsx("div", {
|
|
66
|
-
class: "basefn-app-layout__sidebar",
|
|
67
|
-
children: sidebar
|
|
68
|
-
}),
|
|
69
|
-
Xote__JSX.Elements.jsx("div", {
|
|
70
|
-
class: "basefn-app-layout__sidebar-backdrop",
|
|
71
|
-
onClick: param => Xote.Signal.set(sidebarOpen, false)
|
|
72
|
-
})
|
|
73
|
-
])
|
|
74
|
-
}) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
|
|
93
|
+
tmp,
|
|
75
94
|
Xote__JSX.Elements.jsxs("div", {
|
|
76
|
-
class: "basefn-app-
|
|
95
|
+
class: "basefn-app-layout__body",
|
|
77
96
|
children: Xote__JSX.array([
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
sidebar !== undefined ? Xote__JSX.jsxs(Xote__JSX.jsxFragment, {
|
|
98
|
+
children: Xote__JSX.array([
|
|
99
|
+
Xote__JSX.Elements.jsx("div", {
|
|
100
|
+
class: "basefn-app-layout__sidebar",
|
|
101
|
+
children: sidebar
|
|
102
|
+
}),
|
|
103
|
+
Xote__JSX.Elements.jsx("div", {
|
|
104
|
+
class: "basefn-app-layout__sidebar-backdrop",
|
|
105
|
+
onClick: param => Xote.Signal.set(sidebarOpen, false)
|
|
106
|
+
})
|
|
107
|
+
])
|
|
81
108
|
}) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
|
|
82
|
-
Xote__JSX.Elements.
|
|
83
|
-
class: "basefn-app-
|
|
84
|
-
children: Xote__JSX.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
Xote__JSX.Elements.jsxs("div", {
|
|
110
|
+
class: "basefn-app-layout__main-wrapper",
|
|
111
|
+
children: Xote__JSX.array([
|
|
112
|
+
tmp$1,
|
|
113
|
+
Xote__JSX.Elements.jsx("main", {
|
|
114
|
+
class: "basefn-app-layout__content",
|
|
115
|
+
children: Xote__JSX.Elements.jsx("div", {
|
|
116
|
+
class: getContentClass(),
|
|
117
|
+
children: props.children
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
])
|
|
88
121
|
})
|
|
89
122
|
])
|
|
90
123
|
})
|