@flux-ui/components 3.0.0-next.56 → 3.0.0-next.58

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,7 +1,212 @@
1
+ @use '$flux/css/mixin';
2
+
3
+ /* region root */
4
+
1
5
  .kanban {
6
+ position: relative;
2
7
  display: flex;
3
8
  flex-flow: row;
4
9
  gap: 15px;
10
+ block-size: 100%;
11
+ inline-size: 100%;
5
12
  overflow-x: auto;
6
13
  padding-bottom: 6px;
7
14
  }
15
+
16
+ .kanbanLiveRegion {
17
+ position: absolute;
18
+ width: 1px;
19
+ height: 1px;
20
+ margin: -1px;
21
+ padding: 0;
22
+ border: 0;
23
+ overflow: hidden;
24
+ clip: rect(0, 0, 0, 0);
25
+ white-space: nowrap;
26
+ }
27
+
28
+ /* endregion */
29
+
30
+ /* region column */
31
+
32
+ .kanbanColumn {
33
+ display: flex;
34
+ flex-flow: column;
35
+ flex: 1 0 300px;
36
+ background: var(--gray-100);
37
+ border: 1px solid var(--gray-200);
38
+ border-radius: var(--radius);
39
+ overflow: hidden;
40
+ transition: opacity 180ms var(--swift-out);
41
+ }
42
+
43
+ .kanbanColumn.isColumnDragging {
44
+ opacity: .4;
45
+ }
46
+
47
+ .kanbanColumn.isColumnDropBefore {
48
+ box-shadow: -3px 0 0 var(--primary-500);
49
+ }
50
+
51
+ .kanbanColumnHeader {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 9px;
55
+ padding: 12px 15px;
56
+ border-bottom: 1px solid var(--gray-200);
57
+
58
+ @include mixin.focus-ring(-2);
59
+ }
60
+
61
+ .kanbanColumn.isReorderable .kanbanColumnHeader {
62
+ cursor: grab;
63
+ }
64
+
65
+ .kanbanColumn.isReorderable .kanbanColumnHeader:active {
66
+ cursor: grabbing;
67
+ }
68
+
69
+ .kanbanColumnLabel {
70
+ flex: 1;
71
+ font-size: .8125rem;
72
+ font-weight: 600;
73
+ color: var(--foreground);
74
+ letter-spacing: .01em;
75
+ text-transform: uppercase;
76
+ }
77
+
78
+ .kanbanColumnBody {
79
+ display: flex;
80
+ flex-flow: column;
81
+ gap: 9px;
82
+ padding: 9px;
83
+ min-height: 60px;
84
+ flex: 1;
85
+ overflow-y: auto;
86
+ transition: background 180ms var(--swift-out);
87
+ }
88
+
89
+ .isOver .kanbanColumnBody {
90
+ background: rgb(from var(--primary-500) r g b / .06);
91
+ }
92
+
93
+ .isOver.isDropDisallowed .kanbanColumnBody {
94
+ background: rgb(from var(--danger-500) r g b / .06);
95
+ cursor: not-allowed;
96
+ }
97
+
98
+ .isBoardDragging .kanbanColumn:not(.isOver):not(.isDisabled) .kanbanColumnBody {
99
+ background: rgb(from var(--primary-500) r g b / .02);
100
+ }
101
+
102
+ .kanbanColumn.isDisabled {
103
+ opacity: .6;
104
+ cursor: not-allowed;
105
+ }
106
+
107
+ .kanbanColumn.isDisabled .kanbanColumnBody {
108
+ pointer-events: none;
109
+ }
110
+
111
+ .kanbanColumnEmpty {
112
+ display: flex;
113
+ flex: 1;
114
+ align-items: center;
115
+ justify-content: center;
116
+ padding: 18px 12px;
117
+ font-size: .8125rem;
118
+ color: var(--gray-500);
119
+ text-align: center;
120
+ }
121
+
122
+ .kanbanColumnFooter {
123
+ padding: 9px 15px;
124
+ border-top: 1px solid var(--gray-200);
125
+ }
126
+
127
+ .kanbanDropIndicator {
128
+ flex-shrink: 0;
129
+ height: 2px;
130
+ border-radius: 999px;
131
+ background: transparent;
132
+ transition: background 180ms var(--swift-out);
133
+ }
134
+
135
+ .isDropEndActive {
136
+ background: var(--primary-500);
137
+ }
138
+
139
+ .isDropEndActive.isDropEndDisallowed {
140
+ background: var(--danger-500);
141
+ }
142
+
143
+ /* endregion */
144
+
145
+ /* region card */
146
+
147
+ .kanbanCard {
148
+ position: relative;
149
+ padding: 12px;
150
+ background: var(--gray-25);
151
+ border: 1px solid var(--gray-200);
152
+ border-radius: var(--radius);
153
+ cursor: grab;
154
+ scroll-margin: 9px;
155
+ transition: opacity 180ms var(--swift-out), box-shadow 180ms var(--swift-out), transform 180ms var(--swift-out);
156
+ user-select: none;
157
+
158
+ @include mixin.focus-ring(-2);
159
+
160
+ &:active {
161
+ cursor: grabbing;
162
+ }
163
+
164
+ &:hover {
165
+ box-shadow: 0 1px 4px rgb(0 0 0 / .08);
166
+ }
167
+ }
168
+
169
+ .kanbanCard.isDisabled {
170
+ cursor: not-allowed;
171
+ opacity: .6;
172
+
173
+ &:hover {
174
+ box-shadow: none;
175
+ }
176
+
177
+ &:active {
178
+ cursor: not-allowed;
179
+ }
180
+ }
181
+
182
+ .isDragging {
183
+ opacity: .4;
184
+ cursor: grabbing;
185
+ }
186
+
187
+ .isGrabbed {
188
+ transform: scale(1.04);
189
+ background: var(--surface);
190
+ box-shadow: 0 0 0 2px var(--primary-500), 0 8px 24px rgb(0 0 0 / .15);
191
+ z-index: 1;
192
+ }
193
+
194
+ .isDropBefore {
195
+ &::before {
196
+ content: '';
197
+ position: absolute;
198
+ inset-inline: 0;
199
+ top: -6px;
200
+ height: 2px;
201
+ border-radius: 999px;
202
+ background: var(--primary-500);
203
+ }
204
+ }
205
+
206
+ .isDropBefore.isDropBeforeDisallowed {
207
+ &::before {
208
+ background: var(--danger-500);
209
+ }
210
+ }
211
+
212
+ /* endregion */
package/src/data/di.ts CHANGED
@@ -11,24 +11,57 @@ export const FluxFormFieldInjectionKey: InjectionKey<FluxFormFieldInjection> = S
11
11
  export const FluxTableInjectionKey: InjectionKey<FluxTableInjection> = Symbol();
12
12
  export const FluxTooltipInjectionKey: InjectionKey<FluxTooltipInjection> = Symbol();
13
13
 
14
+ export type FluxKanbanDragMode = 'pointer' | 'keyboard';
15
+
14
16
  export type FluxKanbanDragState = {
17
+ readonly mode: FluxKanbanDragMode;
15
18
  readonly cardId: string | number;
16
19
  readonly fromColumnId: string | number;
17
20
  readonly dropColumnId: string | number | null;
18
21
  readonly beforeCardId: string | number | null;
22
+ readonly originBeforeCardId?: string | number | null;
23
+ };
24
+
25
+ export type FluxKanbanColumnDragState = {
26
+ readonly columnId: string | number;
27
+ readonly dropBeforeColumnId: string | number | null;
19
28
  };
20
29
 
30
+ export type FluxKanbanKeyboardDirection = 'up' | 'down' | 'left' | 'right';
31
+
21
32
  export type FluxKanbanInjection = {
33
+ readonly disabled: Ref<boolean>;
34
+ readonly reorderableColumns: Ref<boolean>;
22
35
  readonly dragState: Ref<FluxKanbanDragState | null>;
36
+ readonly columnDragState: Ref<FluxKanbanColumnDragState | null>;
37
+ readonly isDropAllowed: Ref<boolean>;
23
38
 
24
39
  registerCard(element: Element, cardId: string | number): void;
25
40
  unregisterCard(element: Element): void;
26
41
  getCardInfo(element: Element): { readonly cardId: string | number } | undefined;
42
+ registerColumn(element: Element, columnId: string | number): void;
43
+ unregisterColumn(element: Element): void;
44
+ getColumnInfo(element: Element): { readonly columnId: string | number } | undefined;
45
+ setBoardElement(element: Element | null): void;
46
+ setColumnBodyElement(columnId: string | number, element: Element | null): void;
47
+
27
48
  startDrag(cardId: string | number, fromColumnId: string | number): void;
28
49
  endDrag(): void;
29
50
  updateDropTarget(columnId: string | number, beforeCardId: string | number | null): void;
30
51
  clearDropTarget(): void;
31
52
  commitDrop(): void;
53
+
54
+ grabCard(cardId: string | number, fromColumnId: string | number): void;
55
+ moveKeyboard(direction: FluxKanbanKeyboardDirection): void;
56
+ commitKeyboardDrop(): void;
57
+ cancelKeyboardDrop(): void;
58
+ isCardGrabbed(cardId: string | number): boolean;
59
+
60
+ startColumnDrag(columnId: string | number): void;
61
+ endColumnDrag(): void;
62
+ updateColumnDropTarget(beforeColumnId: string | number | null): void;
63
+ commitColumnDrop(): void;
64
+ onPointerMove(clientX: number, clientY: number): void;
32
65
  };
33
66
 
34
67
  export type FluxAdaptiveGroupChild = {
@@ -1,5 +1,5 @@
1
1
  import { formatNumber } from '@basmilius/utils';
2
- import type { FluxFilterDateEntry, FluxFilterDateRangeEntry, FluxFilterDateRangeSpec, FluxFilterDateSpec, FluxFilterEntryMap, FluxFilterOptionAsyncSpec, FluxFilterOptionEntry, FluxFilterOptionHeader, FluxFilterOptionItem, FluxFilterOptionSpec, FluxFilterOptionsAsyncSpec, FluxFilterOptionsEntry, FluxFilterOptionsSpec, FluxFilterRangeEntry, FluxFilterRangeSpec, FluxFilterSpecMap, FluxFilterValueSingle } from '@flux-ui/types';
2
+ import type { FluxFilterDateEntry, FluxFilterDateRangeEntry, FluxFilterDateRangeSpec, FluxFilterDateSpec, FluxFilterEntryMap, FluxFilterOptionAsyncSpec, FluxFilterOptionEntry, FluxFilterOptionHeader, FluxFilterOptionItem, FluxFilterOptionsAsyncSpec, FluxFilterOptionsEntry, FluxFilterOptionSpec, FluxFilterOptionsSpec, FluxFilterRangeEntry, FluxFilterRangeSpec, FluxFilterSpecMap, FluxFilterValueSingle } from '@flux-ui/types';
3
3
  import { DateTime } from 'luxon';
4
4
  import { useTranslate } from '$flux/composable/private';
5
5
  import type { FluxTranslate } from '$flux/data';
@@ -1,35 +0,0 @@
1
- .kanbanCard {
2
- position: relative;
3
- padding: 12px;
4
- background: var(--gray-25);
5
- border: 1px solid var(--gray-200);
6
- border-radius: var(--radius);
7
- cursor: grab;
8
- transition: opacity 180ms var(--swift-out), box-shadow 180ms var(--swift-out);
9
- user-select: none;
10
-
11
- &:active {
12
- cursor: grabbing;
13
- }
14
-
15
- &:hover {
16
- box-shadow: 0 1px 4px rgb(0 0 0 / .08);
17
- }
18
- }
19
-
20
- .isDragging {
21
- opacity: .4;
22
- cursor: grabbing;
23
- }
24
-
25
- .isDropBefore {
26
- &::before {
27
- content: '';
28
- position: absolute;
29
- inset-inline: 0;
30
- top: -6px;
31
- height: 2px;
32
- border-radius: 999px;
33
- background: var(--primary-500);
34
- }
35
- }
@@ -1,49 +0,0 @@
1
- .kanbanColumn {
2
- display: flex;
3
- flex-flow: column;
4
- flex-shrink: 0;
5
- width: 280px;
6
- background: var(--gray-100);
7
- border: 1px solid var(--gray-200);
8
- border-radius: var(--radius);
9
- overflow: hidden;
10
- }
11
-
12
- .kanbanColumnHeader {
13
- display: flex;
14
- align-items: center;
15
- gap: 9px;
16
- padding: 12px 15px;
17
- border-bottom: 1px solid var(--gray-200);
18
- }
19
-
20
- .kanbanColumnLabel {
21
- flex: 1;
22
- font-size: .8125rem;
23
- font-weight: 600;
24
- color: var(--foreground);
25
- letter-spacing: .01em;
26
- text-transform: uppercase;
27
- }
28
-
29
- .kanbanColumnBody {
30
- display: flex;
31
- flex-flow: column;
32
- gap: 9px;
33
- padding: 9px;
34
- min-height: 60px;
35
- flex: 1;
36
- overflow-y: auto;
37
- transition: background 180ms var(--swift-out);
38
- }
39
-
40
- .isOver .kanbanColumnBody {
41
- background: rgb(from var(--primary-500) r g b / .06);
42
- }
43
-
44
- .kanbanDropIndicator {
45
- height: 2px;
46
- border-radius: 999px;
47
- background: var(--primary-500);
48
- flex-shrink: 0;
49
- }