basefn 1.0.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.
Files changed (154) hide show
  1. package/README.md +104 -0
  2. package/package.json +82 -0
  3. package/rescript.json +32 -0
  4. package/src/Basefn.css +14 -0
  5. package/src/Basefn.res +105 -0
  6. package/src/Basefn.res.mjs +114 -0
  7. package/src/Basefn__Dom.res +9 -0
  8. package/src/Basefn__Dom.res.mjs +24 -0
  9. package/src/Basefn__Utils.res +15 -0
  10. package/src/Basefn__Utils.res.mjs +32 -0
  11. package/src/Demo.res +1417 -0
  12. package/src/Demo.res.mjs +2328 -0
  13. package/src/Eita.res.mjs +105 -0
  14. package/src/Eita__Accordion.res.mjs +77 -0
  15. package/src/Eita__Alert.res.mjs +81 -0
  16. package/src/Eita__AppLayout.res.mjs +100 -0
  17. package/src/Eita__Avatar.res.mjs +40 -0
  18. package/src/Eita__Badge.res.mjs +65 -0
  19. package/src/Eita__Breadcrumb.res.mjs +53 -0
  20. package/src/Eita__Button.res.mjs +47 -0
  21. package/src/Eita__Card.res.mjs +60 -0
  22. package/src/Eita__Checkbox.res.mjs +36 -0
  23. package/src/Eita__Dom.res.mjs +16 -0
  24. package/src/Eita__Drawer.res.mjs +112 -0
  25. package/src/Eita__Dropdown.res.mjs +96 -0
  26. package/src/Eita__Grid.res.mjs +24 -0
  27. package/src/Eita__Input.res.mjs +54 -0
  28. package/src/Eita__Kbd.res.mjs +42 -0
  29. package/src/Eita__Label.res.mjs +24 -0
  30. package/src/Eita__Modal.res.mjs +93 -0
  31. package/src/Eita__Progress.res.mjs +101 -0
  32. package/src/Eita__Radio.res.mjs +38 -0
  33. package/src/Eita__Select.res.mjs +40 -0
  34. package/src/Eita__Separator.res.mjs +70 -0
  35. package/src/Eita__Sidebar.res.mjs +103 -0
  36. package/src/Eita__Slider.res.mjs +89 -0
  37. package/src/Eita__Spinner.res.mjs +69 -0
  38. package/src/Eita__Stepper.res.mjs +114 -0
  39. package/src/Eita__Switch.res.mjs +84 -0
  40. package/src/Eita__Tabs.res.mjs +57 -0
  41. package/src/Eita__Textarea.res.mjs +39 -0
  42. package/src/Eita__Timeline.res.mjs +86 -0
  43. package/src/Eita__Toast.res.mjs +112 -0
  44. package/src/Eita__Tooltip.res.mjs +60 -0
  45. package/src/Eita__Topbar.res.mjs +96 -0
  46. package/src/Eita__Typography.res.mjs +183 -0
  47. package/src/Eita__Utils.res.mjs +32 -0
  48. package/src/Example.res +111 -0
  49. package/src/Example.res.mjs +176 -0
  50. package/src/components/Basefn__Accordion.css +70 -0
  51. package/src/components/Basefn__Accordion.res +79 -0
  52. package/src/components/Basefn__Accordion.res.mjs +77 -0
  53. package/src/components/Basefn__Alert.css +79 -0
  54. package/src/components/Basefn__Alert.res +68 -0
  55. package/src/components/Basefn__Alert.res.mjs +78 -0
  56. package/src/components/Basefn__AppLayout.css +100 -0
  57. package/src/components/Basefn__AppLayout.res +74 -0
  58. package/src/components/Basefn__AppLayout.res.mjs +100 -0
  59. package/src/components/Basefn__Avatar.css +25 -0
  60. package/src/components/Basefn__Avatar.res +23 -0
  61. package/src/components/Basefn__Avatar.res.mjs +40 -0
  62. package/src/components/Basefn__Badge.css +71 -0
  63. package/src/components/Basefn__Badge.res +43 -0
  64. package/src/components/Basefn__Badge.res.mjs +65 -0
  65. package/src/components/Basefn__Breadcrumb.css +36 -0
  66. package/src/components/Basefn__Breadcrumb.res +45 -0
  67. package/src/components/Basefn__Breadcrumb.res.mjs +53 -0
  68. package/src/components/Basefn__Button.css +83 -0
  69. package/src/components/Basefn__Button.res +32 -0
  70. package/src/components/Basefn__Button.res.mjs +54 -0
  71. package/src/components/Basefn__Card.css +50 -0
  72. package/src/components/Basefn__Card.res +45 -0
  73. package/src/components/Basefn__Card.res.mjs +60 -0
  74. package/src/components/Basefn__Checkbox.css +72 -0
  75. package/src/components/Basefn__Checkbox.res +25 -0
  76. package/src/components/Basefn__Checkbox.res.mjs +36 -0
  77. package/src/components/Basefn__Drawer.css +168 -0
  78. package/src/components/Basefn__Drawer.res +86 -0
  79. package/src/components/Basefn__Drawer.res.mjs +112 -0
  80. package/src/components/Basefn__Dropdown.css +76 -0
  81. package/src/components/Basefn__Dropdown.res +85 -0
  82. package/src/components/Basefn__Dropdown.res.mjs +96 -0
  83. package/src/components/Basefn__Grid.css +11 -0
  84. package/src/components/Basefn__Grid.res +296 -0
  85. package/src/components/Basefn__Grid.res.mjs +263 -0
  86. package/src/components/Basefn__Icon.css +12 -0
  87. package/src/components/Basefn__Icon.res +196 -0
  88. package/src/components/Basefn__Icon.res.mjs +183 -0
  89. package/src/components/Basefn__Input.css +44 -0
  90. package/src/components/Basefn__Input.res +48 -0
  91. package/src/components/Basefn__Input.res.mjs +63 -0
  92. package/src/components/Basefn__Kbd.css +65 -0
  93. package/src/components/Basefn__Kbd.res +27 -0
  94. package/src/components/Basefn__Kbd.res.mjs +42 -0
  95. package/src/components/Basefn__Label.css +22 -0
  96. package/src/components/Basefn__Label.res +18 -0
  97. package/src/components/Basefn__Label.res.mjs +24 -0
  98. package/src/components/Basefn__Modal.css +100 -0
  99. package/src/components/Basefn__Modal.res +74 -0
  100. package/src/components/Basefn__Modal.res.mjs +93 -0
  101. package/src/components/Basefn__Progress.css +69 -0
  102. package/src/components/Basefn__Progress.res +88 -0
  103. package/src/components/Basefn__Progress.res.mjs +101 -0
  104. package/src/components/Basefn__Radio.css +72 -0
  105. package/src/components/Basefn__Radio.res +35 -0
  106. package/src/components/Basefn__Radio.res.mjs +38 -0
  107. package/src/components/Basefn__Select.css +44 -0
  108. package/src/components/Basefn__Select.res +33 -0
  109. package/src/components/Basefn__Select.res.mjs +40 -0
  110. package/src/components/Basefn__Separator.css +85 -0
  111. package/src/components/Basefn__Separator.res +45 -0
  112. package/src/components/Basefn__Separator.res.mjs +70 -0
  113. package/src/components/Basefn__Sidebar.css +141 -0
  114. package/src/components/Basefn__Sidebar.res +95 -0
  115. package/src/components/Basefn__Sidebar.res.mjs +107 -0
  116. package/src/components/Basefn__Slider.css +97 -0
  117. package/src/components/Basefn__Slider.res +68 -0
  118. package/src/components/Basefn__Slider.res.mjs +89 -0
  119. package/src/components/Basefn__Spinner.css +63 -0
  120. package/src/components/Basefn__Spinner.res +44 -0
  121. package/src/components/Basefn__Spinner.res.mjs +69 -0
  122. package/src/components/Basefn__Stepper.css +141 -0
  123. package/src/components/Basefn__Stepper.res +86 -0
  124. package/src/components/Basefn__Stepper.res.mjs +114 -0
  125. package/src/components/Basefn__Switch.css +80 -0
  126. package/src/components/Basefn__Switch.res +62 -0
  127. package/src/components/Basefn__Switch.res.mjs +84 -0
  128. package/src/components/Basefn__Tabs.css +54 -0
  129. package/src/components/Basefn__Tabs.res +73 -0
  130. package/src/components/Basefn__Tabs.res.mjs +57 -0
  131. package/src/components/Basefn__Textarea.css +41 -0
  132. package/src/components/Basefn__Textarea.res +28 -0
  133. package/src/components/Basefn__Textarea.res.mjs +41 -0
  134. package/src/components/Basefn__ThemeToggle.css +5 -0
  135. package/src/components/Basefn__ThemeToggle.res +29 -0
  136. package/src/components/Basefn__ThemeToggle.res.mjs +49 -0
  137. package/src/components/Basefn__Timeline.css +144 -0
  138. package/src/components/Basefn__Timeline.res +70 -0
  139. package/src/components/Basefn__Timeline.res.mjs +86 -0
  140. package/src/components/Basefn__Toast.css +100 -0
  141. package/src/components/Basefn__Toast.res +92 -0
  142. package/src/components/Basefn__Toast.res.mjs +112 -0
  143. package/src/components/Basefn__Tooltip.css +84 -0
  144. package/src/components/Basefn__Tooltip.res +42 -0
  145. package/src/components/Basefn__Tooltip.res.mjs +60 -0
  146. package/src/components/Basefn__Topbar.css +130 -0
  147. package/src/components/Basefn__Topbar.res +92 -0
  148. package/src/components/Basefn__Topbar.res.mjs +91 -0
  149. package/src/components/Basefn__Typography.css +120 -0
  150. package/src/components/Basefn__Typography.res +96 -0
  151. package/src/components/Basefn__Typography.res.mjs +175 -0
  152. package/src/styles/Basefn__Theme.res +63 -0
  153. package/src/styles/Basefn__Theme.res.mjs +65 -0
  154. package/src/styles/variables.css +199 -0
@@ -0,0 +1,84 @@
1
+ .basefn-tooltip-wrapper {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .basefn-tooltip {
7
+ position: absolute;
8
+ background-color: #1f2937;
9
+ color: white;
10
+ padding: 0.5rem 0.75rem;
11
+ border-radius: 0.375rem;
12
+ font-size: 0.875rem;
13
+ white-space: nowrap;
14
+ z-index: 1000;
15
+ pointer-events: none;
16
+ animation: basefn-tooltip-fade-in 0.15s ease-out;
17
+ }
18
+
19
+ .basefn-tooltip--top {
20
+ bottom: calc(100% + 8px);
21
+ left: 50%;
22
+ transform: translateX(-50%);
23
+ }
24
+
25
+ .basefn-tooltip--bottom {
26
+ top: calc(100% + 8px);
27
+ left: 50%;
28
+ transform: translateX(-50%);
29
+ }
30
+
31
+ .basefn-tooltip--left {
32
+ right: calc(100% + 8px);
33
+ top: 50%;
34
+ transform: translateY(-50%);
35
+ }
36
+
37
+ .basefn-tooltip--right {
38
+ left: calc(100% + 8px);
39
+ top: 50%;
40
+ transform: translateY(-50%);
41
+ }
42
+
43
+ .basefn-tooltip::after {
44
+ content: '';
45
+ position: absolute;
46
+ border: 4px solid transparent;
47
+ }
48
+
49
+ .basefn-tooltip--top::after {
50
+ top: 100%;
51
+ left: 50%;
52
+ transform: translateX(-50%);
53
+ border-top-color: #1f2937;
54
+ }
55
+
56
+ .basefn-tooltip--bottom::after {
57
+ bottom: 100%;
58
+ left: 50%;
59
+ transform: translateX(-50%);
60
+ border-bottom-color: #1f2937;
61
+ }
62
+
63
+ .basefn-tooltip--left::after {
64
+ left: 100%;
65
+ top: 50%;
66
+ transform: translateY(-50%);
67
+ border-left-color: #1f2937;
68
+ }
69
+
70
+ .basefn-tooltip--right::after {
71
+ right: 100%;
72
+ top: 50%;
73
+ transform: translateY(-50%);
74
+ border-right-color: #1f2937;
75
+ }
76
+
77
+ @keyframes basefn-tooltip-fade-in {
78
+ from {
79
+ opacity: 0;
80
+ }
81
+ to {
82
+ opacity: 1;
83
+ }
84
+ }
@@ -0,0 +1,42 @@
1
+ %%raw(`import './Basefn__Tooltip.css'`)
2
+
3
+ open Xote
4
+
5
+ type position = Top | Bottom | Left | Right
6
+
7
+ let positionToString = (position: position) => {
8
+ switch position {
9
+ | Top => "top"
10
+ | Bottom => "bottom"
11
+ | Left => "left"
12
+ | Right => "right"
13
+ }
14
+ }
15
+
16
+ @jsx.component
17
+ let make = (~content: string, ~position: position=Top, ~children: Component.node) => {
18
+ let isVisible = Signal.make(false)
19
+
20
+ let handleMouseEnter = _ => Signal.set(isVisible, true)
21
+ let handleMouseLeave = _ => Signal.set(isVisible, false)
22
+
23
+ let getTooltipClass = () => {
24
+ let posClass = "basefn-tooltip--" ++ positionToString(position)
25
+ "basefn-tooltip " ++ posClass
26
+ }
27
+
28
+ let tooltipContent = Computed.make(() => {
29
+ if Signal.get(isVisible) {
30
+ [<div class={getTooltipClass()}> {Component.text(content)} </div>]
31
+ } else {
32
+ []
33
+ }
34
+ })
35
+
36
+ <div
37
+ class="basefn-tooltip-wrapper" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}
38
+ >
39
+ {children}
40
+ {Component.signalFragment(tooltipContent)}
41
+ </div>
42
+ }
@@ -0,0 +1,60 @@
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__Tooltip.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 Basefn__Tooltip(props) {
23
+ let __position = props.position;
24
+ let content = props.content;
25
+ let position = __position !== undefined ? __position : "Top";
26
+ let isVisible = Xote.Signal.make(false, undefined, undefined);
27
+ let handleMouseEnter = param => Xote.Signal.set(isVisible, true);
28
+ let handleMouseLeave = param => Xote.Signal.set(isVisible, false);
29
+ let getTooltipClass = () => {
30
+ let posClass = "basefn-tooltip--" + positionToString(position);
31
+ return "basefn-tooltip " + posClass;
32
+ };
33
+ let tooltipContent = Xote.Computed.make(() => {
34
+ if (Xote.Signal.get(isVisible)) {
35
+ return [Xote__JSX.Elements.jsx("div", {
36
+ class: getTooltipClass(),
37
+ children: Xote.Component.text(content)
38
+ })];
39
+ } else {
40
+ return [];
41
+ }
42
+ }, undefined);
43
+ return Xote__JSX.Elements.jsxs("div", {
44
+ class: "basefn-tooltip-wrapper",
45
+ onMouseEnter: handleMouseEnter,
46
+ onMouseLeave: handleMouseLeave,
47
+ children: Xote__JSX.array([
48
+ props.children,
49
+ Xote.Component.signalFragment(tooltipContent)
50
+ ])
51
+ });
52
+ }
53
+
54
+ let make = Basefn__Tooltip;
55
+
56
+ export {
57
+ positionToString,
58
+ make,
59
+ }
60
+ /* Not a pure module */
@@ -0,0 +1,130 @@
1
+ @import '../styles/variables.css';
2
+
3
+ .basefn-topbar {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: space-between;
7
+ padding: 1rem 1.5rem;
8
+ background-color: var(--basefn-bg-primary);
9
+ color: var(--basefn-text-primary);
10
+ height: 4rem;
11
+ position: sticky;
12
+ top: 0;
13
+ z-index: 100;
14
+ border-bottom: 1px solid transparent;
15
+ border-bottom: 1px solid var(--basefn-border-primary);
16
+ }
17
+
18
+ .basefn-topbar--scrolling {
19
+ }
20
+
21
+ .basefn-topbar__left {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 0.5rem;
25
+ flex: 1;
26
+ height: 100%;
27
+ line-height: 2rem;
28
+ }
29
+
30
+ .basefn-topbar__left:empty {
31
+ display: none;
32
+ }
33
+
34
+ .basefn-topbar__center {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 1rem;
38
+ }
39
+
40
+ .basefn-topbar__right {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 1rem;
44
+ flex: 1;
45
+ justify-content: flex-end;
46
+ }
47
+
48
+ .basefn-topbar__logo {
49
+ font-size: 1.25rem;
50
+ font-weight: 700;
51
+ color: var(--basefn-text-primary);
52
+ font-family: var(--font-mono);
53
+ }
54
+
55
+ .basefn-topbar__menu-button {
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ width: 2.5rem;
60
+ height: 2.5rem;
61
+ background: none;
62
+ border: none;
63
+ border-radius: 0.375rem;
64
+ cursor: pointer;
65
+ color: var(--basefn-text-tertiary);
66
+ transition: all 0.2s;
67
+ }
68
+
69
+ .basefn-topbar__menu-button:hover {
70
+ background-color: var(--basefn-bg-tertiary);
71
+ color: var(--basefn-text-primary);
72
+ }
73
+
74
+ .basefn-topbar__search {
75
+ flex: 1;
76
+ max-width: 400px;
77
+ }
78
+
79
+ .basefn-topbar__nav {
80
+ display: flex;
81
+ align-items: center;
82
+ gap: 0.25rem;
83
+ }
84
+
85
+ .basefn-topbar__nav-item {
86
+ padding: 0.5rem 1rem;
87
+ color: var(--basefn-text-tertiary);
88
+ text-decoration: none;
89
+ font-size: 0.875rem;
90
+ font-weight: 500;
91
+ border-radius: var(--basefn-radius-full);
92
+ cursor: pointer;
93
+ transition: all 0.2s;
94
+ background: none;
95
+ border: none;
96
+ }
97
+
98
+ .basefn-topbar__nav-item:hover {
99
+ background-color: var(--basefn-bg-secondary);
100
+ color: var(--basefn-text-primary);
101
+ }
102
+
103
+ .basefn-topbar__nav-item--active,
104
+ .basefn-topbar__nav-item--active:hover {
105
+ background-color: var(--basefn-bg-primary-aa);
106
+ color: var(--basefn-color-primary);
107
+ font-weight: 700;
108
+ }
109
+
110
+ .basefn-topbar__actions {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: 0.75rem;
114
+ }
115
+
116
+ /* Size variants */
117
+ .basefn-topbar--sm {
118
+ height: 56px;
119
+ padding: 1rem;
120
+ }
121
+
122
+ .basefn-topbar--md {
123
+ height: 64px;
124
+ padding: 1rem 1.5rem;
125
+ }
126
+
127
+ .basefn-topbar--lg {
128
+ height: 72px;
129
+ padding: 1rem 2rem;
130
+ }
@@ -0,0 +1,92 @@
1
+ %%raw(`import './Basefn__Topbar.css'`)
2
+
3
+ open Xote
4
+
5
+ type size = Sm | Md | Lg
6
+
7
+ type navItem = {
8
+ label: string,
9
+ active: bool,
10
+ onClick: unit => unit,
11
+ }
12
+
13
+ let sizeToString = (size: size) => {
14
+ switch size {
15
+ | Sm => "sm"
16
+ | Md => "md"
17
+ | Lg => "lg"
18
+ }
19
+ }
20
+
21
+ @jsx.component
22
+ let make = (
23
+ ~logo: option<Component.node>=?,
24
+ ~navItems: option<array<navItem>>=?,
25
+ ~leftContent: option<Component.node>=?,
26
+ ~centerContent: option<Component.node>=?,
27
+ ~rightContent: option<Component.node>=?,
28
+ ~onMenuClick: option<unit => unit>=?,
29
+ ~size: size=Md,
30
+ ) => {
31
+ let scrolling = Signal.make(false)
32
+ let class = Computed.make(() => {
33
+ let sizeClass = " basefn-topbar--" ++ sizeToString(size)
34
+ let scrollingClass = Signal.get(scrolling) ? " basefn-topbar--scrolling" : ""
35
+ "basefn-topbar" ++ sizeClass ++ scrollingClass
36
+ })
37
+
38
+ let _ = Effect.run(() => {
39
+ Basefn__Dom.addEventListener("scroll", () => {
40
+ let scrollY = %raw("window.scrollY")
41
+ Signal.set(scrolling, scrollY >= 64)
42
+ })
43
+ })
44
+
45
+ <header class>
46
+ <div class="basefn-topbar__left">
47
+ {switch onMenuClick {
48
+ | Some(handler) =>
49
+ <button class="basefn-topbar__menu-button" onClick={_ => handler()}>
50
+ {Component.text("\u2630")}
51
+ </button>
52
+ | None => <> </>
53
+ }}
54
+ {switch logo {
55
+ | Some(logoContent) => <div class="basefn-topbar__logo"> {logoContent} </div>
56
+ | None => <> </>
57
+ }}
58
+ {switch leftContent {
59
+ | Some(content) => content
60
+ | None => <> </>
61
+ }}
62
+ </div>
63
+ <div class="basefn-topbar__center">
64
+ {switch navItems {
65
+ | Some(items) =>
66
+ <nav class="basefn-topbar__nav">
67
+ {items
68
+ ->Array.mapWithIndex((item, index) => {
69
+ let className =
70
+ "basefn-topbar__nav-item" ++ (item.active ? " basefn-topbar__nav-item--active" : "")
71
+
72
+ <button key={Int.toString(index)} class={className} onClick={_ => item.onClick()}>
73
+ {Component.text(item.label)}
74
+ </button>
75
+ })
76
+ ->Component.fragment}
77
+ </nav>
78
+ | None => <> </>
79
+ }}
80
+ {switch centerContent {
81
+ | Some(content) => content
82
+ | None => <> </>
83
+ }}
84
+ </div>
85
+ <div class="basefn-topbar__right">
86
+ {switch rightContent {
87
+ | Some(content) => content
88
+ | None => <> </>
89
+ }}
90
+ </div>
91
+ </header>
92
+ }
@@ -0,0 +1,91 @@
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 Basefn__Dom from "../Basefn__Dom.res.mjs";
6
+
7
+ import './Basefn__Topbar.css'
8
+ ;
9
+
10
+ function sizeToString(size) {
11
+ switch (size) {
12
+ case "Sm" :
13
+ return "sm";
14
+ case "Md" :
15
+ return "md";
16
+ case "Lg" :
17
+ return "lg";
18
+ }
19
+ }
20
+
21
+ function Basefn__Topbar(props) {
22
+ let __size = props.size;
23
+ let onMenuClick = props.onMenuClick;
24
+ let rightContent = props.rightContent;
25
+ let centerContent = props.centerContent;
26
+ let leftContent = props.leftContent;
27
+ let navItems = props.navItems;
28
+ let logo = props.logo;
29
+ let size = __size !== undefined ? __size : "Md";
30
+ let scrolling = Xote.Signal.make(false, undefined, undefined);
31
+ let $$class = Xote.Computed.make(() => {
32
+ let sizeClass = " basefn-topbar--" + sizeToString(size);
33
+ let scrollingClass = Xote.Signal.get(scrolling) ? " basefn-topbar--scrolling" : "";
34
+ return "basefn-topbar" + sizeClass + scrollingClass;
35
+ }, undefined);
36
+ Xote.Effect.run(() => Basefn__Dom.addEventListener("scroll", () => {
37
+ let scrollY = window.scrollY;
38
+ Xote.Signal.set(scrolling, scrollY >= 64);
39
+ }), undefined);
40
+ return Xote__JSX.Elements.jsxs("header", {
41
+ class: $$class,
42
+ children: Xote__JSX.array([
43
+ Xote__JSX.Elements.jsxs("div", {
44
+ class: "basefn-topbar__left",
45
+ children: Xote__JSX.array([
46
+ onMenuClick !== undefined ? Xote__JSX.Elements.jsx("button", {
47
+ class: "basefn-topbar__menu-button",
48
+ onClick: param => onMenuClick(),
49
+ children: Xote.Component.text("\u2630")
50
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
51
+ logo !== undefined ? Xote__JSX.Elements.jsx("div", {
52
+ class: "basefn-topbar__logo",
53
+ children: logo
54
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
55
+ leftContent !== undefined ? leftContent : Xote__JSX.jsx(Xote__JSX.jsxFragment, {})
56
+ ])
57
+ }),
58
+ Xote__JSX.Elements.jsxs("div", {
59
+ class: "basefn-topbar__center",
60
+ children: Xote__JSX.array([
61
+ navItems !== undefined ? Xote__JSX.Elements.jsx("nav", {
62
+ class: "basefn-topbar__nav",
63
+ children: Xote.Component.fragment(navItems.map((item, index) => {
64
+ let className = "basefn-topbar__nav-item" + (
65
+ item.active ? " basefn-topbar__nav-item--active" : ""
66
+ );
67
+ return Xote__JSX.Elements.jsxKeyed("button", {
68
+ class: className,
69
+ onClick: param => item.onClick(),
70
+ children: Xote.Component.text(item.label)
71
+ }, index.toString(), undefined);
72
+ }))
73
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
74
+ centerContent !== undefined ? centerContent : Xote__JSX.jsx(Xote__JSX.jsxFragment, {})
75
+ ])
76
+ }),
77
+ Xote__JSX.Elements.jsx("div", {
78
+ class: "basefn-topbar__right",
79
+ children: rightContent !== undefined ? rightContent : Xote__JSX.jsx(Xote__JSX.jsxFragment, {})
80
+ })
81
+ ])
82
+ });
83
+ }
84
+
85
+ let make = Basefn__Topbar;
86
+
87
+ export {
88
+ sizeToString,
89
+ make,
90
+ }
91
+ /* Not a pure module */
@@ -0,0 +1,120 @@
1
+ .basefn-typography {
2
+ margin: 0;
3
+ color: var(--basefn-text-primary);
4
+ }
5
+
6
+ /* Headings */
7
+ .basefn-typography--h1 {
8
+ font-size: 3rem;
9
+ font-weight: 800;
10
+ line-height: 1.2;
11
+ letter-spacing: -0.02em;
12
+ }
13
+
14
+ .basefn-typography--h2 {
15
+ font-size: 2.25rem;
16
+ font-weight: 700;
17
+ line-height: 1.25;
18
+ letter-spacing: -0.01em;
19
+ margin-bottom: 1rem;
20
+ }
21
+
22
+ .basefn-typography--h3 {
23
+ font-size: 1.875rem;
24
+ font-weight: 700;
25
+ line-height: 1.3;
26
+ margin-bottom: 1rem;
27
+ }
28
+
29
+ .basefn-typography--h4 {
30
+ font-size: 1.5rem;
31
+ font-weight: 600;
32
+ line-height: 1.4;
33
+ }
34
+
35
+ .basefn-typography--h5 {
36
+ font-size: 1.25rem;
37
+ font-weight: 600;
38
+ line-height: 1.5;
39
+ }
40
+
41
+ .basefn-typography--h6 {
42
+ font-size: 1rem;
43
+ font-weight: 600;
44
+ line-height: 1.5;
45
+ }
46
+
47
+ /* Paragraph */
48
+ .basefn-typography--p {
49
+ font-size: 1rem;
50
+ line-height: 1.75;
51
+ font-weight: 400;
52
+ margin-bottom: 1rem;
53
+ color: var(--basefn-text-tertiary);
54
+ }
55
+
56
+ /* Lead paragraph */
57
+ .basefn-typography--lead {
58
+ font-size: 1.25rem;
59
+ line-height: 1.75;
60
+ font-weight: 400;
61
+ color: var(--basefn-text-secondary);
62
+ margin-bottom: 2rem;
63
+ }
64
+
65
+ /* Small text */
66
+ .basefn-typography--small {
67
+ font-size: 0.875rem;
68
+ line-height: 1.5;
69
+ font-weight: 400;
70
+ color: var(--basefn-text-tertiary);
71
+ }
72
+
73
+ /* Muted text */
74
+ .basefn-typography--muted {
75
+ font-size: 1rem;
76
+ line-height: 1.75;
77
+ font-weight: 400;
78
+ color: var(--basefn-text-muted);
79
+ }
80
+
81
+ /* Code */
82
+ .basefn-typography--code {
83
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
84
+ font-size: 0.875rem;
85
+ padding: 0.125rem 0.375rem;
86
+ background-color: var(--basefn-bg-tertiary);
87
+ border: 1px solid var(--basefn-border-primary);
88
+ border-radius: 0.25rem;
89
+ color: var(--basefn-text-primary);
90
+ }
91
+
92
+ .basefn-typography--unstyled {
93
+ display: inline-block;
94
+ color: var(--basefn-text-tertiary);
95
+ }
96
+
97
+ /* Text alignment */
98
+ .basefn-typography--left {
99
+ text-align: left;
100
+ }
101
+
102
+ .basefn-typography--center {
103
+ text-align: center;
104
+ }
105
+
106
+ .basefn-typography--right {
107
+ text-align: right;
108
+ }
109
+
110
+ .basefn-typography--justify {
111
+ text-align: justify;
112
+ }
113
+
114
+ .basefn-code {
115
+ background: var(--basefn-bg-primary);
116
+ color: var(--basefn-text-secondary);
117
+ font-family: 'Source Code', Courier, monospace;
118
+ font-size: 0.875rem;
119
+ line-height: 1.5em;
120
+ }
@@ -0,0 +1,96 @@
1
+ %%raw(`import './Basefn__Typography.css'`)
2
+
3
+ open Xote
4
+
5
+ type variant = H1 | H2 | H3 | H4 | H5 | H6 | P | Small | Lead | Muted | Code | Unstyled
6
+
7
+ type align = Left | Center | Right | Justify
8
+
9
+ let variantToTag = (variant: variant) => {
10
+ switch variant {
11
+ | H1 => "h1"
12
+ | H2 => "h2"
13
+ | H3 => "h3"
14
+ | H4 => "h4"
15
+ | H5 => "h5"
16
+ | H6 => "h6"
17
+ | P => "p"
18
+ | Small => "small"
19
+ | Lead => "p"
20
+ | Muted => "p"
21
+ | Code => "code"
22
+ | Unstyled => "div"
23
+ }
24
+ }
25
+
26
+ let variantToClass = (variant: variant) => {
27
+ switch variant {
28
+ | H1 => "basefn-typography--h1"
29
+ | H2 => "basefn-typography--h2"
30
+ | H3 => "basefn-typography--h3"
31
+ | H4 => "basefn-typography--h4"
32
+ | H5 => "basefn-typography--h5"
33
+ | H6 => "basefn-typography--h6"
34
+ | P => "basefn-typography--p"
35
+ | Small => "basefn-typography--small"
36
+ | Lead => "basefn-typography--lead"
37
+ | Muted => "basefn-typography--muted"
38
+ | Code => "basefn-typography--code"
39
+ | Unstyled => "basefn-typography--unstyled"
40
+ }
41
+ }
42
+
43
+ let alignToString = (align: align) => {
44
+ switch align {
45
+ | Left => "left"
46
+ | Center => "center"
47
+ | Right => "right"
48
+ | Justify => "justify"
49
+ }
50
+ }
51
+
52
+ @jsx.component
53
+ let make = (
54
+ ~text: ReactiveProp.t<string>,
55
+ ~variant: variant=P,
56
+ ~align: option<align>=?,
57
+ ~class: string="",
58
+ ~style=?,
59
+ ) => {
60
+ let variantClass = variantToClass(variant)
61
+
62
+ let class = {
63
+ let baseClass = "basefn-typography " ++ variantClass
64
+ let alignClass = switch align {
65
+ | Some(a) => " basefn-typography--" ++ alignToString(a)
66
+ | None => ""
67
+ }
68
+ let customClass = if class !== "" {
69
+ " " ++ class
70
+ } else {
71
+ ""
72
+ }
73
+ baseClass ++ alignClass ++ customClass
74
+ }
75
+
76
+ let renderText = text =>
77
+ switch text {
78
+ | ReactiveProp.Reactive(text) => Component.SignalText(text)
79
+ | ReactiveProp.Static(text) => Component.text(text)
80
+ }
81
+
82
+ switch variant {
83
+ | H1 => <h1 class ?style> {renderText(text)} </h1>
84
+ | H2 => <h2 class ?style> {renderText(text)} </h2>
85
+ | H3 => <h3 class ?style> {renderText(text)} </h3>
86
+ | H4 => <h4 class ?style> {renderText(text)} </h4>
87
+ | H5 => <h5 class ?style> {renderText(text)} </h5>
88
+ | H6 => <h6 class ?style> {renderText(text)} </h6>
89
+ | P => <p class ?style> {renderText(text)} </p>
90
+ | Small => <small class ?style> {renderText(text)} </small>
91
+ | Lead => <p class ?style> {renderText(text)} </p>
92
+ | Muted => <p class ?style> {renderText(text)} </p>
93
+ | Code => <code class ?style> {renderText(text)} </code>
94
+ | Unstyled => <div class ?style> {renderText(text)} </div>
95
+ }
96
+ }