ar-design 0.4.21 → 0.4.23
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.
- package/dist/assets/css/components/data-display/kanban-board/styles.css +75 -0
- package/dist/assets/css/components/form/date-picker/date-picker.css +0 -1
- package/dist/components/data-display/divider/IProps.d.ts +6 -0
- package/dist/components/data-display/divider/IProps.js +1 -0
- package/dist/components/data-display/divider/index.d.ts +2 -1
- package/dist/components/data-display/divider/index.js +1 -1
- package/dist/components/data-display/kanban-board/IProps.d.ts +8 -0
- package/dist/components/data-display/kanban-board/filter/DateFilters.d.ts +23 -0
- package/dist/components/data-display/kanban-board/filter/DateFilters.js +52 -0
- package/dist/components/data-display/kanban-board/filter/SelectFilters.d.ts +25 -0
- package/dist/components/data-display/kanban-board/filter/SelectFilters.js +40 -0
- package/dist/components/data-display/kanban-board/filter/index.d.ts +34 -0
- package/dist/components/data-display/kanban-board/filter/index.js +36 -0
- package/dist/components/data-display/kanban-board/index.js +126 -28
- package/dist/components/form/date-picker/index.js +53 -36
- package/package.json +1 -1
|
@@ -210,6 +210,81 @@
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
.filters {
|
|
214
|
+
position: relative;
|
|
215
|
+
display: flex;
|
|
216
|
+
flex-direction: row;
|
|
217
|
+
justify-content: space-between;
|
|
218
|
+
gap: 1rem;
|
|
219
|
+
background-color: var(--white);
|
|
220
|
+
margin-bottom: 1rem;
|
|
221
|
+
border-radius: var(--border-radius-lg);
|
|
222
|
+
z-index: 6;
|
|
223
|
+
|
|
224
|
+
> :first-child {
|
|
225
|
+
flex: 1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
> ul {
|
|
229
|
+
display: flex;
|
|
230
|
+
flex-direction: row;
|
|
231
|
+
gap: 0.5rem;
|
|
232
|
+
|
|
233
|
+
> li {
|
|
234
|
+
position: relative;
|
|
235
|
+
padding: 0.5rem;
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
user-select: none;
|
|
238
|
+
|
|
239
|
+
&.active {
|
|
240
|
+
background-color: var(--gray-100);
|
|
241
|
+
|
|
242
|
+
> ul {
|
|
243
|
+
animation: dropdownOpen 250ms ease-in-out;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
> div {
|
|
248
|
+
display: flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: 0.5rem;
|
|
251
|
+
|
|
252
|
+
> span {
|
|
253
|
+
color: var(--gray-500);
|
|
254
|
+
font-weight: 500;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
> ul {
|
|
259
|
+
position: absolute;
|
|
260
|
+
top: 100%;
|
|
261
|
+
right: 0;
|
|
262
|
+
background-color: var(--gray-100);
|
|
263
|
+
width: max-content;
|
|
264
|
+
padding: 1rem;
|
|
265
|
+
border-bottom-left-radius: var(--border-radius-sm);
|
|
266
|
+
border-bottom-right-radius: var(--border-radius-sm);
|
|
267
|
+
box-shadow: 0px 5px 5px -2px rgba(var(--black-rgb), 0.1);
|
|
268
|
+
|
|
269
|
+
> li {
|
|
270
|
+
cursor: auto;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@keyframes dropdownOpen {
|
|
278
|
+
from {
|
|
279
|
+
opacity: 0;
|
|
280
|
+
transform: translateY(-8px);
|
|
281
|
+
}
|
|
282
|
+
to {
|
|
283
|
+
opacity: 1;
|
|
284
|
+
transform: translateY(0);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
213
288
|
/* --- [KÜÇÜK MOBİL - IPHONE SE VB.] --- */
|
|
214
289
|
/* Çok dar ekranlar için özel düzeltmeler */
|
|
215
290
|
@media (max-width: 375px) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import "../../../assets/css/components/data-display/divider/divider.css";
|
|
3
|
-
const Divider = () => React.createElement("hr", { className: "ar-divider" });
|
|
3
|
+
const Divider = ({ config }) => React.createElement("hr", { className: "ar-divider", style: { margin: config?.margin } });
|
|
4
4
|
Divider.displayName = "Divider";
|
|
5
5
|
export default Divider;
|
|
@@ -10,6 +10,14 @@ interface IProps<T, TColumnProperties> {
|
|
|
10
10
|
bottom?: number;
|
|
11
11
|
left?: number;
|
|
12
12
|
};
|
|
13
|
+
filter?: {
|
|
14
|
+
search?: (item: T, value: string) => boolean;
|
|
15
|
+
keys: (item: T) => {
|
|
16
|
+
name: string;
|
|
17
|
+
key: string;
|
|
18
|
+
type: "select" | "date";
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
13
21
|
};
|
|
14
22
|
}
|
|
15
23
|
export default IProps;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { Dispatch, SetStateAction } from "react";
|
|
2
|
+
interface IProps {
|
|
3
|
+
states: {
|
|
4
|
+
dateFilters: {
|
|
5
|
+
get: Record<string, {
|
|
6
|
+
from: Date | null;
|
|
7
|
+
to: Date | null;
|
|
8
|
+
}>;
|
|
9
|
+
set: Dispatch<SetStateAction<Record<string, {
|
|
10
|
+
from: Date | null;
|
|
11
|
+
to: Date | null;
|
|
12
|
+
}>>>;
|
|
13
|
+
};
|
|
14
|
+
openName: {
|
|
15
|
+
get: string | null;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
methods: {
|
|
19
|
+
open: (name: string | null) => void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
declare const _default: React.MemoExoticComponent<({ states, methods }: IProps) => React.JSX.Element[]>;
|
|
23
|
+
export default _default;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { memo } from "react";
|
|
2
|
+
import DatePicker from "../../../form/date-picker";
|
|
3
|
+
import { ARIcon } from "../../../icons";
|
|
4
|
+
import Grid from "../../grid-system";
|
|
5
|
+
import Button from "../../../form/button";
|
|
6
|
+
import Divider from "../../divider";
|
|
7
|
+
const { Row, Column, Box } = Grid;
|
|
8
|
+
const DateFilters = ({ states, methods }) => {
|
|
9
|
+
return Object.entries(states.dateFilters.get).map(([name, range], index) => {
|
|
10
|
+
const isEqualsName = states.openName.get === name;
|
|
11
|
+
const className = [];
|
|
12
|
+
if (isEqualsName)
|
|
13
|
+
className.push("active");
|
|
14
|
+
return (React.createElement(React.Fragment, null,
|
|
15
|
+
React.createElement("li", { key: index, className: className.map((c) => c).join(" "), onClick: () => methods.open(name) },
|
|
16
|
+
React.createElement("div", null,
|
|
17
|
+
React.createElement("span", null, name),
|
|
18
|
+
React.createElement(ARIcon, { icon: "ChevronDown" })),
|
|
19
|
+
isEqualsName && (React.createElement("ul", { className: className.map((c) => c).join(" "), onClick: (event) => event.stopPropagation() },
|
|
20
|
+
React.createElement(Row, null,
|
|
21
|
+
React.createElement(Column, null,
|
|
22
|
+
React.createElement(DatePicker, { value: range.from?.toISOString(), onChange: (value) => {
|
|
23
|
+
states.dateFilters.set((prev) => ({
|
|
24
|
+
...prev,
|
|
25
|
+
[name]: {
|
|
26
|
+
...prev[name],
|
|
27
|
+
from: new Date(value),
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
}, placeholder: "From" }))),
|
|
31
|
+
React.createElement(Row, null,
|
|
32
|
+
React.createElement(Column, null,
|
|
33
|
+
React.createElement(DatePicker, { value: range.to?.toISOString(), onChange: (value) => {
|
|
34
|
+
states.dateFilters.set((prev) => ({
|
|
35
|
+
...prev,
|
|
36
|
+
[name]: {
|
|
37
|
+
...prev[name],
|
|
38
|
+
to: new Date(value),
|
|
39
|
+
},
|
|
40
|
+
}));
|
|
41
|
+
}, placeholder: "To" }))),
|
|
42
|
+
React.createElement(Divider, { config: { margin: "0.5rem 0" } }),
|
|
43
|
+
React.createElement(Box, { direction: "flex-end" },
|
|
44
|
+
React.createElement(Button, { color: "red", size: "small", onClick: () => {
|
|
45
|
+
states.dateFilters.set((prev) => ({
|
|
46
|
+
...prev,
|
|
47
|
+
[name]: { from: null, to: null },
|
|
48
|
+
}));
|
|
49
|
+
} }, "Clear")))))));
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
export default memo(DateFilters);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { Dispatch, SetStateAction } from "react";
|
|
2
|
+
interface IProps {
|
|
3
|
+
states: {
|
|
4
|
+
selectFilters: {
|
|
5
|
+
get: {
|
|
6
|
+
[key: string]: (string | null)[];
|
|
7
|
+
};
|
|
8
|
+
set: Dispatch<SetStateAction<{
|
|
9
|
+
[key: string]: (string | null)[];
|
|
10
|
+
}>>;
|
|
11
|
+
};
|
|
12
|
+
selectedFilters: {
|
|
13
|
+
get: Record<string, Set<string | null>>;
|
|
14
|
+
set: Dispatch<SetStateAction<Record<string, Set<string | null>>>>;
|
|
15
|
+
};
|
|
16
|
+
openName: {
|
|
17
|
+
get: string | null;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
methods: {
|
|
21
|
+
open: (name: string | null) => void;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
declare const SelectFilters: ({ states, methods }: IProps) => React.JSX.Element[];
|
|
25
|
+
export default SelectFilters;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ARIcon } from "../../../icons";
|
|
3
|
+
import Checkbox from "../../../form/checkbox";
|
|
4
|
+
import Grid from "../../grid-system";
|
|
5
|
+
import Button from "../../../form/button";
|
|
6
|
+
import Divider from "../../divider";
|
|
7
|
+
const { Box } = Grid;
|
|
8
|
+
const SelectFilters = ({ states, methods }) => {
|
|
9
|
+
return Object.entries(states.selectFilters.get).map(([name, values], index) => {
|
|
10
|
+
const isEqualsName = states.openName.get === name;
|
|
11
|
+
const className = [];
|
|
12
|
+
if (isEqualsName)
|
|
13
|
+
className.push("active");
|
|
14
|
+
return (React.createElement("li", { key: index, className: className.map((c) => c).join(" "), onClick: () => methods.open(name) },
|
|
15
|
+
React.createElement("div", null,
|
|
16
|
+
React.createElement("span", null, name),
|
|
17
|
+
React.createElement(ARIcon, { icon: "ChevronDown" })),
|
|
18
|
+
isEqualsName && (React.createElement("ul", { className: className.map((c) => c).join(" "), onClick: (event) => event.stopPropagation() },
|
|
19
|
+
values.map((value, index) => (React.createElement("li", { key: index },
|
|
20
|
+
React.createElement(Checkbox, { label: String(value ?? "-"), checked: states.selectedFilters.get[name]?.has(value) ?? false, onChange: () => {
|
|
21
|
+
states.selectedFilters.set((prev) => {
|
|
22
|
+
const next = { ...prev };
|
|
23
|
+
const set = new Set(next[name] ?? []);
|
|
24
|
+
set.has(value) ? set.delete(value) : set.add(value);
|
|
25
|
+
next[name] = set;
|
|
26
|
+
return next;
|
|
27
|
+
});
|
|
28
|
+
} })))),
|
|
29
|
+
React.createElement(Divider, { config: { margin: "0.5rem 0" } }),
|
|
30
|
+
React.createElement(Box, { direction: "flex-end" },
|
|
31
|
+
React.createElement(Button, { color: "red", size: "small", onClick: () => {
|
|
32
|
+
states.selectedFilters.set((prev) => {
|
|
33
|
+
const next = { ...prev };
|
|
34
|
+
delete next[name];
|
|
35
|
+
return next;
|
|
36
|
+
});
|
|
37
|
+
} }, "Clear"))))));
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
export default SelectFilters;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
interface IProps {
|
|
4
|
+
states: {
|
|
5
|
+
search: {
|
|
6
|
+
get: string;
|
|
7
|
+
set: Dispatch<React.SetStateAction<string>>;
|
|
8
|
+
};
|
|
9
|
+
dateFilters: {
|
|
10
|
+
get: Record<string, {
|
|
11
|
+
from: Date | null;
|
|
12
|
+
to: Date | null;
|
|
13
|
+
}>;
|
|
14
|
+
set: Dispatch<SetStateAction<Record<string, {
|
|
15
|
+
from: Date | null;
|
|
16
|
+
to: Date | null;
|
|
17
|
+
}>>>;
|
|
18
|
+
};
|
|
19
|
+
selectFilters: {
|
|
20
|
+
get: {
|
|
21
|
+
[key: string]: (string | null)[];
|
|
22
|
+
};
|
|
23
|
+
set: Dispatch<SetStateAction<{
|
|
24
|
+
[key: string]: (string | null)[];
|
|
25
|
+
}>>;
|
|
26
|
+
};
|
|
27
|
+
selectedFilters: {
|
|
28
|
+
get: Record<string, Set<string | null>>;
|
|
29
|
+
set: Dispatch<SetStateAction<Record<string, Set<string | null>>>>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
declare const Filter: ({ states }: IProps) => React.JSX.Element;
|
|
34
|
+
export default Filter;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import DateFilters from "./DateFilters";
|
|
4
|
+
import SelectFilters from "./SelectFilters";
|
|
5
|
+
import React from "react";
|
|
6
|
+
import Input from "../../../form/input";
|
|
7
|
+
const Filter = ({ states }) => {
|
|
8
|
+
// states
|
|
9
|
+
const [openName, setOpenName] = useState(null);
|
|
10
|
+
// methods
|
|
11
|
+
const handleOpen = (name) => setOpenName(openName === name ? null : name);
|
|
12
|
+
return (React.createElement("div", { className: "filters" },
|
|
13
|
+
React.createElement(Input, { variant: "borderless", placeholder: "Filter by keyword", onChange: (event) => states.search.set(event.target.value.toLocaleLowerCase()) }),
|
|
14
|
+
React.createElement("ul", null,
|
|
15
|
+
React.createElement(DateFilters, { states: {
|
|
16
|
+
dateFilters: {
|
|
17
|
+
get: states.dateFilters.get,
|
|
18
|
+
set: states.dateFilters.set,
|
|
19
|
+
},
|
|
20
|
+
openName: { get: openName },
|
|
21
|
+
}, methods: {
|
|
22
|
+
open: handleOpen,
|
|
23
|
+
} }),
|
|
24
|
+
React.createElement(SelectFilters, { states: {
|
|
25
|
+
selectFilters: {
|
|
26
|
+
get: states.selectFilters.get,
|
|
27
|
+
set: states.selectFilters.set,
|
|
28
|
+
},
|
|
29
|
+
selectedFilters: {
|
|
30
|
+
get: states.selectedFilters.get,
|
|
31
|
+
set: states.selectedFilters.set,
|
|
32
|
+
},
|
|
33
|
+
openName: { get: openName },
|
|
34
|
+
}, methods: { open: handleOpen } }))));
|
|
35
|
+
};
|
|
36
|
+
export default Filter;
|
|
@@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import "../../../assets/css/components/data-display/kanban-board/styles.css";
|
|
4
4
|
import DnD from "../dnd";
|
|
5
5
|
import { ARIcon } from "../../icons";
|
|
6
|
+
import Filter from "./filter";
|
|
6
7
|
const KanbanBoard = function ({ trackBy, columns, onChange, config, }) {
|
|
7
8
|
// refs
|
|
8
9
|
const _kanbanWrapper = useRef(null);
|
|
@@ -12,6 +13,11 @@ const KanbanBoard = function ({ trackBy, columns, onChange, config, }) {
|
|
|
12
13
|
const _scrollSpeedRef = useRef(0); // px/frame
|
|
13
14
|
// states
|
|
14
15
|
const [data, setData] = useState([]);
|
|
16
|
+
// states -> Filters
|
|
17
|
+
const [search, setSearch] = useState("");
|
|
18
|
+
const [selectFilters, setSelectFilters] = useState({});
|
|
19
|
+
const [selectedFilters, setSelectedFilters] = useState({});
|
|
20
|
+
const [dateFilters, setDateFilters] = useState({});
|
|
15
21
|
// methods
|
|
16
22
|
const handleBoardDragOver = (event) => {
|
|
17
23
|
event.preventDefault();
|
|
@@ -130,33 +136,125 @@ const KanbanBoard = function ({ trackBy, columns, onChange, config, }) {
|
|
|
130
136
|
.slice(1));
|
|
131
137
|
};
|
|
132
138
|
// useEffects
|
|
133
|
-
useEffect(() =>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const selectMap = new Map();
|
|
141
|
+
const dateMap = new Map();
|
|
142
|
+
columns.forEach((col) => {
|
|
143
|
+
col.items.forEach((item) => {
|
|
144
|
+
const keys = config?.filter?.keys(item);
|
|
145
|
+
keys?.forEach((k) => {
|
|
146
|
+
if (k.type === "select") {
|
|
147
|
+
if (!selectMap.has(k.name))
|
|
148
|
+
selectMap.set(k.name, new Set());
|
|
149
|
+
selectMap.get(k.name).add(k.key ?? null);
|
|
150
|
+
}
|
|
151
|
+
if (k.type === "date")
|
|
152
|
+
dateMap.set(k.name, true);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
setSelectFilters(Object.fromEntries(Array.from(selectMap.entries()).map(([name, set]) => [name, Array.from(set)])));
|
|
157
|
+
setDateFilters((prev) => {
|
|
158
|
+
const next = { ...prev };
|
|
159
|
+
Array.from(dateMap.keys()).forEach((name) => {
|
|
160
|
+
if (!next[name]) {
|
|
161
|
+
next[name] = { from: null, to: null };
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return next;
|
|
165
|
+
});
|
|
166
|
+
}, [columns]);
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
let nextData = columns.map((col) => ({
|
|
169
|
+
...col,
|
|
170
|
+
items: [...col.items],
|
|
171
|
+
}));
|
|
172
|
+
// Search varsa...
|
|
173
|
+
if (config?.filter?.search && search?.trim()) {
|
|
174
|
+
const q = search.trim();
|
|
175
|
+
nextData = nextData.map((col) => ({
|
|
176
|
+
...col,
|
|
177
|
+
items: col.items.filter((item) => config.filter.search(item, q)),
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
// Select ve Date varsa...
|
|
181
|
+
nextData = nextData.map((col) => ({
|
|
182
|
+
...col,
|
|
183
|
+
items: col.items.filter((item) => {
|
|
184
|
+
const keys = config?.filter?.keys(item) ?? [];
|
|
185
|
+
// Select (checkbox)
|
|
186
|
+
const selectOk = Object.entries(selectedFilters).every(([filterName, selectedSet]) => {
|
|
187
|
+
if (!selectedSet || selectedSet.size === 0)
|
|
188
|
+
return true;
|
|
189
|
+
const value = keys.find((k) => k.name === filterName)?.key ?? null;
|
|
190
|
+
return selectedSet.has(value);
|
|
191
|
+
});
|
|
192
|
+
if (!selectOk)
|
|
193
|
+
return false;
|
|
194
|
+
// Date (range)
|
|
195
|
+
const dateOk = Object.entries(dateFilters).every(([filterName, range]) => {
|
|
196
|
+
if (!range.from && !range.to)
|
|
197
|
+
return true;
|
|
198
|
+
const raw = keys.find((k) => k.name === filterName)?.key;
|
|
199
|
+
if (!raw)
|
|
200
|
+
return false;
|
|
201
|
+
const d = new Date(raw);
|
|
202
|
+
if (range.from && d < range.from)
|
|
203
|
+
return false;
|
|
204
|
+
if (range.to && d > range.to)
|
|
205
|
+
return false;
|
|
206
|
+
return true;
|
|
207
|
+
});
|
|
208
|
+
return dateOk;
|
|
209
|
+
}),
|
|
210
|
+
}));
|
|
211
|
+
setData(nextData);
|
|
212
|
+
}, [columns, search, selectedFilters, dateFilters]);
|
|
213
|
+
return (React.createElement(React.Fragment, null,
|
|
214
|
+
config?.filter && (React.createElement(Filter, { states: {
|
|
215
|
+
search: {
|
|
216
|
+
get: search,
|
|
217
|
+
set: setSearch,
|
|
218
|
+
},
|
|
219
|
+
dateFilters: {
|
|
220
|
+
get: dateFilters,
|
|
221
|
+
set: setDateFilters,
|
|
222
|
+
},
|
|
223
|
+
selectFilters: {
|
|
224
|
+
get: selectFilters,
|
|
225
|
+
set: setSelectFilters,
|
|
226
|
+
},
|
|
227
|
+
selectedFilters: {
|
|
228
|
+
get: selectedFilters,
|
|
229
|
+
set: setSelectedFilters,
|
|
230
|
+
},
|
|
231
|
+
} })),
|
|
232
|
+
React.createElement("div", { ref: _kanbanWrapper, className: "ar-kanban-board", style: {
|
|
233
|
+
height: `calc(100dvh - (${_kanbanWrapper.current?.getBoundingClientRect().top}px + ${config?.safeAreaOffset?.bottom ?? 0}px))`,
|
|
234
|
+
}, onDragOver: handleBoardDragOver, onDragEnd: stopScrolling, onDrop: stopScrolling },
|
|
235
|
+
React.createElement("div", { className: "buttons" },
|
|
236
|
+
React.createElement("div", { className: "button left", onMouseDown: () => handleStartScroll("left"), onMouseUp: handleStopScroll, onMouseLeave: handleStopScroll },
|
|
237
|
+
React.createElement(ARIcon, { icon: "ArrowLeft" })),
|
|
238
|
+
React.createElement("div", { className: "button right", onMouseDown: () => handleStartScroll("right"), onMouseUp: handleStopScroll, onMouseLeave: handleStopScroll },
|
|
239
|
+
React.createElement(ARIcon, { icon: "ArrowRight" }))),
|
|
240
|
+
React.createElement("div", { className: "titles" }, data.map((board, index) => (React.createElement("div", { key: index, className: "title" },
|
|
241
|
+
React.createElement("h4", null,
|
|
242
|
+
React.createElement("span", { style: {
|
|
243
|
+
backgroundColor: darkenColor(board.titleColor ?? "", 1),
|
|
244
|
+
borderColor: darkenColor(board.titleColor ?? "", 1),
|
|
245
|
+
} }),
|
|
246
|
+
board.title.toLocaleUpperCase("tr")),
|
|
247
|
+
board.description && React.createElement("span", null, board.description))))),
|
|
248
|
+
React.createElement("div", { className: "columns" }, data.map((board, index) => (React.createElement("div", { key: index, className: "column", onDrop: handleDrop(board.key) },
|
|
249
|
+
React.createElement("div", { className: "items", onDragOver: handleItemsDragOver, onDragLeave: handleItemsDragLeave, onDrop: handleItemsDrop },
|
|
250
|
+
React.createElement(DnD, { key: board.key, data: board.items, renderItem: (item, dndIndex) => {
|
|
251
|
+
return (React.createElement("div", { key: dndIndex, className: "item", onDragOver: (event) => {
|
|
252
|
+
event.preventDefault();
|
|
253
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
254
|
+
const mouseY = event.clientY;
|
|
255
|
+
const isBelow = mouseY > rect.top + rect.height / 2;
|
|
256
|
+
_hoverItemIndex.current = isBelow ? index + 1 : index;
|
|
257
|
+
} }, board.renderItem(item, index)));
|
|
258
|
+
}, columnKey: board.key, confing: { isMoveIcon: false } })))))))));
|
|
161
259
|
};
|
|
162
260
|
export default KanbanBoard;
|
|
@@ -25,6 +25,7 @@ const DatePicker = ({ variant, color, onChange, config, validation, ...attribute
|
|
|
25
25
|
// refs
|
|
26
26
|
const _arCalendar = useRef(null);
|
|
27
27
|
const _arClock = useRef(null);
|
|
28
|
+
const _placeholder = useRef(null);
|
|
28
29
|
const _calendarHeader = useRef(null);
|
|
29
30
|
const _calendarFooter = useRef(null);
|
|
30
31
|
const _clockHeader = useRef(null);
|
|
@@ -247,45 +248,61 @@ const DatePicker = ({ variant, color, onChange, config, validation, ...attribute
|
|
|
247
248
|
setYears(years);
|
|
248
249
|
}, [selectedYear]);
|
|
249
250
|
return (React.createElement("div", { className: "ar-date-picker" },
|
|
250
|
-
attributes.placeholder && attributes.placeholder.length > 0 && (React.createElement("label",
|
|
251
|
+
attributes.placeholder && attributes.placeholder.length > 0 && (React.createElement("label", { ref: _placeholder },
|
|
251
252
|
validation ? "* " : "",
|
|
252
253
|
attributes.placeholder)),
|
|
253
|
-
React.createElement(
|
|
254
|
-
|
|
254
|
+
React.createElement("div", { className: "wrapper", ...(String(attributes.value).length > 0
|
|
255
|
+
? {
|
|
256
|
+
style: {
|
|
257
|
+
clipPath: `polygon(
|
|
258
|
+
-15px 0,
|
|
259
|
+
10px -5px,
|
|
260
|
+
10px 5px,
|
|
261
|
+
calc(${_placeholder.current?.getBoundingClientRect().width}px + 7px) 5px,
|
|
262
|
+
calc(${_placeholder.current?.getBoundingClientRect().width}px + 7px) -5px,
|
|
263
|
+
100% -70px,
|
|
264
|
+
calc(100% + 5px) calc(100% + 5px),
|
|
265
|
+
-5px calc(100% + 5px)
|
|
266
|
+
)`,
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
: {}) },
|
|
270
|
+
React.createElement(Input, { ref: _beginDate, variant: variant, color: color, ...attributes, value: DATE.ParseValue(String(attributes.value), config?.isClock), type: config?.isClock ? "datetime-local" : "date", onKeyDown: (event) => {
|
|
271
|
+
if (event.code === "Space")
|
|
272
|
+
event.preventDefault();
|
|
273
|
+
else if (event.code === "Enter")
|
|
274
|
+
handleOk();
|
|
275
|
+
}, onChange: (event) => {
|
|
276
|
+
// Disabled gelmesi durumunda işlem yapmasına izin verme...
|
|
277
|
+
if (attributes.disabled)
|
|
278
|
+
return;
|
|
279
|
+
(() => {
|
|
280
|
+
if (!calendarIsOpen)
|
|
281
|
+
setCalendarIsOpen(true);
|
|
282
|
+
const value = event.target.value;
|
|
283
|
+
const [date, time] = value.split("T");
|
|
284
|
+
const [year, month, day] = date.split("-").map(Number);
|
|
285
|
+
const hours = time ? time.split(".")[0].split(":").map(Number)[0] : 0;
|
|
286
|
+
const minutes = time ? time.split(".")[0].split(":").map(Number)[1] : 0;
|
|
287
|
+
_year.current = year;
|
|
288
|
+
_month.current = month - 1;
|
|
289
|
+
_day.current = day;
|
|
290
|
+
if (hours || minutes) {
|
|
291
|
+
_hours.current = hours;
|
|
292
|
+
_minutes.current = minutes;
|
|
293
|
+
}
|
|
294
|
+
// Yıl ve Ay'ı anlık yeniler.
|
|
295
|
+
setSelectedYear(_year.current);
|
|
296
|
+
setSelectedMonth(_month.current);
|
|
297
|
+
// Takvimi anlık yeniler.
|
|
298
|
+
setDateChanged((prev) => !prev);
|
|
299
|
+
setTimeChanged((prev) => !prev);
|
|
300
|
+
onChange(value);
|
|
301
|
+
})();
|
|
302
|
+
}, onClick: (event) => {
|
|
255
303
|
event.preventDefault();
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}, onChange: (event) => {
|
|
259
|
-
// Disabled gelmesi durumunda işlem yapmasına izin verme...
|
|
260
|
-
if (attributes.disabled)
|
|
261
|
-
return;
|
|
262
|
-
(() => {
|
|
263
|
-
if (!calendarIsOpen)
|
|
264
|
-
setCalendarIsOpen(true);
|
|
265
|
-
const value = event.target.value;
|
|
266
|
-
const [date, time] = value.split("T");
|
|
267
|
-
const [year, month, day] = date.split("-").map(Number);
|
|
268
|
-
const hours = time ? time.split(".")[0].split(":").map(Number)[0] : 0;
|
|
269
|
-
const minutes = time ? time.split(".")[0].split(":").map(Number)[1] : 0;
|
|
270
|
-
_year.current = year;
|
|
271
|
-
_month.current = month - 1;
|
|
272
|
-
_day.current = day;
|
|
273
|
-
if (hours || minutes) {
|
|
274
|
-
_hours.current = hours;
|
|
275
|
-
_minutes.current = minutes;
|
|
276
|
-
}
|
|
277
|
-
// Yıl ve Ay'ı anlık yeniler.
|
|
278
|
-
setSelectedYear(_year.current);
|
|
279
|
-
setSelectedMonth(_month.current);
|
|
280
|
-
// Takvimi anlık yeniler.
|
|
281
|
-
setDateChanged((prev) => !prev);
|
|
282
|
-
setTimeChanged((prev) => !prev);
|
|
283
|
-
onChange(value);
|
|
284
|
-
})();
|
|
285
|
-
}, onClick: (event) => {
|
|
286
|
-
event.preventDefault();
|
|
287
|
-
setCalendarIsOpen(true);
|
|
288
|
-
}, autoComplete: "off", validation: validation }),
|
|
304
|
+
setCalendarIsOpen(true);
|
|
305
|
+
}, autoComplete: "off", validation: validation })),
|
|
289
306
|
calendarIsOpen &&
|
|
290
307
|
ReactDOM.createPortal(React.createElement("div", { ref: _arCalendar, className: "ar-date-calendar" },
|
|
291
308
|
React.createElement("div", { ref: _calendarHeader, className: "header" },
|