@kestra-io/ui-libs 0.0.2 → 0.0.4

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.
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <Handle type="source" :position="sourcePosition" />
2
+ <Handle type="source" :position="sourcePosition"/>
3
3
  <basic-node
4
4
  :id="id"
5
5
  :data="data"
@@ -11,7 +11,7 @@
11
11
  @mouseleave="forwardEvent(EVENTS.MOUSE_LEAVE)"
12
12
  >
13
13
  <template #content>
14
- <execution-informations v-if="data.execution" :color="color" />
14
+ <execution-informations v-if="execution" :execution="execution" :task="data.node.task" :color="color"/>
15
15
  </template>
16
16
  <template #badge-button-before>
17
17
  <span
@@ -19,36 +19,48 @@
19
19
  class="rounded-button"
20
20
  :class="[`bg-${color}`]"
21
21
  @click="$emit(EVENTS.SHOW_LOGS, {id, taskRuns})"
22
+ data-bs-toggle="tooltip"
23
+ data-bs-placement="top"
24
+ :title="$t('show task logs')"
22
25
  >
23
- <TextBoxSearch class="button-icon" alt="Show logs" />
26
+ <TextBoxSearch class="button-icon" alt="Show logs"/>
24
27
  </span>
25
28
  <span
26
- v-if="!data.execution && !data.isReadOnly && data.isFlowable"
29
+ v-if="!execution && !data.isReadOnly && data.isFlowable"
27
30
  class="rounded-button"
28
31
  :class="[`bg-${color}`]"
29
32
  @click="$emit(EVENTS.ADD_ERROR, {task: data.node.task})"
33
+ data-bs-toggle="tooltip"
34
+ data-bs-placement="top"
35
+ :title="$t('add error handler')"
30
36
  >
31
- <InformationOutline class="button-icon" alt="Edit task" />
37
+ <AlertOutline class="button-icon" alt="Edit task"/>
32
38
  </span>
33
39
  <span
34
- v-if="!data.execution && !data.isReadOnly"
40
+ v-if="!execution && !data.isReadOnly"
35
41
  class="rounded-button"
36
42
  :class="[`bg-${color}`]"
37
43
  @click="$emit(EVENTS.EDIT, {task: data.node.task, section: SECTIONS.TASKS})"
44
+ data-bs-toggle="tooltip"
45
+ data-bs-placement="top"
46
+ :title="$t('edit')"
38
47
  >
39
- <Pencil class="button-icon" alt="Edit task" />
48
+ <Pencil class="button-icon" alt="Edit task"/>
40
49
  </span>
41
50
  <span
42
- v-if="!data.execution && !data.isReadOnly"
51
+ v-if="!execution && !data.isReadOnly"
43
52
  class="rounded-button"
44
53
  :class="[`bg-${color}`]"
45
54
  @click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TASKS})"
55
+ data-bs-toggle="tooltip"
56
+ data-bs-placement="top"
57
+ :title="$t('delete')"
46
58
  >
47
- <Delete class="button-icon" alt="Delete task" />
59
+ <Delete class="button-icon" alt="Delete task"/>
48
60
  </span>
49
61
  </template>
50
62
  </basic-node>
51
- <Handle type="target" :position="targetPosition" />
63
+ <Handle type="target" :position="targetPosition"/>
52
64
  </template>
53
65
 
54
66
  <script>
@@ -60,12 +72,29 @@
60
72
  import Pencil from "vue-material-design-icons/Pencil.vue";
61
73
  import Delete from "vue-material-design-icons/Delete.vue";
62
74
  import TextBoxSearch from "vue-material-design-icons/TextBoxSearch.vue";
63
- import InformationOutline from "vue-material-design-icons/InformationOutline.vue"
75
+ import AlertOutline from "vue-material-design-icons/AlertOutline.vue"
76
+ import {mapState} from "vuex";
77
+ import {Tooltip} from "bootstrap"
64
78
 
65
79
  export default {
66
80
  name: "Task",
67
81
  inheritAttrs: false,
82
+ mounted(){
83
+ const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
84
+ tooltipTriggerList.map(function (tooltipTriggerEl) {
85
+ return new Tooltip(tooltipTriggerEl)
86
+ })
87
+ },
88
+ beforeUnmount() {
89
+ document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
90
+ const tooltip = Tooltip.getInstance(el);
91
+ if (tooltip) {
92
+ tooltip.dispose();
93
+ }
94
+ });
95
+ },
68
96
  computed: {
97
+ ...mapState("execution", ["execution"]),
69
98
  SECTIONS() {
70
99
  return SECTIONS
71
100
  },
@@ -75,9 +104,6 @@
75
104
  color() {
76
105
  return this.data.color ?? "primary"
77
106
  },
78
- execution() {
79
- return this.data.execution
80
- },
81
107
  taskRunList() {
82
108
  return this.execution && this.execution.taskRunList ? this.execution.taskRunList : []
83
109
  },
@@ -136,7 +162,7 @@
136
162
  Handle,
137
163
  BasicNode,
138
164
  TextBoxSearch,
139
- InformationOutline
165
+ AlertOutline,
140
166
  },
141
167
  props: {
142
168
  data: {
@@ -163,6 +189,4 @@
163
189
  }
164
190
  }
165
191
  </script>
166
- <style scoped lang="scss">
167
- @import "../../scss/custom";
168
- </style>
192
+
@@ -9,18 +9,24 @@
9
9
  >
10
10
  <template #badge-button-before>
11
11
  <span
12
- v-if="!data.execution && !data.isReadOnly"
12
+ v-if="!execution && !data.isReadOnly"
13
13
  class="rounded-button"
14
14
  :class="[`bg-${color}`]"
15
15
  @click="$emit(EVENTS.EDIT, {task: data.node.trigger, section: SECTIONS.TRIGGERS})"
16
+ data-bs-toggle="tooltip"
17
+ data-bs-placement="top"
18
+ :title="$t('edit')"
16
19
  >
17
20
  <Pencil class="button-icon" alt="Edit task" />
18
21
  </span>
19
22
  <span
20
- v-if="!data.execution && !data.isReadOnly"
23
+ v-if="!execution && !data.isReadOnly"
21
24
  class="rounded-button"
22
25
  :class="[`bg-${color}`]"
23
26
  @click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TRIGGERS})"
27
+ data-bs-toggle="tooltip"
28
+ data-bs-placement="top"
29
+ :title="$t('delete')"
24
30
  >
25
31
  <Delete class="button-icon" alt="Delete task" />
26
32
  </span>
@@ -32,14 +38,33 @@
32
38
  <script>
33
39
  import BasicNode from "./BasicNode.vue";
34
40
  import {Handle} from "@vue-flow/core";
41
+ import {mapState} from "vuex";
35
42
  import {EVENTS, SECTIONS} from "../../utils/constants.js";
36
43
  import Pencil from "vue-material-design-icons/Pencil.vue";
37
44
  import Delete from "vue-material-design-icons/Delete.vue";
45
+ import {Tooltip} from "bootstrap";
38
46
 
39
47
  export default {
40
48
  name: "Task",
41
49
  inheritAttrs: false,
50
+ mounted(){
51
+ const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
52
+ this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
53
+ return new Tooltip(tooltipTriggerEl, {
54
+ trigger : "hover"
55
+ })
56
+ })
57
+ },
58
+ beforeUnmount() {
59
+ document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
60
+ const tooltip = Tooltip.getInstance(el);
61
+ if (tooltip) {
62
+ tooltip.dispose();
63
+ }
64
+ });
65
+ },
42
66
  computed: {
67
+ ...mapState("execution", ["execution"]),
43
68
  SECTIONS() {
44
69
  return SECTIONS
45
70
  },
@@ -0,0 +1,355 @@
1
+ <script setup>
2
+ import {
3
+ ref,
4
+ defineProps,
5
+ defineEmits, watch, nextTick,
6
+ onMounted
7
+ } from "vue";
8
+ import {
9
+ ClusterNode,
10
+ DotNode,
11
+ TaskNode,
12
+ TriggerNode,
13
+ CollapsedClusterNode,
14
+ EdgeNode,
15
+ } from "../index.js";
16
+ import {useVueFlow, VueFlow} from "@vue-flow/core";
17
+ import {ControlButton, Controls} from "@vue-flow/controls";
18
+ import SplitCellsVertical from "../../assets/icons/SplitCellsVertical.vue";
19
+ import SplitCellsHorizontal from "../../assets/icons/SplitCellsHorizontal.vue";
20
+ import {cssVariable} from "../../utils/global.js";
21
+ import {VueFlowUtils, YamlUtils} from "../../index.js";
22
+ import Utils from "../../utils/Utils.js";
23
+ import VueflowUtils from "../../utils/VueFlowUtils.js";
24
+ import {CLUSTER_UID_SEPARATOR} from "../../utils/constants.js";
25
+
26
+ const props = defineProps({
27
+ id: {
28
+ type: String,
29
+ required: true
30
+ },
31
+ isHorizontal: {
32
+ type: Boolean,
33
+ default: true,
34
+ },
35
+ isReadOnly: {
36
+ type: Boolean,
37
+ default: true,
38
+ },
39
+ isAllowedEdit: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
43
+ flowables: {
44
+ type: Array,
45
+ default: () => [],
46
+ },
47
+ source: {
48
+ type: String,
49
+ default: undefined,
50
+ required: true,
51
+ },
52
+ toggleOrientationButton: {
53
+ type: Boolean,
54
+ default: false,
55
+ },
56
+ flowGraph: {
57
+ type: Object,
58
+ required: true
59
+ },
60
+ flowId: {
61
+ type: String,
62
+ required: false,
63
+ default: undefined
64
+ },
65
+ namespace: {
66
+ type: String,
67
+ required: false,
68
+ default: undefined
69
+ },
70
+ });
71
+
72
+ const dragging = ref(false);
73
+ const lastPosition = ref(null)
74
+ const {getNodes, onNodeDrag, onNodeDragStart, onNodeDragStop, fitView, setElements} = useVueFlow({id: props.id});
75
+ const edgeReplacer = ref({});
76
+ const hiddenNodes = ref([]);
77
+ const collapsed = ref([]);
78
+ const clusterToNode = ref([])
79
+
80
+ const emit = defineEmits(
81
+ [
82
+ "edit",
83
+ "delete",
84
+ "open-link",
85
+ "show-logs",
86
+ "show-description",
87
+ "on-add-flowable-error",
88
+ "add-task",
89
+ "toggle-orientation",
90
+ "loading",
91
+ "swapped-task",
92
+ "message"
93
+ ]
94
+ )
95
+
96
+ onMounted( () => {
97
+ generateGraph();
98
+ })
99
+
100
+ watch(() => props.flowGraph, () => {
101
+ generateGraph();
102
+ })
103
+
104
+ const generateGraph = () => {
105
+ VueFlowUtils.cleanGraph(props.id);
106
+
107
+ nextTick(() => {
108
+ forwardEvent("loading", true);
109
+ const elements = VueflowUtils.generateGraph(
110
+ props.id,
111
+ props.flowId,
112
+ props.namespace,
113
+ props.flowGraph,
114
+ props.source,
115
+ hiddenNodes.value,
116
+ props.isHorizontal,
117
+ edgeReplacer.value,
118
+ collapsed.value,
119
+ clusterToNode.value,
120
+ props.isReadOnly,
121
+ props.isAllowedEdit,
122
+ flowables()
123
+ );
124
+ setElements(elements);
125
+ fitView();
126
+ forwardEvent("loading", false);
127
+ })
128
+ }
129
+
130
+ const forwardEvent = (type, payload) => {
131
+ emit(type, payload);
132
+ };
133
+
134
+ // Graph interactions functions
135
+ const onMouseOver = (node) => {
136
+ if (!dragging.value) {
137
+ VueFlowUtils.linkedElements(props.id, node.uid).forEach((n) => {
138
+ if (n.type === "task") {
139
+ n.style = {...n.style, outline: "0.5px solid " + cssVariable("--bs-gray-900")}
140
+ n.class = "rounded-3"
141
+ }
142
+ });
143
+ }
144
+
145
+ }
146
+
147
+ const onMouseLeave = () => {
148
+ resetNodesStyle();
149
+ }
150
+
151
+ const resetNodesStyle = () => {
152
+ getNodes.value.filter(n => n.type === "task" || n.type === "trigger")
153
+ .forEach(n => {
154
+ n.style = {...n.style, opacity: "1", outline: "none"}
155
+ n.class = ""
156
+ })
157
+ }
158
+
159
+ onNodeDragStart((e) => {
160
+ dragging.value = true;
161
+ resetNodesStyle();
162
+ e.node.style = {...e.node.style, zIndex: 1976}
163
+ lastPosition.value = e.node.position;
164
+ })
165
+
166
+ onNodeDragStop((e) => {
167
+ dragging.value = false;
168
+ if (checkIntersections(e.intersections, e.node) === null) {
169
+ const taskNode1 = e.node;
170
+ // check multiple intersection with task
171
+ const taskNode2 = e.intersections.find(n => n.type === "task");
172
+ if (taskNode2) {
173
+ try {
174
+ emit("swapped-task", YamlUtils.swapTasks(props.source, taskNode1.id, taskNode2.id))
175
+ } catch (e) {
176
+ emit("message", {
177
+ variant: "error",
178
+ title: "cannot swap tasks",
179
+ message: `${e.message}, ${e.messageOptions}`
180
+ });
181
+ taskNode1.position = lastPosition.value;
182
+ }
183
+ } else {
184
+ taskNode1.position = lastPosition.value;
185
+ }
186
+ } else {
187
+ e.node.position = lastPosition.value;
188
+ }
189
+ resetNodesStyle();
190
+ e.node.style = {...e.node.style, zIndex: 5}
191
+ lastPosition.value = null;
192
+ })
193
+
194
+ onNodeDrag((e) => {
195
+ resetNodesStyle();
196
+ getNodes.value.filter(n => n.id !== e.node.id).forEach(n => {
197
+ if (n.type === "trigger" || (n.type === "task" && YamlUtils.isParentChildrenRelation(props.source, n.id, e.node.id))) {
198
+ n.style = {...n.style, opacity: "0.5"}
199
+ } else {
200
+ n.style = {...n.style, opacity: "1"}
201
+ }
202
+ })
203
+ if (!checkIntersections(e.intersections, e.node) && e.intersections.filter(n => n.type === "task").length === 1) {
204
+ e.intersections.forEach(n => {
205
+ if (n.type === "task") {
206
+ n.style = {...n.style, outline: "0.5px solid " + cssVariable("--bs-primary")}
207
+ n.class = "rounded-3"
208
+ }
209
+ })
210
+ e.node.style = {...e.node.style, outline: "0.5px solid " + cssVariable("--bs-primary")}
211
+ e.node.class = "rounded-3"
212
+ }
213
+ })
214
+
215
+ const checkIntersections = (intersections, node) => {
216
+ const tasksMeet = intersections.filter(n => n.type === "task").map(n => n.id);
217
+ if (tasksMeet.length > 1) {
218
+ return "toomuchtaskerror";
219
+ }
220
+ if (tasksMeet.length === 1 && YamlUtils.isParentChildrenRelation(props.source, tasksMeet[0], node.id)) {
221
+ return "parentchildrenerror";
222
+ }
223
+ if (intersections.filter(n => n.type === "trigger").length > 0) {
224
+ return "triggererror";
225
+ }
226
+ return null;
227
+ }
228
+
229
+ const collapseCluster = (clusterUid, regenerate, recursive) => {
230
+
231
+ const cluster = props.flowGraph.clusters.find(cluster => cluster.cluster.uid === clusterUid)
232
+ const nodeId = clusterUid === "Triggers" ? "Triggers" : Utils.splitFirst(clusterUid, CLUSTER_UID_SEPARATOR);
233
+ collapsed.value = collapsed.value.concat([nodeId])
234
+
235
+ hiddenNodes.value = hiddenNodes.value.concat(cluster.nodes.filter(e => e !== nodeId || recursive));
236
+ if (clusterUid !== "Triggers") {
237
+ hiddenNodes.value = hiddenNodes.value.concat([cluster.cluster.uid])
238
+ edgeReplacer.value = {
239
+ ...edgeReplacer.value,
240
+ [cluster.cluster.uid]: nodeId,
241
+ [cluster.start]: nodeId,
242
+ [cluster.end]: nodeId
243
+ }
244
+
245
+ for (let child of cluster.nodes) {
246
+ if (props.flowGraph.clusters.map(cluster => cluster.cluster.uid).includes(child)) {
247
+ collapseCluster(child, false, true);
248
+ }
249
+ }
250
+ } else {
251
+ edgeReplacer.value = {
252
+ ...edgeReplacer.value,
253
+ [cluster.start]: nodeId,
254
+ [cluster.end]: nodeId
255
+ }
256
+ }
257
+
258
+ if (regenerate) {
259
+ generateGraph();
260
+ }
261
+ }
262
+
263
+ const expand = (taskId) => {
264
+ edgeReplacer.value = {}
265
+ hiddenNodes.value = []
266
+ clusterToNode.value = []
267
+ collapsed.value = collapsed.value.filter(n => n != taskId)
268
+
269
+ collapsed.value.forEach(n => collapseCluster(CLUSTER_UID_SEPARATOR + n, false, false))
270
+
271
+ generateGraph();
272
+ }
273
+
274
+ const flowables = () => {
275
+ return props.flowGraph && props.flowGraph.flowables ? props.flowGraph.flowables : [];
276
+ }
277
+ </script>
278
+ <template>
279
+ <VueFlow
280
+ :id="id"
281
+ :default-marker-color="cssVariable('--bs-cyan')"
282
+ fit-view-on-init
283
+ :nodes-draggable="false"
284
+ :nodes-connectable="false"
285
+ :elevate-nodes-on-select="false"
286
+ :elevate-edges-on-select="false"
287
+ >
288
+ <template #node-cluster="clusterProps">
289
+ <ClusterNode
290
+ v-bind="clusterProps"
291
+ @collapse="collapseCluster($event, true)"
292
+ />
293
+ </template>
294
+
295
+ <template #node-dot="dotProps">
296
+ <DotNode
297
+ v-bind="dotProps"
298
+ />
299
+ </template>
300
+
301
+ <template #node-task="taskProps">
302
+ <TaskNode
303
+ v-bind="taskProps"
304
+ @edit="forwardEvent('edit', $event)"
305
+ @delete="forwardEvent('delete', $event)"
306
+ @expand="expand($event)"
307
+ @open-link="forwardEvent('open-link', $event)"
308
+ @show-logs="forwardEvent('show-logs', $event)"
309
+ @show-description="forwardEvent('show-description', $event)"
310
+ @mouseover="onMouseOver($event)"
311
+ @mouseleave="onMouseLeave()"
312
+ @add-error="forwardEvent('on-add-flowable-error', $event)"
313
+ />
314
+ </template>
315
+
316
+ <template #node-trigger="triggerProps">
317
+ <TriggerNode
318
+ v-bind="triggerProps"
319
+ :is-read-only="isReadOnly"
320
+ :is-allowed-edit="isAllowedEdit"
321
+ @delete="forwardEvent('delete', $event)"
322
+ @edit="forwardEvent('edit', $event)"
323
+ />
324
+ </template>
325
+
326
+ <template #node-collapsedcluster="CollapsedProps">
327
+ <CollapsedClusterNode
328
+ v-bind="CollapsedProps"
329
+ @expand="expand($event)"
330
+ />
331
+ </template>
332
+
333
+ <template #edge-edge="EdgeProps">
334
+ <EdgeNode
335
+ v-bind="EdgeProps"
336
+ :yaml-source="source"
337
+ :flowables-ids="flowables"
338
+ @add-task="forwardEvent('add-task', $event)"
339
+ :is-read-only="isReadOnly"
340
+ :is-allowed-edit="isAllowedEdit"
341
+ />
342
+ </template>
343
+
344
+ <Controls :show-interactive="false">
345
+ <ControlButton @click="forwardEvent('toggle-orientation', $event)" v-if="toggleOrientationButton">
346
+ <SplitCellsVertical :size="48" v-if="!isHorizontal" />
347
+ <SplitCellsHorizontal v-if="isHorizontal" />
348
+ </ControlButton>
349
+ </Controls>
350
+ </VueFlow>
351
+ </template>
352
+
353
+ <style scoped lang="scss">
354
+
355
+ </style>
package/src/index.js CHANGED
@@ -1,8 +1,7 @@
1
- import "./scss/index.scss"
1
+ import YamlUtils from "./utils/YamlUtils.js";
2
+ import Utils from "./utils/Utils.js";
3
+ import VueFlowUtils from "./utils/VueFlowUtils.js";
2
4
 
3
- // import GraphUtils from "./utils/GraphUtils";
4
- // import YamlUtils from "./utils/YamlUtils";
5
- // import Utils from "./utils/Utils";
5
+ export {YamlUtils, Utils, VueFlowUtils};
6
6
 
7
7
  export * from "./components/index.js";
8
- // export { GraphUtils, YamlUtils, Utils };
@@ -1,3 +1,8 @@
1
+ // primary color
2
+ $primary: #8405FF !default;
3
+ $secondary: #C182FF !default;
4
+ $tertiary: #2F3342 !default;
5
+
1
6
  // color system
2
7
  $blue: #1761FD !default;
3
8
  $indigo: #8405FF !default;
@@ -11,22 +16,18 @@ $green: #03DABA !default;
11
16
  $teal: #03D87F !default;
12
17
  $cyan: #60C5FE !default;
13
18
 
14
- // primary color
15
- $primary: #8405FF !default;
16
- $secondary: #C182FF !default;
17
- $tertiary: #2F3342 !default;
18
19
 
19
20
  // gray
20
21
  $white: #FFF !default;
21
22
  $gray-100: #F5F5FF !default;
22
- $gray-200: #f1f5fa !default;
23
+ $gray-200: #F0F0FF !default;
23
24
  $gray-300: #E5E4F7 !default;
24
- $gray-400: #b6c2e4 !default;
25
- $gray-500: #8997bd !default;
26
- $gray-600: #7081b9 !default;
27
- $gray-700: #303e67 !default;
28
- $gray-800: #2c3652 !default;
29
- $gray-900: #1d2c48 !default;
25
+ $gray-400: #D1CFE9 !default;
26
+ $gray-500: #B8B6D9 !default;
27
+ $gray-600: #A6A4CA !default;
28
+ $gray-700: #9A8EB4 !default;
29
+ $gray-800: #7E719F !default;
30
+ $gray-900: #564A75 !default;
30
31
  $black: #26282D !default;
31
32
 
32
33
  $light: $gray-200 !default;
@@ -34,10 +35,21 @@ $dark: $gray-900 !default;
34
35
 
35
36
  // fonts
36
37
  $font-size-base: 1rem !default;
38
+ $font-size-xs: $font-size-base * .75;
39
+ $font-size-sm: $font-size-base * .875;
40
+ $font-size-lg: $font-size-base * 1.25;
41
+ $font-size-xl: $font-size-base * 1.375;
37
42
  $font-family-sans-serif: "Public Sans", sans-serif;
38
43
  $font-family-monospace: "Source Code Pro", monospace;
39
44
  $font-size-xs: $font-size-base * 0.75 !default;
40
45
 
46
+ $h1-font-size: $font-size-base * 3.375;
47
+ $h2-font-size: $font-size-base * 2.5;
48
+ $h3-font-size: $font-size-base * 2;
49
+ $h4-font-size: $font-size-base * 1.375;
50
+ $h5-font-size: $font-size-base * 1.25;
51
+ $h6-font-size: $font-size-base * 1.125;
52
+
41
53
  // border radius
42
54
  $border-radius: 0.25rem !default;
43
55
  $border-radius-lg: 0.5rem !default;
@@ -49,12 +61,16 @@ $spacer: 1rem !default;
49
61
 
50
62
  // body
51
63
  $body-color: $gray-800 !default;
64
+ $body-tertiary-color: #FFFFFF;
65
+ $body-tertiary-bg: #785EEA;
52
66
  $border-color: $gray-300 !default;
53
67
  $body-bg: $gray-100 !default;
54
68
  $card-bg: $white !default;
55
69
  $input-bg: $white !default;
56
70
 
71
+ // link
57
72
  $link-color: $primary !default;
73
+ $link-decoration: none;
58
74
 
59
75
  // border radius
60
76
  $border-radius: .25rem !default;
@@ -65,6 +81,45 @@ $box-shadow-sm: 0 .125rem .25rem rgba($black, .075);
65
81
  $box-shadow: 0 .5rem 1rem rgba($black, .15);
66
82
  $box-shadow-lg: 0 1rem 3rem rgba($black, .175);
67
83
 
84
+ // button
85
+ $btn-font-size-lg: 18px;
86
+
87
+ // grid
88
+ $grid-gutter-width: 1.75rem;
89
+
90
+ // nav
91
+ $nav-pills-border-radius: 50rem;
92
+
93
+ // accordion
94
+ $accordion-icon-color: $white;
95
+ $accordion-icon-active-color: $white;
96
+
97
+ // purples
98
+ $purple-1: #382369;
99
+ $purple-2: #FBC7F4;
100
+ $purple-3: #9580EE;
101
+ $purple-4: linear-gradient(160.34deg, rgba(130, 0, 255, 0.12) 5.3%, rgba(130, 0, 255, 0) 75.43%), #201838;
102
+ $purple-5: #362762;
103
+ $purple-6: #6113BC;
104
+ $purple-7: #1A1223;
105
+ $purple-8: #EEEDFF;
106
+ $purple-9: 0px 12.972px 39.7269px rgba(90, 0, 176, 0.1);
107
+ $purple-10: #150E1C;
108
+ $purple-11: #332C3B;
109
+ $purple-12: #432A71;
110
+ $purple-16: #281A35;
111
+ $purple-19: conic-gradient(from 90deg at 50% 50%, #BE79FF 0deg, #7136F6 360deg);
112
+ $purple-20: #291E39;
113
+ $purple-21: #A42DCD;
114
+ $purple-22: #FCF7FE;
115
+ $purple-23: #EDE8F3;
116
+ $purple-24: #15023F;
117
+ $purple-26: #DCCDEB;
118
+ $purple-27: #8200FF;
119
+ $purple-28: #2D313E;
120
+ $purple-29: #F1F5FF;
121
+ $purple-30: rgba(255, 255, 255, 0.1);
122
+
68
123
  // boostrap flags
69
124
  $enable-reduced-motion: false;
70
125
 
@@ -93,6 +148,8 @@ $element-colors: (
93
148
  ),
94
149
  );
95
150
 
151
+ $baseline-max-width: 730px;
152
+
96
153
  // bootstrap
97
154
  @import "bootstrap/scss/functions";
98
155
  @import "bootstrap/scss/mixins";