@meshxdata/fops 0.1.55 → 0.1.57

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 (34) hide show
  1. package/CHANGELOG.md +4 -4
  2. package/package.json +1 -2
  3. package/src/commands/index.js +2 -0
  4. package/src/commands/k3s-cmd.js +124 -0
  5. package/src/commands/lifecycle.js +7 -0
  6. package/src/plugins/builtins/docker-compose.js +17 -35
  7. package/src/plugins/bundled/fops-plugin-azure/lib/azure-openai.js +0 -3
  8. package/src/plugins/bundled/fops-plugin-azure/lib/commands/vm-cmds.js +5 -2
  9. package/src/plugins/bundled/fops-plugin-cloud/api.js +14 -0
  10. package/src/project.js +12 -7
  11. package/src/plugins/bundled/fops-plugin-cloud/ui/postcss.config.cjs +0 -5
  12. package/src/plugins/bundled/fops-plugin-cloud/ui/src/App.jsx +0 -32
  13. package/src/plugins/bundled/fops-plugin-cloud/ui/src/api/client.js +0 -114
  14. package/src/plugins/bundled/fops-plugin-cloud/ui/src/api/queries.js +0 -111
  15. package/src/plugins/bundled/fops-plugin-cloud/ui/src/components/LogPanel.jsx +0 -162
  16. package/src/plugins/bundled/fops-plugin-cloud/ui/src/components/ThemeToggle.jsx +0 -46
  17. package/src/plugins/bundled/fops-plugin-cloud/ui/src/css/additional-styles/utility-patterns.css +0 -147
  18. package/src/plugins/bundled/fops-plugin-cloud/ui/src/css/style.css +0 -138
  19. package/src/plugins/bundled/fops-plugin-cloud/ui/src/favicon.svg +0 -15
  20. package/src/plugins/bundled/fops-plugin-cloud/ui/src/lib/utils.ts +0 -19
  21. package/src/plugins/bundled/fops-plugin-cloud/ui/src/main.jsx +0 -25
  22. package/src/plugins/bundled/fops-plugin-cloud/ui/src/pages/Audit.jsx +0 -164
  23. package/src/plugins/bundled/fops-plugin-cloud/ui/src/pages/Costs.jsx +0 -305
  24. package/src/plugins/bundled/fops-plugin-cloud/ui/src/pages/CreateResource.jsx +0 -285
  25. package/src/plugins/bundled/fops-plugin-cloud/ui/src/pages/Fleet.jsx +0 -307
  26. package/src/plugins/bundled/fops-plugin-cloud/ui/src/pages/Resources.jsx +0 -229
  27. package/src/plugins/bundled/fops-plugin-cloud/ui/src/partials/Header.jsx +0 -132
  28. package/src/plugins/bundled/fops-plugin-cloud/ui/src/partials/Sidebar.jsx +0 -174
  29. package/src/plugins/bundled/fops-plugin-cloud/ui/src/partials/SidebarLinkGroup.jsx +0 -21
  30. package/src/plugins/bundled/fops-plugin-cloud/ui/src/utils/AuthContext.jsx +0 -170
  31. package/src/plugins/bundled/fops-plugin-cloud/ui/src/utils/Info.jsx +0 -49
  32. package/src/plugins/bundled/fops-plugin-cloud/ui/src/utils/ThemeContext.jsx +0 -37
  33. package/src/plugins/bundled/fops-plugin-cloud/ui/src/utils/Transition.jsx +0 -116
  34. package/src/plugins/bundled/fops-plugin-cloud/ui/src/utils/Utils.js +0 -63
@@ -1,162 +0,0 @@
1
- import React, { useRef, useEffect, useMemo } from "react";
2
-
3
- // ANSI color code → Tailwind class mapping
4
- const ANSI_COLORS = {
5
- "30": "text-gray-900", "31": "text-red-400", "32": "text-green-400",
6
- "33": "text-yellow-400", "34": "text-blue-400", "35": "text-purple-400",
7
- "36": "text-cyan-400", "37": "text-gray-200", "90": "text-gray-500",
8
- "91": "text-red-300", "92": "text-green-300", "93": "text-yellow-300",
9
- "94": "text-blue-300", "95": "text-purple-300", "96": "text-cyan-300",
10
- "97": "text-white",
11
- };
12
-
13
- const ANSI_RE = /\x1b\[([0-9;]*)m/g;
14
-
15
- function parseAnsi(str) {
16
- const segments = [];
17
- let lastIndex = 0;
18
- let currentClass = "text-gray-300";
19
- ANSI_RE.lastIndex = 0;
20
- let match;
21
- while ((match = ANSI_RE.exec(str)) !== null) {
22
- if (match.index > lastIndex) {
23
- segments.push({ text: str.slice(lastIndex, match.index), className: currentClass });
24
- }
25
- const codes = match[1].split(";");
26
- for (const code of codes) {
27
- if (code === "0" || code === "") currentClass = "text-gray-300";
28
- else if (code === "1") currentClass = currentClass + " font-bold";
29
- else if (ANSI_COLORS[code]) currentClass = ANSI_COLORS[code];
30
- }
31
- lastIndex = ANSI_RE.lastIndex;
32
- }
33
- if (lastIndex < str.length) {
34
- segments.push({ text: str.slice(lastIndex), className: currentClass });
35
- }
36
- return segments;
37
- }
38
-
39
- function stripAnsi(s) {
40
- return s.replace(/\x1b\[[0-9;]*m/g, "");
41
- }
42
-
43
- // Provisioning phases detected from section headers in the log stream
44
- const PHASES = [
45
- { id: "infra", label: "Infrastructure", match: "Infrastructure" },
46
- { id: "firewall", label: "Firewall", match: "Firewall" },
47
- { id: "security", label: "Security", match: "Security" },
48
- { id: "connect", label: "Connectivity", match: "Connectivity" },
49
- { id: "services", label: "Services", match: "Services" },
50
- { id: "post", label: "Post-start", match: "Post-start" },
51
- ];
52
-
53
- function detectPhases(lines) {
54
- const reached = new Set();
55
- let current = null;
56
-
57
- for (const line of lines) {
58
- const clean = stripAnsi(line.text);
59
-
60
- // Detect section headers: "─ Infrastructure ─" or "── Post-start ──"
61
- for (const phase of PHASES) {
62
- if (clean.includes(phase.match)) {
63
- reached.add(phase.id);
64
- current = phase.id;
65
- }
66
- }
67
-
68
- // "Reconciliation complete" means all reconciliation phases done
69
- if (clean.includes("Reconciliation complete")) {
70
- reached.add("post");
71
- current = "post";
72
- }
73
- }
74
-
75
- return { reached, current };
76
- }
77
-
78
- export default function LogPanel({ lines = [], title = "Output", isDone = false, showPhases = false }) {
79
- const endRef = useRef(null);
80
-
81
- useEffect(() => {
82
- endRef.current?.scrollIntoView({ behavior: "smooth" });
83
- }, [lines.length]);
84
-
85
- const { reached, current } = useMemo(() => detectPhases(lines), [lines]);
86
-
87
- const completedChecks = useMemo(
88
- () => lines.filter((l) => stripAnsi(l.text).includes("✓")).length,
89
- [lines],
90
- );
91
-
92
- const phaseIndex = PHASES.findIndex((p) => p.id === current);
93
- const progressPercent = isDone ? 100 : Math.min(95, Math.floor(((phaseIndex + 1) / PHASES.length) * 100));
94
-
95
- if (lines.length === 0) return null;
96
-
97
- return (
98
- <div className="mt-6">
99
- {/* Phase steps */}
100
- {showPhases && (
101
- <div className="mb-5">
102
- <div className="flex items-center gap-1">
103
- {PHASES.map((phase, i) => {
104
- const done = isDone || (reached.has(phase.id) && current !== phase.id);
105
- const active = !isDone && current === phase.id;
106
- return (
107
- <React.Fragment key={phase.id}>
108
- <div className="flex items-center gap-1.5">
109
- <div className={`w-6 h-6 rounded-full flex items-center justify-center text-[10px] font-bold shrink-0 ${
110
- done ? "bg-green-500 text-white"
111
- : active ? "bg-violet-500 text-white"
112
- : "bg-gray-200 dark:bg-gray-700 text-gray-400 dark:text-gray-500"
113
- }`}>
114
- {done ? "✓" : i + 1}
115
- </div>
116
- <span className={`text-xs font-medium whitespace-nowrap hidden sm:inline ${
117
- done ? "text-green-600 dark:text-green-400"
118
- : active ? "text-gray-800 dark:text-gray-100"
119
- : "text-gray-400 dark:text-gray-500"
120
- }`}>
121
- {phase.label}
122
- </span>
123
- </div>
124
- {i < PHASES.length - 1 && (
125
- <div className={`flex-1 h-px min-w-4 ${done ? "bg-green-500/40" : "bg-gray-200 dark:bg-gray-700"}`} />
126
- )}
127
- </React.Fragment>
128
- );
129
- })}
130
- </div>
131
- </div>
132
- )}
133
-
134
- {/* Header + progress */}
135
- <div className="flex items-center justify-between mb-2">
136
- <h3 className="text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase">{title}</h3>
137
- <span className="text-xs text-gray-500 dark:text-gray-400 font-mono">
138
- {isDone ? "Complete" : `${completedChecks} checks — ${progressPercent}%`}
139
- </span>
140
- </div>
141
-
142
- <div className="w-full h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full mb-3 overflow-hidden">
143
- <div
144
- className={`h-full rounded-full transition-all duration-500 ease-out ${isDone ? "bg-green-500" : "bg-violet-500"}`}
145
- style={{ width: `${progressPercent}%` }}
146
- />
147
- </div>
148
-
149
- {/* Terminal output */}
150
- <div className={`bg-gray-900 dark:bg-gray-950 border border-gray-200 dark:border-gray-700/60 rounded-lg p-4 overflow-y-auto font-mono text-xs leading-relaxed ${showPhases ? "max-h-[60vh]" : "max-h-80"}`}>
151
- {lines.map((line, i) => (
152
- <div key={i}>
153
- {parseAnsi(line.text).map((seg, j) => (
154
- <span key={j} className={seg.className}>{seg.text}</span>
155
- ))}
156
- </div>
157
- ))}
158
- <div ref={endRef} />
159
- </div>
160
- </div>
161
- );
162
- }
@@ -1,46 +0,0 @@
1
- import React from "react";
2
- import { useThemeProvider } from "../utils/ThemeContext";
3
-
4
- export default function ThemeToggle() {
5
- const { currentTheme, changeCurrentTheme } = useThemeProvider();
6
-
7
- return (
8
- <div>
9
- <input
10
- type="checkbox"
11
- name="light-switch"
12
- id="light-switch"
13
- className="light-switch sr-only"
14
- checked={currentTheme === "light"}
15
- onChange={() => changeCurrentTheme(currentTheme === "light" ? "dark" : "light")}
16
- />
17
- <label
18
- className="flex items-center justify-center cursor-pointer w-8 h-8 hover:bg-gray-100 lg:hover:bg-gray-200 dark:hover:bg-gray-700/50 dark:lg:hover:bg-gray-800 rounded-full"
19
- htmlFor="light-switch"
20
- >
21
- <svg
22
- className="dark:hidden fill-current text-gray-500/80 dark:text-gray-400/80"
23
- width={16}
24
- height={16}
25
- viewBox="0 0 16 16"
26
- xmlns="http://www.w3.org/2000/svg"
27
- >
28
- <path d="M8 0a1 1 0 0 1 1 1v.5a1 1 0 1 1-2 0V1a1 1 0 0 1 1-1Z" />
29
- <path d="M12 8a4 4 0 1 1-8 0 4 4 0 0 1 8 0Zm-4 2a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" />
30
- <path d="M13.657 3.757a1 1 0 0 0-1.414-1.414l-.354.354a1 1 0 0 0 1.414 1.414l.354-.354ZM13.5 8a1 1 0 0 1 1-1h.5a1 1 0 1 1 0 2h-.5a1 1 0 0 1-1-1ZM13.303 11.889a1 1 0 0 0-1.414 1.414l.354.354a1 1 0 0 0 1.414-1.414l-.354-.354ZM8 13.5a1 1 0 0 1 1 1v.5a1 1 0 1 1-2 0v-.5a1 1 0 0 1 1-1ZM4.111 13.303a1 1 0 1 0-1.414-1.414l-.354.354a1 1 0 1 0 1.414 1.414l.354-.354ZM0 8a1 1 0 0 1 1-1h.5a1 1 0 0 1 0 2H1a1 1 0 0 1-1-1ZM3.757 2.343a1 1 0 1 0-1.414 1.414l.354.354A1 1 0 1 0 4.11 2.697l-.354-.354Z" />
31
- </svg>
32
- <svg
33
- className="hidden dark:block fill-current text-gray-500/80 dark:text-gray-400/80"
34
- width={16}
35
- height={16}
36
- viewBox="0 0 16 16"
37
- xmlns="http://www.w3.org/2000/svg"
38
- >
39
- <path d="M11.875 4.375a.625.625 0 1 0 1.25 0c.001-.69.56-1.249 1.25-1.25a.625.625 0 1 0 0-1.25 1.252 1.252 0 0 1-1.25-1.25.625.625 0 1 0-1.25 0 1.252 1.252 0 0 1-1.25 1.25.625.625 0 1 0 0 1.25c.69.001 1.249.56 1.25 1.25Z" />
40
- <path d="M7.019 1.985a1.55 1.55 0 0 0-.483-1.36 1.44 1.44 0 0 0-1.53-.277C2.056 1.553 0 4.5 0 7.9 0 12.352 3.648 16 8.1 16c3.407 0 6.246-2.058 7.51-4.963a1.446 1.446 0 0 0-.25-1.55 1.554 1.554 0 0 0-1.372-.502c-4.01.552-7.539-2.987-6.97-7ZM2 7.9C2 5.64 3.193 3.664 4.961 2.6 4.82 7.245 8.72 11.158 13.36 11.04 12.265 12.822 10.341 14 8.1 14 4.752 14 2 11.248 2 7.9Z" />
41
- </svg>
42
- <span className="sr-only">Switch to light / dark version</span>
43
- </label>
44
- </div>
45
- );
46
- }
@@ -1,147 +0,0 @@
1
- /* Cloud panel field inputs */
2
- .field-input {
3
- @apply w-full bg-white dark:bg-gray-900/60 border border-gray-200 dark:border-gray-700/60 text-sm text-gray-800 dark:text-gray-100 rounded-lg px-3 py-2.5 placeholder-gray-400 dark:placeholder-gray-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/30 shadow-xs transition;
4
- }
5
-
6
- /* Typography */
7
- .h1 {
8
- @apply text-4xl font-extrabold tracking-tighter;
9
- }
10
-
11
- .h2 {
12
- @apply text-3xl font-extrabold tracking-tighter;
13
- }
14
-
15
- .h3 {
16
- @apply text-3xl font-extrabold;
17
- }
18
-
19
- .h4 {
20
- @apply text-2xl font-extrabold tracking-tight;
21
- }
22
-
23
- @media (width >= theme(--breakpoint-md)) {
24
- .h1 {
25
- @apply text-5xl;
26
- }
27
-
28
- .h2 {
29
- @apply text-4xl;
30
- }
31
- }
32
-
33
- /* Buttons */
34
- .btn,
35
- .btn-lg,
36
- .btn-sm,
37
- .btn-xs {
38
- @apply font-medium text-sm inline-flex items-center justify-center border border-transparent rounded-lg leading-5 shadow-xs transition;
39
- }
40
-
41
- .btn {
42
- @apply px-3 py-2;
43
- }
44
-
45
- .btn-lg {
46
- @apply px-4 py-3;
47
- }
48
-
49
- .btn-sm {
50
- @apply px-2 py-1;
51
- }
52
-
53
- .btn-xs {
54
- @apply px-2 py-0.5;
55
- }
56
-
57
- /* Forms */
58
- input[type="search"]::-webkit-search-decoration,
59
- input[type="search"]::-webkit-search-cancel-button,
60
- input[type="search"]::-webkit-search-results-button,
61
- input[type="search"]::-webkit-search-results-decoration {
62
- -webkit-appearance: none;
63
- }
64
-
65
- .form-input,
66
- .form-textarea,
67
- .form-multiselect,
68
- .form-select,
69
- .form-checkbox,
70
- .form-radio {
71
- @apply bg-white dark:bg-gray-900/30 border focus:ring-0 focus:ring-offset-0 dark:disabled:bg-gray-700/30 dark:disabled:border-gray-700 dark:disabled:hover:border-gray-700;
72
- }
73
-
74
- .form-checkbox {
75
- @apply rounded-sm;
76
- }
77
-
78
- .form-input,
79
- .form-textarea,
80
- .form-multiselect,
81
- .form-select {
82
- @apply text-sm text-gray-800 dark:text-gray-100 leading-5 py-2 px-3 border-gray-200 hover:border-gray-300 focus:border-gray-300 dark:border-gray-700/60 dark:hover:border-gray-600 dark:focus:border-gray-600 shadow-xs rounded-lg;
83
- }
84
-
85
- .form-input,
86
- .form-textarea {
87
- @apply placeholder-gray-400 dark:placeholder-gray-500;
88
- }
89
-
90
- .form-select {
91
- @apply pr-10;
92
- }
93
-
94
- .form-checkbox,
95
- .form-radio {
96
- @apply text-violet-500 checked:bg-violet-500 checked:border-transparent border border-gray-300 dark:border-gray-700/60 dark:checked:border-transparent focus-visible:ring-2 focus-visible:ring-violet-500/50;
97
- }
98
-
99
- /* Switch element */
100
- .form-switch {
101
- @apply relative select-none;
102
- width: 44px;
103
- }
104
-
105
- .form-switch label {
106
- @apply block overflow-hidden cursor-pointer h-6 rounded-full;
107
- }
108
-
109
- .form-switch label > span:first-child {
110
- @apply absolute block rounded-full;
111
- width: 20px;
112
- height: 20px;
113
- top: 2px;
114
- left: 2px;
115
- right: 50%;
116
- transition: all .15s ease-out;
117
- }
118
-
119
- .form-switch input[type="checkbox"] + label {
120
- @apply bg-gray-400 dark:bg-gray-700;
121
- }
122
-
123
- .form-switch input[type="checkbox"]:checked + label {
124
- @apply bg-violet-500;
125
- }
126
-
127
- .form-switch input[type="checkbox"]:checked + label > span:first-child {
128
- left: 22px;
129
- }
130
-
131
- .form-switch input[type="checkbox"]:disabled + label {
132
- @apply cursor-not-allowed bg-gray-100 dark:bg-gray-700/20 border border-gray-200 dark:border-gray-700/60;
133
- }
134
-
135
- .form-switch input[type="checkbox"]:disabled + label > span:first-child {
136
- @apply bg-gray-400 dark:bg-gray-600;
137
- }
138
-
139
- /* Chrome, Safari and Opera */
140
- .no-scrollbar::-webkit-scrollbar {
141
- display: none;
142
- }
143
-
144
- .no-scrollbar {
145
- -ms-overflow-style: none; /* IE and Edge */
146
- scrollbar-width: none; /* Firefox */
147
- }
@@ -1,138 +0,0 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback');
2
-
3
- @import 'tailwindcss';
4
- @import './additional-styles/utility-patterns.css' layer(components);
5
-
6
- @plugin "@tailwindcss/forms" {
7
- strategy: base;
8
- }
9
-
10
- @custom-variant dark (&:is(.dark *));
11
- @custom-variant sidebar-expanded (&:is(.sidebar-expanded *));
12
-
13
- @theme {
14
- --shadow-sm: 0 1px 1px 0 rgb(0 0 0 / 0.05), 0 1px 2px 0 rgb(0 0 0 / 0.02);
15
-
16
- --color-gray-50: #f9fafb;
17
- --color-gray-100: #f3f4f6;
18
- --color-gray-200: #e5e7eb;
19
- --color-gray-300: #bfc4cd;
20
- --color-gray-400: #9ca3af;
21
- --color-gray-500: #6b7280;
22
- --color-gray-600: #4b5563;
23
- --color-gray-700: #374151;
24
- --color-gray-800: #1f2937;
25
- --color-gray-900: #111827;
26
- --color-gray-950: #030712;
27
-
28
- --color-violet-50: #f1eeff;
29
- --color-violet-100: #e6e1ff;
30
- --color-violet-200: #d2cbff;
31
- --color-violet-300: #b7acff;
32
- --color-violet-400: #9c8cff;
33
- --color-violet-500: #8470ff;
34
- --color-violet-600: #755ff8;
35
- --color-violet-700: #5d47de;
36
- --color-violet-800: #4634b1;
37
- --color-violet-900: #2f227c;
38
- --color-violet-950: #1c1357;
39
-
40
- --color-sky-50: #e3f3ff;
41
- --color-sky-100: #d1ecff;
42
- --color-sky-200: #b6e1ff;
43
- --color-sky-300: #a0d7ff;
44
- --color-sky-400: #7bc8ff;
45
- --color-sky-500: #67bfff;
46
- --color-sky-600: #56b1f3;
47
- --color-sky-700: #3193da;
48
- --color-sky-800: #1c71ae;
49
- --color-sky-900: #124d79;
50
- --color-sky-950: #0b324f;
51
-
52
- --color-green-50: #d2ffe2;
53
- --color-green-100: #b1fdcd;
54
- --color-green-200: #8bf0b0;
55
- --color-green-300: #67e294;
56
- --color-green-400: #4bd37d;
57
- --color-green-500: #3ec972;
58
- --color-green-600: #34bd68;
59
- --color-green-700: #239f52;
60
- --color-green-800: #15773a;
61
- --color-green-900: #0f5429;
62
- --color-green-950: #0a3f1e;
63
-
64
- --color-red-50: #ffe8e8;
65
- --color-red-100: #ffd1d1;
66
- --color-red-200: #ffb2b2;
67
- --color-red-300: #ff9494;
68
- --color-red-400: #ff7474;
69
- --color-red-500: #ff5656;
70
- --color-red-600: #fa4949;
71
- --color-red-700: #e63939;
72
- --color-red-800: #c52727;
73
- --color-red-900: #941818;
74
- --color-red-950: #600f0f;
75
-
76
- --color-yellow-50: #fff2c9;
77
- --color-yellow-100: #ffe7a0;
78
- --color-yellow-200: #ffe081;
79
- --color-yellow-300: #ffd968;
80
- --color-yellow-400: #f7cd4c;
81
- --color-yellow-500: #f0bb33;
82
- --color-yellow-600: #dfad2b;
83
- --color-yellow-700: #bc9021;
84
- --color-yellow-800: #816316;
85
- --color-yellow-900: #4f3d0e;
86
- --color-yellow-950: #342809;
87
-
88
- --font-inter: "Inter", "sans-serif";
89
-
90
- --text-xs: 0.75rem;
91
- --text-xs--line-height: 1.5;
92
- --text-sm: 0.875rem;
93
- --text-sm--line-height: 1.5715;
94
- --text-base: 1rem;
95
- --text-base--line-height: 1.5;
96
- --text-base--letter-spacing: -0.01em;
97
- --text-lg: 1.125rem;
98
- --text-lg--line-height: 1.5;
99
- --text-lg--letter-spacing: -0.01em;
100
- --text-xl: 1.25rem;
101
- --text-xl--line-height: 1.5;
102
- --text-xl--letter-spacing: -0.01em;
103
- --text-2xl: 1.5rem;
104
- --text-2xl--line-height: 1.33;
105
- --text-2xl--letter-spacing: -0.01em;
106
- --text-3xl: 1.88rem;
107
- --text-3xl--line-height: 1.33;
108
- --text-3xl--letter-spacing: -0.01em;
109
- --text-4xl: 2.25rem;
110
- --text-4xl--line-height: 1.25;
111
- --text-4xl--letter-spacing: -0.02em;
112
- --text-5xl: 3rem;
113
- --text-5xl--line-height: 1.25;
114
- --text-5xl--letter-spacing: -0.02em;
115
- --text-6xl: 3.75rem;
116
- --text-6xl--line-height: 1.2;
117
- --text-6xl--letter-spacing: -0.02em;
118
-
119
- --breakpoint-xs: 480px;
120
- }
121
-
122
- /*
123
- The default border color has changed to `currentColor` in Tailwind CSS v4,
124
- so we've added these compatibility styles to make sure everything still
125
- looks the same as it did with Tailwind CSS v3.
126
-
127
- If we ever want to remove these styles, we need to add an explicit border
128
- color utility to any element that depends on these defaults.
129
- */
130
- @layer base {
131
- *,
132
- ::after,
133
- ::before,
134
- ::backdrop,
135
- ::file-selector-button {
136
- border-color: var(--color-gray-200, currentColor);
137
- }
138
- }
@@ -1,15 +0,0 @@
1
- <svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
3
- <path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
4
- <defs>
5
- <linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
6
- <stop stop-color="#41D1FF"/>
7
- <stop offset="1" stop-color="#BD34FE"/>
8
- </linearGradient>
9
- <linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
10
- <stop stop-color="#FFEA83"/>
11
- <stop offset="0.0833333" stop-color="#FFDD35"/>
12
- <stop offset="1" stop-color="#FFA800"/>
13
- </linearGradient>
14
- </defs>
15
- </svg>
@@ -1,19 +0,0 @@
1
- import { clsx, type ClassValue } from "clsx"
2
- import { twMerge } from "tailwind-merge"
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
6
- }
7
-
8
- export function formatDate(input: string | number): string {
9
- const date = new Date(input)
10
- return date.toLocaleDateString("en-US", {
11
- month: "long",
12
- day: "numeric",
13
- year: "numeric",
14
- })
15
- }
16
-
17
- export function absoluteUrl(path: string) {
18
- return `${process.env.NEXT_PUBLIC_APP_URL}${path}`
19
- }
@@ -1,25 +0,0 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom/client";
3
- import { BrowserRouter as Router } from "react-router-dom";
4
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
- import ThemeProvider from "./utils/ThemeContext";
6
- import AuthProvider from "./utils/AuthContext";
7
- import App from "./App";
8
-
9
- const queryClient = new QueryClient({
10
- defaultOptions: { queries: { staleTime: 5000, retry: 1 } },
11
- });
12
-
13
- ReactDOM.createRoot(document.getElementById("root")).render(
14
- <React.StrictMode>
15
- <Router basename="/cloud">
16
- <ThemeProvider>
17
- <AuthProvider>
18
- <QueryClientProvider client={queryClient}>
19
- <App />
20
- </QueryClientProvider>
21
- </AuthProvider>
22
- </ThemeProvider>
23
- </Router>
24
- </React.StrictMode>,
25
- );