next-helios-fe 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 (112) hide show
  1. package/@types/index.d.ts +2 -0
  2. package/dist/components/button/index.d.ts +15 -0
  3. package/dist/components/calendar/big-calendar/event.d.ts +7 -0
  4. package/dist/components/calendar/big-calendar/index.d.ts +14 -0
  5. package/dist/components/calendar/big-calendar/toolbar.d.ts +8 -0
  6. package/dist/components/calendar/calendar/index.d.ts +11 -0
  7. package/dist/components/chart/index.d.ts +17 -0
  8. package/dist/components/chip/index.d.ts +12 -0
  9. package/dist/components/content-container/accordion/index.d.ts +10 -0
  10. package/dist/components/content-container/accordion/item.d.ts +6 -0
  11. package/dist/components/content-container/card.d.ts +10 -0
  12. package/dist/components/content-container/carousel.d.ts +10 -0
  13. package/dist/components/content-container/drawer.d.ts +8 -0
  14. package/dist/components/content-container/modal/index.d.ts +21 -0
  15. package/dist/components/content-container/sortable/index.d.ts +14 -0
  16. package/dist/components/content-container/sortable/item.d.ts +8 -0
  17. package/dist/components/content-container/sortable/knob.d.ts +5 -0
  18. package/dist/components/content-container/tab/index.d.ts +17 -0
  19. package/dist/components/content-container/tab/window.d.ts +5 -0
  20. package/dist/components/data-tree/index.d.ts +6 -0
  21. package/dist/components/dialog/index.d.ts +16 -0
  22. package/dist/components/dropdown/header.d.ts +5 -0
  23. package/dist/components/dropdown/index.d.ts +15 -0
  24. package/dist/components/dropdown/item.d.ts +7 -0
  25. package/dist/components/form/index.d.ts +44 -0
  26. package/dist/components/form/input/checkbox.d.ts +9 -0
  27. package/dist/components/form/input/color.d.ts +10 -0
  28. package/dist/components/form/input/email.d.ts +9 -0
  29. package/dist/components/form/input/file.d.ts +14 -0
  30. package/dist/components/form/input/number.d.ts +9 -0
  31. package/dist/components/form/input/password.d.ts +9 -0
  32. package/dist/components/form/input/radio.d.ts +9 -0
  33. package/dist/components/form/input/range.d.ts +9 -0
  34. package/dist/components/form/input/search.d.ts +8 -0
  35. package/dist/components/form/input/text.d.ts +9 -0
  36. package/dist/components/form/input/time.d.ts +9 -0
  37. package/dist/components/form/other/autocomplete.d.ts +15 -0
  38. package/dist/components/form/other/multipleSelect.d.ts +23 -0
  39. package/dist/components/form/other/phoneNumber.d.ts +10 -0
  40. package/dist/components/form/other/pin.d.ts +10 -0
  41. package/dist/components/form/other/secret.d.ts +11 -0
  42. package/dist/components/form/other/select.d.ts +15 -0
  43. package/dist/components/form/other/textarea.d.ts +9 -0
  44. package/dist/components/index.d.ts +19 -0
  45. package/dist/components/map/index.d.ts +13 -0
  46. package/dist/components/map/marker.d.ts +8 -0
  47. package/dist/components/syntax-highlighter/index.d.ts +9 -0
  48. package/dist/components/table/action.d.ts +5 -0
  49. package/dist/components/table/index.d.ts +24 -0
  50. package/dist/components/timeline/index.d.ts +10 -0
  51. package/dist/components/timeline/item.d.ts +7 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +2 -0
  54. package/dist/index.js.LICENSE.txt +62 -0
  55. package/package.json +72 -0
  56. package/src/components/button/index.tsx +74 -0
  57. package/src/components/calendar/big-calendar/event.tsx +46 -0
  58. package/src/components/calendar/big-calendar/index.tsx +102 -0
  59. package/src/components/calendar/big-calendar/toolbar.tsx +98 -0
  60. package/src/components/calendar/calendar/index.tsx +26 -0
  61. package/src/components/chart/index.tsx +121 -0
  62. package/src/components/chip/index.tsx +47 -0
  63. package/src/components/content-container/accordion/index.tsx +28 -0
  64. package/src/components/content-container/accordion/item.tsx +40 -0
  65. package/src/components/content-container/card.tsx +21 -0
  66. package/src/components/content-container/carousel.tsx +35 -0
  67. package/src/components/content-container/drawer.tsx +78 -0
  68. package/src/components/content-container/modal/index.tsx +127 -0
  69. package/src/components/content-container/sortable/index.tsx +47 -0
  70. package/src/components/content-container/sortable/item.tsx +20 -0
  71. package/src/components/content-container/sortable/knob.tsx +11 -0
  72. package/src/components/content-container/tab/index.tsx +94 -0
  73. package/src/components/content-container/tab/window.tsx +10 -0
  74. package/src/components/data-tree/index.tsx +60 -0
  75. package/src/components/dialog/index.tsx +88 -0
  76. package/src/components/dropdown/header.tsx +11 -0
  77. package/src/components/dropdown/index.tsx +69 -0
  78. package/src/components/dropdown/item.tsx +22 -0
  79. package/src/components/form/index.tsx +81 -0
  80. package/src/components/form/input/checkbox.tsx +49 -0
  81. package/src/components/form/input/color.tsx +104 -0
  82. package/src/components/form/input/email.tsx +40 -0
  83. package/src/components/form/input/file.tsx +189 -0
  84. package/src/components/form/input/number.tsx +93 -0
  85. package/src/components/form/input/password.tsx +57 -0
  86. package/src/components/form/input/radio.tsx +49 -0
  87. package/src/components/form/input/range.tsx +67 -0
  88. package/src/components/form/input/search.tsx +50 -0
  89. package/src/components/form/input/text.tsx +39 -0
  90. package/src/components/form/input/time.tsx +315 -0
  91. package/src/components/form/other/autocomplete.tsx +199 -0
  92. package/src/components/form/other/multipleSelect.tsx +211 -0
  93. package/src/components/form/other/phoneNumber.tsx +1668 -0
  94. package/src/components/form/other/pin.tsx +56 -0
  95. package/src/components/form/other/secret.tsx +74 -0
  96. package/src/components/form/other/select.tsx +187 -0
  97. package/src/components/form/other/textarea.tsx +44 -0
  98. package/src/components/index.ts +29 -0
  99. package/src/components/map/index.tsx +72 -0
  100. package/src/components/map/marker.tsx +40 -0
  101. package/src/components/syntax-highlighter/index.tsx +45 -0
  102. package/src/components/table/action.tsx +22 -0
  103. package/src/components/table/index.tsx +431 -0
  104. package/src/components/timeline/index.tsx +28 -0
  105. package/src/components/timeline/item.tsx +25 -0
  106. package/src/index.css +1 -0
  107. package/src/index.ts +3 -0
  108. package/src/styles/big-calendar.scss +810 -0
  109. package/src/styles/calendar.scss +195 -0
  110. package/src/styles/index.css +2 -0
  111. package/tsconfig.json +17 -0
  112. package/webpack.config.js +35 -0
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { PinField } from "react-pin-field";
4
+
5
+ export interface PinProps extends React.InputHTMLAttributes<HTMLInputElement> {
6
+ options?: {
7
+ height?: "short" | "medium" | "high";
8
+ length: number;
9
+ };
10
+ label?: string;
11
+ onChange?: (e: any) => void;
12
+ }
13
+
14
+ export const Pin: React.FC<PinProps> = ({
15
+ options,
16
+ label,
17
+ onChange,
18
+ ...rest
19
+ }) => {
20
+ const height =
21
+ options?.height === "short"
22
+ ? "py-1"
23
+ : options?.height === "high"
24
+ ? "py-2"
25
+ : "py-1.5";
26
+
27
+ return (
28
+ <label className="grid gap-2 w-fit">
29
+ {label && (
30
+ <span
31
+ className={`text-sm select-none ${
32
+ rest.required && "after:content-['*'] after:ml-1 after:text-danger"
33
+ }`}
34
+ >
35
+ {label}
36
+ </span>
37
+ )}
38
+ <div className="flex items-center gap-4">
39
+ <PinField
40
+ className={`text-center w-10 border-default border rounded-md bg-secondary-bg placeholder:duration-300 placeholder:translate-x-0 focus:placeholder:translate-x-1 placeholder:text-slate-300 focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark disabled:bg-secondary-light disabled:text-slate-400 ${height}`}
41
+ length={6}
42
+ validate={/^[0-9]$/}
43
+ onChange={(value) => {
44
+ const e = {
45
+ target: {
46
+ value,
47
+ },
48
+ };
49
+ onChange && onChange!(e);
50
+ }}
51
+ {...rest}
52
+ />
53
+ </div>
54
+ </label>
55
+ );
56
+ };
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import React, { useState } from "react";
3
+ import { Icon } from "@iconify/react";
4
+
5
+ export interface SecretProps
6
+ extends React.InputHTMLAttributes<HTMLInputElement> {
7
+ options?: {
8
+ width?: "full" | "fit";
9
+ height?: "short" | "medium" | "high";
10
+ };
11
+ label?: string;
12
+ value?: string;
13
+ onClipboardClick?: (value: string) => void;
14
+ }
15
+
16
+ export const Secret: React.FC<SecretProps> = ({
17
+ options,
18
+ label,
19
+ value,
20
+ onClipboardClick,
21
+ ...rest
22
+ }) => {
23
+ const [show, setShow] = useState(false);
24
+ const width = options?.width === "fit" ? "w-fit" : "w-full";
25
+ const height =
26
+ options?.height === "short"
27
+ ? "py-1"
28
+ : options?.height === "high"
29
+ ? "py-2"
30
+ : "py-1.5";
31
+
32
+ return (
33
+ <label className={`grid gap-2 ${width}`}>
34
+ {label && (
35
+ <span
36
+ className={`text-sm select-none ${
37
+ rest.required && "after:content-['*'] after:ml-1 after:text-danger"
38
+ }`}
39
+ >
40
+ {label}
41
+ </span>
42
+ )}
43
+ <div className="relative flex items-center">
44
+ <input
45
+ type="text"
46
+ className={`w-full px-4 border-default border rounded-md bg-secondary-bg placeholder:duration-300 placeholder:translate-x-0 focus:placeholder:translate-x-1 placeholder:text-slate-300 focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark disabled:bg-secondary-light disabled:text-slate-400 ${height}`}
47
+ value={show ? value : value ? value.slice(0, 3) + ".." : ""}
48
+ disabled
49
+ {...rest}
50
+ />
51
+ <div className="absolute right-4 flex">
52
+ <div
53
+ className="p-1 rounded-full text-xl text-slate-400 cursor-pointer hover:bg-secondary-light"
54
+ onClick={(e) => {
55
+ e.preventDefault();
56
+ setShow(!show);
57
+ }}
58
+ >
59
+ <Icon icon={`flowbite:eye${show ? "" : "-slash"}-outline`} />
60
+ </div>
61
+ <div
62
+ className="p-1 rounded-full text-xl text-slate-400 cursor-pointer hover:bg-secondary-light"
63
+ onClick={(e) => {
64
+ e.preventDefault();
65
+ onClipboardClick && onClipboardClick(value!);
66
+ }}
67
+ >
68
+ <Icon icon="fluent:clipboard-text-ltr-32-regular" />
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </label>
73
+ );
74
+ };
@@ -0,0 +1,187 @@
1
+ "use client";
2
+ import React, { useState, useEffect, useRef } from "react";
3
+ import { Icon } from "@iconify/react";
4
+ import { createPortal } from "react-dom";
5
+
6
+ export interface SelectProps
7
+ extends React.SelectHTMLAttributes<HTMLSelectElement> {
8
+ options?: {
9
+ width?: "full" | "fit";
10
+ height?: "short" | "medium" | "high";
11
+ };
12
+ label?: string;
13
+ menus: {
14
+ label: string;
15
+ value: string;
16
+ [key: string]: any;
17
+ }[];
18
+ placeholder?: string;
19
+ }
20
+
21
+ export const Select: React.FC<SelectProps> = ({
22
+ options,
23
+ label,
24
+ menus,
25
+ placeholder,
26
+ ...rest
27
+ }) => {
28
+ const [tempValue, setTempValue] = useState("");
29
+ const [isOpen, setIsOpen] = useState(false);
30
+ const [position, setPosition] = useState<{
31
+ top: number;
32
+ left: number;
33
+ } | null>(null);
34
+ const [dropdownWidth, setDropdownWidth] = useState<number>(0);
35
+ const triggerRef = useRef<HTMLDivElement>(null);
36
+ const dropdownRef = useRef<HTMLDivElement>(null);
37
+ const width = options?.width === "fit" ? "w-fit" : "w-full";
38
+ const height =
39
+ options?.height === "short"
40
+ ? "py-1"
41
+ : options?.height === "high"
42
+ ? "py-2"
43
+ : "py-1.5";
44
+
45
+ useEffect(() => {
46
+ const handleClickOutside = (e: MouseEvent) => {
47
+ if (
48
+ dropdownRef.current &&
49
+ !dropdownRef.current.contains(e.target as Node) &&
50
+ !triggerRef.current?.contains(e.target as Node)
51
+ ) {
52
+ setIsOpen(false);
53
+ }
54
+ };
55
+
56
+ document.addEventListener("mousedown", handleClickOutside);
57
+ return () => {
58
+ document.removeEventListener("mousedown", handleClickOutside);
59
+ };
60
+ }, []);
61
+
62
+ useEffect(() => {
63
+ if (triggerRef.current) {
64
+ const rect = triggerRef.current.getBoundingClientRect();
65
+ const dropdownHeight = dropdownRef.current?.offsetHeight || 0;
66
+ const windowHeight = window.innerHeight;
67
+
68
+ setPosition({
69
+ top: rect.bottom + window.scrollY + 10,
70
+ left: rect.left + window.scrollX,
71
+ });
72
+
73
+ setDropdownWidth(rect.width);
74
+
75
+ if (rect.bottom + dropdownHeight > windowHeight) {
76
+ setPosition((prev) =>
77
+ prev
78
+ ? { ...prev, top: rect.top + window.scrollY - dropdownHeight - 10 }
79
+ : null
80
+ );
81
+ }
82
+ }
83
+
84
+ if (isOpen) {
85
+ document.getElementById("body")!.style.overflow = "hidden";
86
+ } else {
87
+ document.getElementById("body")!.style.overflow = "auto";
88
+ }
89
+ }, [isOpen]);
90
+
91
+ useEffect(() => {
92
+ if (rest.value) {
93
+ setTempValue(rest.value as string);
94
+ return;
95
+ } else if (rest.defaultValue) {
96
+ setTempValue(rest.defaultValue as string);
97
+ return;
98
+ }
99
+ }, [rest.value, rest.defaultValue]);
100
+
101
+ useEffect(() => {
102
+ if (tempValue) {
103
+ rest.onChange &&
104
+ rest.onChange({
105
+ target: { value: tempValue } as HTMLSelectElement,
106
+ } as any);
107
+ }
108
+ }, [tempValue]);
109
+
110
+ return (
111
+ <label className={`grid gap-2 ${width}`}>
112
+ {label && (
113
+ <span
114
+ className={`text-sm select-none ${
115
+ rest.required && "after:content-['*'] after:ml-1 after:text-danger"
116
+ }`}
117
+ >
118
+ {label}
119
+ </span>
120
+ )}
121
+ <div className="relative" ref={triggerRef}>
122
+ <div
123
+ className="relative flex items-center cursor-pointer"
124
+ onClick={() => setIsOpen(!isOpen)}
125
+ >
126
+ <input
127
+ type="text"
128
+ className={`w-full px-4 border-default border rounded-md bg-secondary-bg cursor-pointer caret-transparent placeholder:duration-300 placeholder:translate-x-0 focus:placeholder:translate-x-1 placeholder:text-slate-300 focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark disabled:bg-secondary-light disabled:text-slate-400 disabled:cursor-default ${height}`}
129
+ placeholder={placeholder}
130
+ disabled={rest.disabled}
131
+ value={tempValue}
132
+ onClick={() => setIsOpen(true)}
133
+ />
134
+ <div className="absolute right-4 text-xl text-slate-400 pointer-events-none">
135
+ <Icon icon={`gravity-ui:chevron-${isOpen ? "up" : "down"}`} />
136
+ </div>
137
+ </div>
138
+ {isOpen &&
139
+ position &&
140
+ createPortal(
141
+ <div
142
+ ref={dropdownRef}
143
+ className="absolute max-h-40 p-1 z-50 pointer-events-auto bg-secondary-bg shadow border rounded-md overflow-auto"
144
+ style={{
145
+ top: position.top,
146
+ left: position.left,
147
+ width: dropdownWidth,
148
+ }}
149
+ >
150
+ {menus.length === 0 ? (
151
+ <div className="flex justify-center">
152
+ <span className="px-4 py-1">No data found</span>
153
+ </div>
154
+ ) : (
155
+ menus.map((item, index) => (
156
+ <button
157
+ key={index}
158
+ type="button"
159
+ className={`min-w-40 w-full my-0.5 px-4 py-2 rounded-md text-sm text-left text-default ${
160
+ (menus.find((item) => item.value === rest.value)?.label ||
161
+ tempValue) === item.label
162
+ ? "bg-primary-transparent cursor-default"
163
+ : "hover:bg-secondary-light "
164
+ }`}
165
+ onMouseDown={() => {
166
+ setTempValue(item.label);
167
+ setIsOpen(false);
168
+ }}
169
+ >
170
+ {item.label}
171
+ </button>
172
+ ))
173
+ )}
174
+ </div>,
175
+ document.body
176
+ )}
177
+ </div>
178
+ <select className="hidden" {...rest}>
179
+ {menus.map((item, index) => (
180
+ <option key={index} value={item.value}>
181
+ {item.label}
182
+ </option>
183
+ ))}
184
+ </select>
185
+ </label>
186
+ );
187
+ };
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import React from "react";
3
+
4
+ export interface TextareaProps
5
+ extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
6
+ options?: {
7
+ width?: "full" | "fit";
8
+ height?: "short" | "medium" | "high";
9
+ };
10
+ label?: string;
11
+ }
12
+
13
+ export const Textarea: React.FC<TextareaProps> = ({
14
+ options,
15
+ label,
16
+ ...rest
17
+ }) => {
18
+ const width = options?.width === "fit" ? "w-fit" : "w-full";
19
+ const height =
20
+ options?.height === "short"
21
+ ? "py-1"
22
+ : options?.height === "high"
23
+ ? "py-2"
24
+ : "py-1.5";
25
+
26
+ return (
27
+ <label className={`grid gap-2 ${width}`}>
28
+ {label && (
29
+ <span
30
+ className={`text-sm select-none ${
31
+ rest.required && "after:content-['*'] after:ml-1 after:text-danger"
32
+ }`}
33
+ >
34
+ {label}
35
+ </span>
36
+ )}
37
+ <textarea
38
+ rows={rest.rows || 10}
39
+ className={`w-full px-4 border-default border rounded-md bg-secondary-bg placeholder:duration-300 placeholder:translate-x-0 focus:placeholder:translate-x-1 placeholder:text-slate-300 focus:outline-none focus:ring-1 focus:ring-primary focus:shadow focus:shadow-primary focus:border-primary-dark disabled:bg-secondary-light disabled:text-slate-400 ${height}`}
40
+ {...rest}
41
+ />
42
+ </label>
43
+ );
44
+ };
@@ -0,0 +1,29 @@
1
+ // export { Sidebar } from "./main-layout/sidebar";
2
+ // export { Header } from "./main-layout/header";
3
+ // export { Body } from "./main-layout/body";
4
+ // export { Footer } from "./main-layout/footer";
5
+ // export { Chat } from "./chat";
6
+ // export { Logo } from "./other-component/logo";
7
+ // export { Avatar } from "./other-component/avatar";
8
+ // export { Mfa } from "./security/mfa";
9
+ // export { Recaptcha } from "./security/recaptcha";
10
+ export { Tab } from "./content-container/tab";
11
+ export { Dialog } from "./dialog";
12
+ export { Modal } from "./content-container/modal";
13
+ export { Drawer } from "./content-container/drawer";
14
+ export { Carousel } from "./content-container/carousel";
15
+ export { Accordion } from "./content-container/accordion";
16
+ export { Sortable } from "./content-container/sortable";
17
+ export { Card } from "./content-container/card";
18
+ export { Dropdown } from "./dropdown";
19
+ export { Chip } from "./chip";
20
+ export { Form } from "./form";
21
+ export { Button } from "./button";
22
+ export { Table } from "./table";
23
+ export { Chart } from "./chart";
24
+ export { Calendar } from "./calendar/calendar";
25
+ export { BigCalendar } from "./calendar/big-calendar";
26
+ // export { Map } from "./map";
27
+ export { Timeline } from "./timeline";
28
+ export { DataTree } from "./data-tree";
29
+ export { SyntaxHighlighter } from "./syntax-highlighter";
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import React, { useRef } from "react";
3
+ import dynamic from "next/dynamic";
4
+ const MapContainer = dynamic(
5
+ () => import("react-leaflet").then((mod) => mod.MapContainer),
6
+ { ssr: false }
7
+ );
8
+ const TileLayer = dynamic(
9
+ () => import("react-leaflet").then((mod) => mod.TileLayer),
10
+ { ssr: false }
11
+ );
12
+ import { useMap, useMapEvent } from "react-leaflet";
13
+ import("leaflet-defaulticon-compatibility")
14
+ .then((module) => {})
15
+ .catch((error) => {
16
+ console.error("Failed to import leaflet-defaulticon-compatibility:", error);
17
+ });
18
+ import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css";
19
+ import "leaflet/dist/leaflet.css";
20
+ import { Marker, type MarkerProps } from "./marker";
21
+
22
+ const ChangeView = ({ center, zoom }: any) => {
23
+ const map = useMap();
24
+ map.setView(center, zoom);
25
+ return null;
26
+ };
27
+
28
+ const SetViewOnClick = ({ animateRef }: any) => {
29
+ const map = useMapEvent("click", (e) => {
30
+ map.setView(e.latlng, map.getZoom(), {
31
+ animate: animateRef.current || false,
32
+ });
33
+ });
34
+
35
+ return null;
36
+ };
37
+
38
+ interface MapProps {
39
+ children: React.ReactNode;
40
+ currentPosition: any[];
41
+ }
42
+
43
+ interface MapComponentProps extends React.FC<MapProps> {
44
+ Marker: React.FC<MarkerProps>;
45
+ }
46
+
47
+ export const Map: MapComponentProps = ({ children, currentPosition }) => {
48
+ const animateRef = useRef(true);
49
+
50
+ return (
51
+ <div className="flex-1 w-full h-full">
52
+ <MapContainer
53
+ // center={currentPosition}
54
+ // zoom={10}
55
+ scrollWheelZoom={true}
56
+ zoomControl={false}
57
+ // attributionControl={false}
58
+ style={{ width: "100%", height: "100%", zIndex: "10" }}
59
+ >
60
+ <TileLayer
61
+ attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
62
+ url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
63
+ />
64
+ {children}
65
+ <ChangeView center={currentPosition} zoom={15} />
66
+ <SetViewOnClick animateRef={animateRef} />
67
+ </MapContainer>
68
+ </div>
69
+ );
70
+ };
71
+
72
+ Map.Marker = Marker;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import React from "react";
3
+ import dynamic from "next/dynamic";
4
+ const Mk = dynamic(() => import("react-leaflet").then((mod) => mod.Marker), {
5
+ ssr: false,
6
+ });
7
+ const Tooltip = dynamic(
8
+ () => import("react-leaflet").then((mod) => mod.Tooltip),
9
+ { ssr: false }
10
+ );
11
+ const Popup = dynamic(() => import("react-leaflet").then((mod) => mod.Popup), {
12
+ ssr: false,
13
+ });
14
+
15
+ export interface MarkerProps {
16
+ position: any;
17
+ label: string;
18
+ desc?: React.ReactNode;
19
+ onClick: (position: any) => void;
20
+ }
21
+
22
+ export const Marker: React.FC<MarkerProps> = ({
23
+ position,
24
+ label,
25
+ desc,
26
+ onClick,
27
+ }) => {
28
+ return (
29
+ <Mk
30
+ position={position}
31
+ eventHandlers={{
32
+ click: onClick,
33
+ }}
34
+ alt={label}
35
+ >
36
+ <Tooltip permanent>{label}</Tooltip>
37
+ {desc && <Popup autoClose>{desc}</Popup>}
38
+ </Mk>
39
+ );
40
+ };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import React from "react";
3
+ import SH from "react-syntax-highlighter";
4
+ import {
5
+ atomOneLight,
6
+ atomOneDark,
7
+ } from "react-syntax-highlighter/dist/esm/styles/hljs";
8
+ import { Icon } from "@iconify/react";
9
+
10
+ interface SyntaxHighlighterProps {
11
+ theme?: "light" | "dark" | "system";
12
+ codeString: string;
13
+ language?: string;
14
+ onClipboardClick?: (value: string) => void;
15
+ }
16
+
17
+ export const SyntaxHighlighter: React.FC<SyntaxHighlighterProps> = ({
18
+ theme,
19
+ codeString,
20
+ language,
21
+ onClipboardClick,
22
+ }) => {
23
+ return (
24
+ <div className="relative w-full border rounded-md overflow-hidden">
25
+ <SH
26
+ language={language}
27
+ style={theme === "light" ? atomOneLight : atomOneDark}
28
+ showLineNumbers
29
+ wrapLongLines
30
+ >
31
+ {codeString}
32
+ </SH>
33
+ <div
34
+ className="absolute top-4 right-4 p-1 rounded-full text-xl text-slate-400 cursor-pointer hover:bg-secondary-light"
35
+ onClick={(e) => {
36
+ e.preventDefault();
37
+ navigator.clipboard.writeText(codeString);
38
+ onClipboardClick && onClipboardClick(codeString);
39
+ }}
40
+ >
41
+ <Icon icon="fluent:clipboard-text-ltr-32-regular" />
42
+ </div>
43
+ </div>
44
+ );
45
+ };
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import React from "react";
3
+
4
+ export interface ActionProps {
5
+ children: React.ReactNode;
6
+ }
7
+
8
+ export const Action: React.FC<ActionProps> = ({ children }) => {
9
+ const childrenList = React.Children.toArray(children);
10
+
11
+ return (
12
+ <div className="flex justify-center items-center gap-4">
13
+ {childrenList?.map((item, index) => {
14
+ return (
15
+ <div key={index}>
16
+ {item}
17
+ </div>
18
+ );
19
+ })}
20
+ </div>
21
+ );
22
+ };