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,49 @@
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
+ import * as Basefn__Icon from "./Basefn__Icon.res.mjs";
7
+ import * as Basefn__Theme from "../styles/Basefn__Theme.res.mjs";
8
+ import * as Basefn__Button from "./Basefn__Button.res.mjs";
9
+ import * as Basefn__Tooltip from "./Basefn__Tooltip.res.mjs";
10
+
11
+ import './Basefn__ThemeToggle.css'
12
+ ;
13
+
14
+ function Basefn__ThemeToggle(props) {
15
+ let handleClick = e => {
16
+ Basefn__Dom.preventDefault(e);
17
+ Basefn__Dom.stopPropagation(e);
18
+ Basefn__Theme.toggleTheme();
19
+ };
20
+ let icon = Xote.Computed.make(() => {
21
+ let match = Xote.Signal.get(Basefn__Theme.currentTheme);
22
+ if (match === "Light") {
23
+ return [Xote__JSX.jsx(Basefn__Icon.make, {
24
+ name: "Sun"
25
+ })];
26
+ } else {
27
+ return [Xote__JSX.jsx(Basefn__Icon.make, {
28
+ name: "Moon"
29
+ })];
30
+ }
31
+ }, undefined);
32
+ return Xote__JSX.jsx(Basefn__Tooltip.make, {
33
+ content: "Toggle theme",
34
+ position: "Bottom",
35
+ children: Xote__JSX.jsx(Basefn__Button.make, {
36
+ children: Xote.Component.signalFragment(icon),
37
+ class: Xote.ReactiveProp.$$static("basefn-theme-toggle"),
38
+ onClick: handleClick,
39
+ variant: "Ghost"
40
+ })
41
+ });
42
+ }
43
+
44
+ let make = Basefn__ThemeToggle;
45
+
46
+ export {
47
+ make,
48
+ }
49
+ /* Not a pure module */
@@ -0,0 +1,144 @@
1
+ .basefn-timeline {
2
+ position: relative;
3
+ }
4
+
5
+ .basefn-timeline--vertical {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 2rem;
9
+ }
10
+
11
+ .basefn-timeline--horizontal {
12
+ display: flex;
13
+ gap: 2rem;
14
+ overflow-x: auto;
15
+ }
16
+
17
+ .basefn-timeline__item {
18
+ position: relative;
19
+ display: flex;
20
+ gap: 1rem;
21
+ }
22
+
23
+ .basefn-timeline--vertical .basefn-timeline__item {
24
+ flex-direction: row;
25
+ }
26
+
27
+ .basefn-timeline--horizontal .basefn-timeline__item {
28
+ flex-direction: column;
29
+ min-width: 200px;
30
+ }
31
+
32
+ .basefn-timeline__marker-wrapper {
33
+ position: relative;
34
+ display: flex;
35
+ flex-direction: column;
36
+ align-items: center;
37
+ flex-shrink: 0;
38
+ }
39
+
40
+ .basefn-timeline--horizontal .basefn-timeline__marker-wrapper {
41
+ flex-direction: row;
42
+ }
43
+
44
+ .basefn-timeline__marker {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ width: 2.5rem;
49
+ height: 2.5rem;
50
+ border-radius: 50%;
51
+ background-color: #e5e7eb;
52
+ color: #6b7280;
53
+ font-weight: 600;
54
+ font-size: 0.875rem;
55
+ z-index: 2;
56
+ flex-shrink: 0;
57
+ }
58
+
59
+ .basefn-timeline__marker--default {
60
+ background-color: #e5e7eb;
61
+ color: #6b7280;
62
+ }
63
+
64
+ .basefn-timeline__marker--primary {
65
+ background-color: #3b82f6;
66
+ color: white;
67
+ }
68
+
69
+ .basefn-timeline__marker--success {
70
+ background-color: #10b981;
71
+ color: white;
72
+ }
73
+
74
+ .basefn-timeline__marker--warning {
75
+ background-color: #f59e0b;
76
+ color: white;
77
+ }
78
+
79
+ .basefn-timeline__marker--error {
80
+ background-color: #ef4444;
81
+ color: white;
82
+ }
83
+
84
+ .basefn-timeline__connector {
85
+ position: absolute;
86
+ background-color: #e5e7eb;
87
+ z-index: 1;
88
+ }
89
+
90
+ .basefn-timeline--vertical .basefn-timeline__connector {
91
+ width: 2px;
92
+ top: 2.5rem;
93
+ bottom: -2rem;
94
+ left: 1.25rem;
95
+ }
96
+
97
+ .basefn-timeline--vertical .basefn-timeline__item:last-child .basefn-timeline__connector {
98
+ display: none;
99
+ }
100
+
101
+ .basefn-timeline--horizontal .basefn-timeline__connector {
102
+ height: 2px;
103
+ left: 2.5rem;
104
+ right: -2rem;
105
+ top: 1.25rem;
106
+ }
107
+
108
+ .basefn-timeline--horizontal .basefn-timeline__item:last-child .basefn-timeline__connector {
109
+ display: none;
110
+ }
111
+
112
+ .basefn-timeline__content {
113
+ flex: 1;
114
+ padding-top: 0.25rem;
115
+ }
116
+
117
+ .basefn-timeline--horizontal .basefn-timeline__content {
118
+ padding-top: 0;
119
+ }
120
+
121
+ .basefn-timeline__title {
122
+ font-weight: 600;
123
+ font-size: 0.9375rem;
124
+ color: #1f2937;
125
+ margin-bottom: 0.25rem;
126
+ }
127
+
128
+ .basefn-timeline__timestamp {
129
+ font-size: 0.75rem;
130
+ color: #6b7280;
131
+ margin-bottom: 0.5rem;
132
+ }
133
+
134
+ .basefn-timeline__description {
135
+ font-size: 0.875rem;
136
+ color: #4b5563;
137
+ line-height: 1.5;
138
+ }
139
+
140
+ /* Optional dot variant */
141
+ .basefn-timeline__marker--dot {
142
+ width: 0.75rem;
143
+ height: 0.75rem;
144
+ }
@@ -0,0 +1,70 @@
1
+ %%raw(`import './Basefn__Timeline.css'`)
2
+
3
+ open Xote
4
+
5
+ type orientation = Vertical | Horizontal
6
+
7
+ type variant = Default | Primary | Success | Warning | Error
8
+
9
+ let variantToString = (variant: variant) => {
10
+ switch variant {
11
+ | Default => "default"
12
+ | Primary => "primary"
13
+ | Success => "success"
14
+ | Warning => "warning"
15
+ | Error => "error"
16
+ }
17
+ }
18
+
19
+ type timelineItem = {
20
+ title: string,
21
+ timestamp: option<string>,
22
+ description: option<string>,
23
+ variant: variant,
24
+ icon: option<string>,
25
+ }
26
+
27
+ @jsx.component
28
+ let make = (~items: array<timelineItem>, ~orientation: orientation=Vertical) => {
29
+ let getTimelineClass = () => {
30
+ let orientationClass = switch orientation {
31
+ | Vertical => "basefn-timeline--vertical"
32
+ | Horizontal => "basefn-timeline--horizontal"
33
+ }
34
+ "basefn-timeline " ++ orientationClass
35
+ }
36
+
37
+ let getMarkerClass = (variant: variant) => {
38
+ let variantClass = "basefn-timeline__marker--" ++ variantToString(variant)
39
+ "basefn-timeline__marker " ++ variantClass
40
+ }
41
+
42
+ <div class={getTimelineClass()}>
43
+ {items
44
+ ->Array.mapWithIndex((item, index) => {
45
+ <div key={Int.toString(index)} class="basefn-timeline__item">
46
+ <div class="basefn-timeline__marker-wrapper">
47
+ <div class={getMarkerClass(item.variant)}>
48
+ {switch item.icon {
49
+ | Some(iconText) => Component.text(iconText)
50
+ | None => Component.text(Int.toString(index + 1))
51
+ }}
52
+ </div>
53
+ <div class="basefn-timeline__connector" />
54
+ </div>
55
+ <div class="basefn-timeline__content">
56
+ <div class="basefn-timeline__title"> {Component.text(item.title)} </div>
57
+ {switch item.timestamp {
58
+ | Some(time) => <div class="basefn-timeline__timestamp"> {Component.text(time)} </div>
59
+ | None => <> </>
60
+ }}
61
+ {switch item.description {
62
+ | Some(desc) => <div class="basefn-timeline__description"> {Component.text(desc)} </div>
63
+ | None => <> </>
64
+ }}
65
+ </div>
66
+ </div>
67
+ })
68
+ ->Component.fragment}
69
+ </div>
70
+ }
@@ -0,0 +1,86 @@
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__Timeline.css'
7
+ ;
8
+
9
+ function variantToString(variant) {
10
+ switch (variant) {
11
+ case "Default" :
12
+ return "default";
13
+ case "Primary" :
14
+ return "primary";
15
+ case "Success" :
16
+ return "success";
17
+ case "Warning" :
18
+ return "warning";
19
+ case "Error" :
20
+ return "error";
21
+ }
22
+ }
23
+
24
+ function Basefn__Timeline(props) {
25
+ let __orientation = props.orientation;
26
+ let orientation = __orientation !== undefined ? __orientation : "Vertical";
27
+ let getTimelineClass = () => {
28
+ let orientationClass;
29
+ orientationClass = orientation === "Vertical" ? "basefn-timeline--vertical" : "basefn-timeline--horizontal";
30
+ return "basefn-timeline " + orientationClass;
31
+ };
32
+ let getMarkerClass = variant => {
33
+ let variantClass = "basefn-timeline__marker--" + variantToString(variant);
34
+ return "basefn-timeline__marker " + variantClass;
35
+ };
36
+ return Xote__JSX.Elements.jsx("div", {
37
+ class: getTimelineClass(),
38
+ children: Xote.Component.fragment(props.items.map((item, index) => {
39
+ let iconText = item.icon;
40
+ let time = item.timestamp;
41
+ let desc = item.description;
42
+ return Xote__JSX.Elements.jsxsKeyed("div", {
43
+ class: "basefn-timeline__item",
44
+ children: Xote__JSX.array([
45
+ Xote__JSX.Elements.jsxs("div", {
46
+ class: "basefn-timeline__marker-wrapper",
47
+ children: Xote__JSX.array([
48
+ Xote__JSX.Elements.jsx("div", {
49
+ class: getMarkerClass(item.variant),
50
+ children: iconText !== undefined ? Xote.Component.text(iconText) : Xote.Component.text((index + 1 | 0).toString())
51
+ }),
52
+ Xote__JSX.Elements.jsx("div", {
53
+ class: "basefn-timeline__connector"
54
+ })
55
+ ])
56
+ }),
57
+ Xote__JSX.Elements.jsxs("div", {
58
+ class: "basefn-timeline__content",
59
+ children: Xote__JSX.array([
60
+ Xote__JSX.Elements.jsx("div", {
61
+ class: "basefn-timeline__title",
62
+ children: Xote.Component.text(item.title)
63
+ }),
64
+ time !== undefined ? Xote__JSX.Elements.jsx("div", {
65
+ class: "basefn-timeline__timestamp",
66
+ children: Xote.Component.text(time)
67
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
68
+ desc !== undefined ? Xote__JSX.Elements.jsx("div", {
69
+ class: "basefn-timeline__description",
70
+ children: Xote.Component.text(desc)
71
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {})
72
+ ])
73
+ })
74
+ ])
75
+ }, index.toString(), undefined);
76
+ }))
77
+ });
78
+ }
79
+
80
+ let make = Basefn__Timeline;
81
+
82
+ export {
83
+ variantToString,
84
+ make,
85
+ }
86
+ /* Not a pure module */
@@ -0,0 +1,100 @@
1
+ .basefn-toast-container {
2
+ position: fixed;
3
+ z-index: 9999;
4
+ pointer-events: none;
5
+ }
6
+
7
+ .basefn-toast-container--top-right {
8
+ top: 1rem;
9
+ right: 1rem;
10
+ }
11
+
12
+ .basefn-toast-container--top-left {
13
+ top: 1rem;
14
+ left: 1rem;
15
+ }
16
+
17
+ .basefn-toast-container--bottom-right {
18
+ bottom: 1rem;
19
+ right: 1rem;
20
+ }
21
+
22
+ .basefn-toast-container--bottom-left {
23
+ bottom: 1rem;
24
+ left: 1rem;
25
+ }
26
+
27
+ .basefn-toast {
28
+ display: flex;
29
+ align-items: flex-start;
30
+ gap: 0.75rem;
31
+ min-width: 300px;
32
+ max-width: 400px;
33
+ padding: 1rem;
34
+ margin-bottom: 0.75rem;
35
+ background: white;
36
+ border-radius: 0.5rem;
37
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
38
+ pointer-events: auto;
39
+ border-left: 4px solid;
40
+ animation: basefn-toast-slide-in 0.3s ease-out;
41
+ }
42
+
43
+ .basefn-toast--info {
44
+ border-left-color: #3b82f6;
45
+ }
46
+
47
+ .basefn-toast--success {
48
+ border-left-color: #10b981;
49
+ }
50
+
51
+ .basefn-toast--warning {
52
+ border-left-color: #f59e0b;
53
+ }
54
+
55
+ .basefn-toast--error {
56
+ border-left-color: #ef4444;
57
+ }
58
+
59
+ .basefn-toast__content {
60
+ flex: 1;
61
+ }
62
+
63
+ .basefn-toast__title {
64
+ font-weight: 600;
65
+ font-size: 0.875rem;
66
+ color: #1f2937;
67
+ margin-bottom: 0.25rem;
68
+ }
69
+
70
+ .basefn-toast__message {
71
+ font-size: 0.875rem;
72
+ color: #6b7280;
73
+ line-height: 1.4;
74
+ }
75
+
76
+ .basefn-toast__close {
77
+ background: none;
78
+ border: none;
79
+ font-size: 1.25rem;
80
+ color: #9ca3af;
81
+ cursor: pointer;
82
+ padding: 0;
83
+ line-height: 1;
84
+ transition: color 0.2s;
85
+ }
86
+
87
+ .basefn-toast__close:hover {
88
+ color: #6b7280;
89
+ }
90
+
91
+ @keyframes basefn-toast-slide-in {
92
+ from {
93
+ opacity: 0;
94
+ transform: translateX(100%);
95
+ }
96
+ to {
97
+ opacity: 1;
98
+ transform: translateX(0);
99
+ }
100
+ }
@@ -0,0 +1,92 @@
1
+ %%raw(`import './Basefn__Toast.css'`)
2
+
3
+ open Xote
4
+
5
+ type variant = Info | Success | Warning | Error
6
+
7
+ type position = TopRight | TopLeft | BottomRight | BottomLeft
8
+
9
+ let variantToString = (variant: variant) => {
10
+ switch variant {
11
+ | Info => "info"
12
+ | Success => "success"
13
+ | Warning => "warning"
14
+ | Error => "error"
15
+ }
16
+ }
17
+
18
+ let positionToString = (position: position) => {
19
+ switch position {
20
+ | TopRight => "top-right"
21
+ | TopLeft => "top-left"
22
+ | BottomRight => "bottom-right"
23
+ | BottomLeft => "bottom-left"
24
+ }
25
+ }
26
+
27
+ @jsx.component
28
+ let make = (
29
+ ~title: option<string>=?,
30
+ ~message: string,
31
+ ~variant: variant=Info,
32
+ ~position: position=TopRight,
33
+ ~isVisible: Signal.t<bool>,
34
+ ~onClose: unit => unit,
35
+ ~autoDismiss: bool=true,
36
+ ~duration: int=3000,
37
+ ) => {
38
+ // Auto dismiss logic
39
+ let _ = Effect.run(() => {
40
+ if Signal.get(isVisible) && autoDismiss {
41
+ let timeoutId = setTimeout(() => {
42
+ Signal.set(isVisible, false)
43
+ onClose()
44
+ }, duration)
45
+ Some(() => clearTimeout(timeoutId))
46
+ } else {
47
+ None
48
+ }
49
+ })
50
+
51
+ let getToastClass = () => {
52
+ let variantClass = "basefn-toast--" ++ variantToString(variant)
53
+ "basefn-toast " ++ variantClass
54
+ }
55
+
56
+ let getContainerClass = () => {
57
+ let posClass = "basefn-toast-container--" ++ positionToString(position)
58
+ "basefn-toast-container " ++ posClass
59
+ }
60
+
61
+ let content = Computed.make(() => {
62
+ if Signal.get(isVisible) {
63
+ [
64
+ <div class={getContainerClass()}>
65
+ <div class={getToastClass()}>
66
+ <div class="basefn-toast__content">
67
+ {switch title {
68
+ | Some(titleText) =>
69
+ <div class="basefn-toast__title"> {Component.text(titleText)} </div>
70
+ | None => <> </>
71
+ }}
72
+ <div class="basefn-toast__message"> {Component.text(message)} </div>
73
+ </div>
74
+ <button
75
+ class="basefn-toast__close"
76
+ onClick={_ => {
77
+ Signal.set(isVisible, false)
78
+ onClose()
79
+ }}
80
+ >
81
+ {Component.text("\u00d7")}
82
+ </button>
83
+ </div>
84
+ </div>,
85
+ ]
86
+ } else {
87
+ []
88
+ }
89
+ })
90
+
91
+ Component.signalFragment(content)
92
+ }
@@ -0,0 +1,112 @@
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__Toast.css'
7
+ ;
8
+
9
+ function variantToString(variant) {
10
+ switch (variant) {
11
+ case "Info" :
12
+ return "info";
13
+ case "Success" :
14
+ return "success";
15
+ case "Warning" :
16
+ return "warning";
17
+ case "Error" :
18
+ return "error";
19
+ }
20
+ }
21
+
22
+ function positionToString(position) {
23
+ switch (position) {
24
+ case "TopRight" :
25
+ return "top-right";
26
+ case "TopLeft" :
27
+ return "top-left";
28
+ case "BottomRight" :
29
+ return "bottom-right";
30
+ case "BottomLeft" :
31
+ return "bottom-left";
32
+ }
33
+ }
34
+
35
+ function Basefn__Toast(props) {
36
+ let __duration = props.duration;
37
+ let __autoDismiss = props.autoDismiss;
38
+ let onClose = props.onClose;
39
+ let isVisible = props.isVisible;
40
+ let __position = props.position;
41
+ let __variant = props.variant;
42
+ let message = props.message;
43
+ let title = props.title;
44
+ let variant = __variant !== undefined ? __variant : "Info";
45
+ let position = __position !== undefined ? __position : "TopRight";
46
+ let autoDismiss = __autoDismiss !== undefined ? __autoDismiss : true;
47
+ let duration = __duration !== undefined ? __duration : 3000;
48
+ Xote.Effect.run(() => {
49
+ if (!(Xote.Signal.get(isVisible) && autoDismiss)) {
50
+ return;
51
+ }
52
+ let timeoutId = setTimeout(() => {
53
+ Xote.Signal.set(isVisible, false);
54
+ onClose();
55
+ }, duration);
56
+ return () => {
57
+ clearTimeout(timeoutId);
58
+ };
59
+ }, undefined);
60
+ let getToastClass = () => {
61
+ let variantClass = "basefn-toast--" + variantToString(variant);
62
+ return "basefn-toast " + variantClass;
63
+ };
64
+ let getContainerClass = () => {
65
+ let posClass = "basefn-toast-container--" + positionToString(position);
66
+ return "basefn-toast-container " + posClass;
67
+ };
68
+ return Xote.Component.signalFragment(Xote.Computed.make(() => {
69
+ if (Xote.Signal.get(isVisible)) {
70
+ return [Xote__JSX.Elements.jsx("div", {
71
+ class: getContainerClass(),
72
+ children: Xote__JSX.Elements.jsxs("div", {
73
+ class: getToastClass(),
74
+ children: Xote__JSX.array([
75
+ Xote__JSX.Elements.jsxs("div", {
76
+ class: "basefn-toast__content",
77
+ children: Xote__JSX.array([
78
+ title !== undefined ? Xote__JSX.Elements.jsx("div", {
79
+ class: "basefn-toast__title",
80
+ children: Xote.Component.text(title)
81
+ }) : Xote__JSX.jsx(Xote__JSX.jsxFragment, {}),
82
+ Xote__JSX.Elements.jsx("div", {
83
+ class: "basefn-toast__message",
84
+ children: Xote.Component.text(message)
85
+ })
86
+ ])
87
+ }),
88
+ Xote__JSX.Elements.jsx("button", {
89
+ class: "basefn-toast__close",
90
+ onClick: param => {
91
+ Xote.Signal.set(isVisible, false);
92
+ onClose();
93
+ },
94
+ children: Xote.Component.text("\u00d7")
95
+ })
96
+ ])
97
+ })
98
+ })];
99
+ } else {
100
+ return [];
101
+ }
102
+ }, undefined));
103
+ }
104
+
105
+ let make = Basefn__Toast;
106
+
107
+ export {
108
+ variantToString,
109
+ positionToString,
110
+ make,
111
+ }
112
+ /* Not a pure module */