@archbase/kanban 4.0.37

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 (95) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +630 -0
  3. package/dist/archbase-kanban-4.0.37.tgz +0 -0
  4. package/dist/components/Card/Card.d.ts +26 -0
  5. package/dist/components/Card/index.d.ts +1 -0
  6. package/dist/components/CardSkeleton/CardSkeleton.d.ts +9 -0
  7. package/dist/components/CardSkeleton/index.d.ts +2 -0
  8. package/dist/components/Column/Column.d.ts +47 -0
  9. package/dist/components/Column/index.d.ts +1 -0
  10. package/dist/components/ColumnAdder/ColumnAdder.d.ts +6 -0
  11. package/dist/components/ColumnAdder/index.d.ts +1 -0
  12. package/dist/components/ColumnContent/ColumnContent.d.ts +24 -0
  13. package/dist/components/ColumnContent/index.d.ts +1 -0
  14. package/dist/components/ColumnHeader/ColumnHeader.d.ts +10 -0
  15. package/dist/components/ColumnHeader/index.d.ts +1 -0
  16. package/dist/components/DefaultCard/DefaultCard.d.ts +3 -0
  17. package/dist/components/DefaultCard/index.d.ts +1 -0
  18. package/dist/components/GenericItem/GenericItem.d.ts +26 -0
  19. package/dist/components/GenericItem/index.d.ts +1 -0
  20. package/dist/components/Kanban.d.ts +3 -0
  21. package/dist/components/index.d.ts +2 -0
  22. package/dist/components/types.d.ts +124 -0
  23. package/dist/context/KanbanContext.d.ts +5 -0
  24. package/dist/global/dnd/dropManager.d.ts +16 -0
  25. package/dist/global/dnd/useCardDnd.d.ts +22 -0
  26. package/dist/global/dnd/useColumnDnd.d.ts +29 -0
  27. package/dist/index.css +1 -0
  28. package/dist/index.d.ts +4 -0
  29. package/dist/index.js +1041 -0
  30. package/dist/utils/columnsUtils.d.ts +4 -0
  31. package/dist/utils/getPrefix.d.ts +2 -0
  32. package/dist/utils/getSharedProps.d.ts +8 -0
  33. package/dist/utils/infinite-scroll.d.ts +4 -0
  34. package/dist/utils/mergeRefs.d.ts +5 -0
  35. package/dist/utils/scroll.d.ts +2 -0
  36. package/package.json +66 -0
  37. package/src/common/_index.scss +0 -0
  38. package/src/components/Card/Card.tsx +215 -0
  39. package/src/components/Card/_Card.scss +11 -0
  40. package/src/components/Card/_index.scss +1 -0
  41. package/src/components/Card/index.ts +1 -0
  42. package/src/components/CardSkeleton/CardSkeleton.tsx +45 -0
  43. package/src/components/CardSkeleton/_CardSkeleton.scss +245 -0
  44. package/src/components/CardSkeleton/_index.scss +1 -0
  45. package/src/components/CardSkeleton/index.ts +2 -0
  46. package/src/components/Column/Column.tsx +246 -0
  47. package/src/components/Column/_Column.scss +44 -0
  48. package/src/components/Column/_index.scss +1 -0
  49. package/src/components/Column/index.ts +1 -0
  50. package/src/components/ColumnAdder/ColumnAdder.tsx +18 -0
  51. package/src/components/ColumnAdder/_ColumnAdder.scss +0 -0
  52. package/src/components/ColumnAdder/_index.scss +1 -0
  53. package/src/components/ColumnAdder/index.ts +1 -0
  54. package/src/components/ColumnContent/ColumnContent.tsx +238 -0
  55. package/src/components/ColumnContent/_ColumnContent.scss +23 -0
  56. package/src/components/ColumnContent/_index.scss +1 -0
  57. package/src/components/ColumnContent/index.ts +1 -0
  58. package/src/components/ColumnHeader/ColumnHeader.tsx +43 -0
  59. package/src/components/ColumnHeader/_ColumnHeader.scss +26 -0
  60. package/src/components/ColumnHeader/_index.scss +1 -0
  61. package/src/components/ColumnHeader/index.ts +1 -0
  62. package/src/components/DefaultCard/DefaultCard.tsx +9 -0
  63. package/src/components/DefaultCard/_DefaultCard.scss +14 -0
  64. package/src/components/DefaultCard/_index.scss +1 -0
  65. package/src/components/DefaultCard/index.ts +1 -0
  66. package/src/components/GenericItem/GenericItem.tsx +132 -0
  67. package/src/components/GenericItem/_GenericItem.scss +4 -0
  68. package/src/components/GenericItem/_index.scss +1 -0
  69. package/src/components/GenericItem/index.ts +1 -0
  70. package/src/components/Kanban.tsx +102 -0
  71. package/src/components/_Kanban.scss +8 -0
  72. package/src/components/_index.scss +9 -0
  73. package/src/components/index.ts +2 -0
  74. package/src/components/types.ts +155 -0
  75. package/src/context/KanbanContext.tsx +19 -0
  76. package/src/global/_index.scss +3 -0
  77. package/src/global/assets/styles/abstracts/_breakpoints.scss +71 -0
  78. package/src/global/assets/styles/abstracts/_colors.scss +85 -0
  79. package/src/global/assets/styles/abstracts/_functions.scss +3 -0
  80. package/src/global/assets/styles/abstracts/_index.scss +5 -0
  81. package/src/global/assets/styles/abstracts/_mixins.scss +49 -0
  82. package/src/global/assets/styles/abstracts/_padding.scss +1 -0
  83. package/src/global/assets/styles/abstracts/_variables.scss +8 -0
  84. package/src/global/assets/styles/base/_index.scss +34 -0
  85. package/src/global/dnd/dropManager.ts +301 -0
  86. package/src/global/dnd/useCardDnd.tsx +225 -0
  87. package/src/global/dnd/useColumnDnd.tsx +231 -0
  88. package/src/global/theme-default.scss +137 -0
  89. package/src/index.ts +6 -0
  90. package/src/utils/columnsUtils.ts +19 -0
  91. package/src/utils/getPrefix.ts +7 -0
  92. package/src/utils/getSharedProps.ts +18 -0
  93. package/src/utils/infinite-scroll.ts +18 -0
  94. package/src/utils/mergeRefs.ts +23 -0
  95. package/src/utils/scroll.ts +34 -0
@@ -0,0 +1,4 @@
1
+ import { BoardData, BoardItem } from '../components';
2
+ export declare const getColumnsFromDataSource: (dataSource: BoardData) => BoardItem[];
3
+ export declare const getColumnChildren: (column: BoardItem, dataSource: BoardData) => BoardItem[];
4
+ export declare const getHeaderHeight: (header: HTMLDivElement) => number;
@@ -0,0 +1,2 @@
1
+ export declare const prefix = "rkk";
2
+ export declare const withPrefix: (string: string | string[], separator?: string) => string;
@@ -0,0 +1,8 @@
1
+ import { BoardProps } from '../components';
2
+ export declare const getSharedProps: (props: BoardProps) => {
3
+ viewOnly: boolean;
4
+ virtualization: boolean;
5
+ cardsGap: number;
6
+ allowColumnAdder: boolean;
7
+ allowListFooter: (column: import('../components').BoardItem) => boolean;
8
+ };
@@ -0,0 +1,4 @@
1
+ export declare const checkIfSkeletonIsVisible: ({ columnId, limit }: {
2
+ columnId: any;
3
+ limit?: number;
4
+ }) => boolean;
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ type CallbackRef<T> = (ref: T | null) => void;
3
+ type Ref<T> = React.MutableRefObject<T> | CallbackRef<T>;
4
+ export default function mergeRefs<T>(refA?: Ref<T | null> | null, refB?: Ref<T | null> | null): React.RefCallback<T>;
5
+ export {};
@@ -0,0 +1,2 @@
1
+ import { BoardItem, ScrollEvent } from '../components';
2
+ export declare const handleScroll: (e: React.UIEvent<HTMLDivElement> | number, virtualization: boolean, onScroll: (e: ScrollEvent, column: BoardItem) => void, column: BoardItem) => void;
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@archbase/kanban",
3
+ "version": "4.0.37",
4
+ "description": "Kanban board components for Archbase React, based on react-kanban-kit with Archbase packaging",
5
+ "author": "Edson Martins <edsonmartins2005@gmail.com>",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.js"
16
+ },
17
+ "./dist/index.css": "./dist/index.css",
18
+ "./dist/cjs/index.css": "./dist/index.css",
19
+ "./dist/esm/index.css": "./dist/index.css"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src",
24
+ "README.md",
25
+ "LICENSE"
26
+ ],
27
+ "peerDependencies": {
28
+ "react": "^18.3.0 || ^19.2.0",
29
+ "react-dom": "^18.3.0 || ^19.2.0"
30
+ },
31
+ "dependencies": {
32
+ "@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
33
+ "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
34
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
35
+ "@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-autoscroll": "^2.0.0",
36
+ "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^2.1.0",
37
+ "classes": "^0.3.0",
38
+ "classnames": "^2.5.1",
39
+ "virtua": "^0.40.4"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.16.1",
43
+ "@types/react": "^19.0.6",
44
+ "@types/react-dom": "^19.0.2",
45
+ "@vitejs/plugin-react": "^4.3.4",
46
+ "react": "^19.2.3",
47
+ "react-dom": "^19.2.3",
48
+ "sass-embedded": "^1.80.7",
49
+ "typescript": "~5.7.2",
50
+ "vite": "^6.0.3",
51
+ "vite-plugin-dts": "^4.5.4",
52
+ "vitest": "^2.1.8"
53
+ },
54
+ "publishConfig": {
55
+ "registry": "http://192.168.1.110:4873"
56
+ },
57
+ "scripts": {
58
+ "dev": "NODE_OPTIONS=\"--max-old-space-size=16384\" vite build --watch",
59
+ "build": "NODE_OPTIONS=\"--max-old-space-size=16384\" vite build",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "test:coverage": "vitest run --coverage",
63
+ "lint": "eslint . --max-warnings 0",
64
+ "clean": "rm -rf dist .turbo node_modules"
65
+ }
66
+ }
File without changes
@@ -0,0 +1,215 @@
1
+ import { withPrefix } from "@/utils/getPrefix";
2
+ import React, { Fragment, memo, useMemo } from "react";
3
+ import { BoardItem, DndState } from "../types";
4
+ import { createPortal } from "react-dom";
5
+ import { TaskCardState, useCardDnd } from "@/global/dnd/useCardDnd";
6
+
7
+ export const CardShadow = memo(
8
+ ({
9
+ height,
10
+ customIndicator,
11
+ }: {
12
+ height: number;
13
+ customIndicator?: React.ReactNode;
14
+ }) => {
15
+ return (
16
+ <div className={withPrefix("card-shadow-container")}>
17
+ {customIndicator || (
18
+ <div
19
+ className={withPrefix("card-shadow")}
20
+ style={{ height: `${height - 2}px` }}
21
+ />
22
+ )}
23
+ </div>
24
+ );
25
+ },
26
+ );
27
+
28
+ const CardDisplay = (props: {
29
+ outerRef?: React.RefObject<HTMLDivElement>;
30
+ innerRef?: React.RefObject<HTMLDivElement>;
31
+ state: TaskCardState;
32
+ data: BoardItem;
33
+ column: BoardItem;
34
+ index: number;
35
+ isDraggable: boolean;
36
+ render: (props: {
37
+ data: BoardItem;
38
+ column: BoardItem;
39
+ index: number;
40
+ isDraggable: boolean;
41
+ }) => React.ReactNode;
42
+ onClick?: (e: React.MouseEvent<HTMLDivElement>, card: BoardItem) => void;
43
+ cardsGap?: number;
44
+ renderCardDragIndicator?: (card: BoardItem, info: any) => React.ReactNode;
45
+ renderGap?: (column: BoardItem) => React.ReactNode;
46
+ }) => {
47
+ const {
48
+ outerRef,
49
+ innerRef,
50
+ state,
51
+ data,
52
+ column,
53
+ index,
54
+ isDraggable,
55
+ cardsGap,
56
+ render,
57
+ onClick,
58
+ renderCardDragIndicator,
59
+ } = props;
60
+
61
+ const containerStyle = useMemo(() => {
62
+ const styles: React.CSSProperties = {};
63
+ if (state.type === "is-dragging-and-left-self") {
64
+ styles.display = "none";
65
+ }
66
+ return styles;
67
+ }, [state.type]);
68
+
69
+ const innerStyle = useMemo(() => {
70
+ if (state.type === "is-dragging") {
71
+ return { opacity: 0.6 };
72
+ }
73
+ if (state.type === "preview") {
74
+ return {
75
+ width: state.dragging.width,
76
+ height: state.dragging.height,
77
+ transform: "rotate(4deg)",
78
+ };
79
+ }
80
+ return {};
81
+ }, [state]);
82
+
83
+ const showTopShadow = state.type === "is-over" && state.closestEdge === "top";
84
+ const showBottomShadow =
85
+ state.type === "is-over" && state.closestEdge === "bottom";
86
+ const shadowHeight = state.type === "is-over" ? state.dragging.height : 0;
87
+ const renderContent = render({ data, column, index, isDraggable });
88
+ const customIndicator = renderCardDragIndicator?.(
89
+ state.type === "is-dragging" ? data : null,
90
+ {
91
+ height: shadowHeight,
92
+ },
93
+ );
94
+
95
+ return (
96
+ <Fragment>
97
+ <div
98
+ ref={outerRef}
99
+ className={withPrefix("card-outer")}
100
+ onClick={(e) => onClick?.(e, data)}
101
+ style={{
102
+ ...containerStyle,
103
+ ...(cardsGap !== undefined ? { marginBottom: cardsGap } : {}),
104
+ }}
105
+ data-test-id={data?.id}
106
+ data-rkk-column={column?.id}
107
+ data-rkk-index={index}
108
+ >
109
+ {showTopShadow && (
110
+ <CardShadow height={shadowHeight} customIndicator={customIndicator} />
111
+ )}
112
+ <div
113
+ ref={innerRef}
114
+ className={withPrefix("card-inner")}
115
+ style={{
116
+ ...innerStyle,
117
+ marginBottom: showBottomShadow ? cardsGap : 0,
118
+ marginTop: showTopShadow ? cardsGap : 0,
119
+ }}
120
+ >
121
+ {renderContent}
122
+ </div>
123
+ {showBottomShadow && (
124
+ <CardShadow height={shadowHeight} customIndicator={customIndicator} />
125
+ )}
126
+ </div>
127
+ {/* {renderGap?.(column)} */}
128
+ </Fragment>
129
+ );
130
+ };
131
+
132
+ interface Props {
133
+ render: (props: {
134
+ data: BoardItem;
135
+ column: BoardItem;
136
+ index: number;
137
+ isDraggable: boolean;
138
+ }) => React.ReactNode;
139
+ data: BoardItem;
140
+ column: BoardItem;
141
+ index: number;
142
+ isDraggable: boolean;
143
+ onClick?: (e: React.MouseEvent<HTMLDivElement>, card: BoardItem) => void;
144
+ cardsGap?: number;
145
+ renderGap?: (column: BoardItem) => React.ReactNode;
146
+ onCardDndStateChange?: (info: DndState) => void;
147
+ renderCardDragIndicator?: (card: BoardItem, info: any) => React.ReactNode;
148
+ renderCardDragPreview?: (card: BoardItem, info: any) => React.ReactNode;
149
+ }
150
+
151
+ const Card = (props: Props) => {
152
+ const {
153
+ render,
154
+ data,
155
+ column,
156
+ index,
157
+ isDraggable,
158
+ cardsGap,
159
+ onClick,
160
+ onCardDndStateChange,
161
+ renderCardDragIndicator,
162
+ renderCardDragPreview,
163
+ renderGap,
164
+ } = props;
165
+ const { outerRef, innerRef, state } = useCardDnd(
166
+ data,
167
+ column,
168
+ index,
169
+ isDraggable,
170
+ onCardDndStateChange,
171
+ );
172
+
173
+ return (
174
+ <>
175
+ <CardDisplay
176
+ outerRef={outerRef}
177
+ innerRef={innerRef}
178
+ state={state}
179
+ data={data}
180
+ column={column}
181
+ index={index}
182
+ isDraggable={isDraggable}
183
+ render={render}
184
+ onClick={onClick}
185
+ cardsGap={cardsGap}
186
+ renderCardDragIndicator={renderCardDragIndicator}
187
+ renderGap={renderGap}
188
+ />
189
+
190
+ {state.type === "preview"
191
+ ? createPortal(
192
+ renderCardDragPreview?.(data, {
193
+ state,
194
+ data,
195
+ column,
196
+ index,
197
+ isDraggable,
198
+ }) || (
199
+ <CardDisplay
200
+ state={state}
201
+ data={data}
202
+ column={column}
203
+ index={index}
204
+ isDraggable={isDraggable}
205
+ render={render}
206
+ />
207
+ ),
208
+ state.container,
209
+ )
210
+ : null}
211
+ </>
212
+ );
213
+ };
214
+
215
+ export default Card;
@@ -0,0 +1,11 @@
1
+ @use "../../global/assets/styles/abstracts/variables" as *;
2
+
3
+ .#{$prefix}-card-shadow-container {
4
+ position: relative;
5
+ }
6
+
7
+ .#{$prefix}-card-shadow {
8
+ border-radius: 8px;
9
+ background-color: #ffffffb7;
10
+ border: 1px solid var(--Schemes-Outline-Variant, #e8ecf5);
11
+ }
@@ -0,0 +1 @@
1
+ @forward "./Card";
@@ -0,0 +1 @@
1
+ export { default } from "./Card";
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import { withPrefix } from "@/utils/getPrefix";
3
+
4
+ export type SkeletonAnimationType = "shimmer" | "pulse" | "wave";
5
+
6
+ interface CardSkeletonProps {
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ animationType?: SkeletonAnimationType;
10
+ }
11
+
12
+ const CardSkeleton: React.FC<CardSkeletonProps> = ({
13
+ className,
14
+ style,
15
+ animationType = "shimmer",
16
+ }) => {
17
+ const skeletonClass = `${withPrefix("skeleton")} ${
18
+ animationType === "pulse" ? withPrefix("skeleton-pulse") : ""
19
+ } ${animationType === "wave" ? withPrefix("skeleton-wave") : ""} ${
20
+ className || ""
21
+ }`.trim();
22
+
23
+ const renderDefaultSkeleton = () => (
24
+ <div className={withPrefix("skeleton-content")}>
25
+ <div className={withPrefix("skeleton-title")}></div>
26
+
27
+ <div className={withPrefix("skeleton-description")}>
28
+ <div className={withPrefix("skeleton-line")}></div>
29
+ <div
30
+ className={`${withPrefix("skeleton-line")} ${withPrefix(
31
+ "skeleton-line-short"
32
+ )}`}
33
+ ></div>
34
+ </div>
35
+ </div>
36
+ );
37
+
38
+ return (
39
+ <div className={skeletonClass} style={style}>
40
+ {renderDefaultSkeleton()}
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export default CardSkeleton;
@@ -0,0 +1,245 @@
1
+ @use "../../global/assets/styles/abstracts/variables" as *;
2
+
3
+ // Shimmer animation keyframes
4
+ @keyframes skeleton-shimmer {
5
+ 0% {
6
+ background-position: -200px 0;
7
+ }
8
+ 100% {
9
+ background-position: calc(200px + 100%) 0;
10
+ }
11
+ }
12
+
13
+ // Wave animation keyframes
14
+ @keyframes skeleton-wave {
15
+ 0% {
16
+ transform: translateX(-100%);
17
+ }
18
+ 50% {
19
+ transform: translateX(100%);
20
+ }
21
+ 100% {
22
+ transform: translateX(100%);
23
+ }
24
+ }
25
+
26
+ // Pulse animation keyframes
27
+ @keyframes skeleton-pulse {
28
+ 0%,
29
+ 100% {
30
+ opacity: 1;
31
+ }
32
+ 50% {
33
+ opacity: 0.4;
34
+ }
35
+ }
36
+
37
+ .#{$prefix}-skeleton {
38
+ border-radius: 8px;
39
+ border: 1px solid #e8ecf5;
40
+ background: #fff;
41
+ padding: 16px;
42
+ margin-bottom: 8px;
43
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
44
+ transition: box-shadow 0.2s ease;
45
+ position: relative;
46
+ overflow: hidden;
47
+
48
+ &:hover {
49
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
50
+ }
51
+
52
+ &-content {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: 12px;
56
+ }
57
+
58
+ // Base skeleton element styles
59
+ %skeleton-base {
60
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
61
+ background-size: 200px 100%;
62
+ animation: skeleton-shimmer 1.5s infinite ease-in-out;
63
+ border-radius: 4px;
64
+ position: relative;
65
+ }
66
+
67
+ // Wave animation base
68
+ %skeleton-wave-base {
69
+ background: #f0f0f0;
70
+ position: relative;
71
+ overflow: hidden;
72
+ border-radius: 4px;
73
+
74
+ &::after {
75
+ position: absolute;
76
+ top: 0;
77
+ right: 0;
78
+ bottom: 0;
79
+ left: 0;
80
+ transform: translateX(-100%);
81
+ background: linear-gradient(
82
+ 90deg,
83
+ rgba(255, 255, 255, 0) 0,
84
+ rgba(255, 255, 255, 0.2) 20%,
85
+ rgba(255, 255, 255, 0.5) 60%,
86
+ rgba(255, 255, 255, 0)
87
+ );
88
+ animation: skeleton-wave 2s infinite;
89
+ content: "";
90
+ }
91
+ }
92
+
93
+ // Title skeleton
94
+ &-title {
95
+ @extend %skeleton-base;
96
+ height: 20px;
97
+ width: 80%;
98
+ border-radius: 6px;
99
+ }
100
+
101
+ // Description section
102
+ &-description {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 8px;
106
+ }
107
+
108
+ &-line {
109
+ @extend %skeleton-base;
110
+ height: 14px;
111
+ width: 100%;
112
+
113
+ &-short {
114
+ width: 65%;
115
+ }
116
+ }
117
+
118
+ // Priority indicator
119
+ &-priority {
120
+ @extend %skeleton-base;
121
+ height: 4px;
122
+ width: 40px;
123
+ border-radius: 2px;
124
+ margin-bottom: 4px;
125
+ }
126
+
127
+ // Tags section
128
+ &-tags {
129
+ display: flex;
130
+ gap: 8px;
131
+ flex-wrap: wrap;
132
+ }
133
+
134
+ &-tag {
135
+ @extend %skeleton-base;
136
+ height: 20px;
137
+ width: 60px;
138
+ border-radius: 12px;
139
+
140
+ &:nth-child(2) {
141
+ width: 45px;
142
+ }
143
+
144
+ &:nth-child(3) {
145
+ width: 55px;
146
+ }
147
+ }
148
+
149
+ // Footer section
150
+ &-footer {
151
+ display: flex;
152
+ justify-content: space-between;
153
+ align-items: center;
154
+ margin-top: 4px;
155
+
156
+ &-left {
157
+ display: flex;
158
+ align-items: center;
159
+ gap: 8px;
160
+ }
161
+ }
162
+
163
+ &-avatar {
164
+ @extend %skeleton-base;
165
+ width: 24px;
166
+ height: 24px;
167
+ border-radius: 50%;
168
+ flex-shrink: 0;
169
+ }
170
+
171
+ &-assignee {
172
+ @extend %skeleton-base;
173
+ height: 12px;
174
+ width: 60px;
175
+ border-radius: 3px;
176
+ }
177
+
178
+ &-date {
179
+ @extend %skeleton-base;
180
+ height: 12px;
181
+ width: 80px;
182
+ border-radius: 3px;
183
+ }
184
+ }
185
+
186
+ // Wave animation variant
187
+ .#{$prefix}-skeleton-wave {
188
+ .#{$prefix}-skeleton-title,
189
+ .#{$prefix}-skeleton-line,
190
+ .#{$prefix}-skeleton-tag,
191
+ .#{$prefix}-skeleton-avatar,
192
+ .#{$prefix}-skeleton-assignee,
193
+ .#{$prefix}-skeleton-date,
194
+ .#{$prefix}-skeleton-priority {
195
+ @extend %skeleton-wave-base;
196
+ animation: none; // Remove shimmer animation
197
+ }
198
+ }
199
+
200
+ // Pulse animation variant
201
+ .#{$prefix}-skeleton-pulse {
202
+ .#{$prefix}-skeleton-title,
203
+ .#{$prefix}-skeleton-line,
204
+ .#{$prefix}-skeleton-tag,
205
+ .#{$prefix}-skeleton-avatar,
206
+ .#{$prefix}-skeleton-assignee,
207
+ .#{$prefix}-skeleton-date,
208
+ .#{$prefix}-skeleton-priority {
209
+ background: #f0f0f0;
210
+ animation: skeleton-pulse 1.5s ease-in-out infinite;
211
+ }
212
+ }
213
+
214
+ // Responsive design for smaller screens
215
+ @media (max-width: 768px) {
216
+ .#{$prefix}-skeleton {
217
+ padding: 12px;
218
+
219
+ &-content {
220
+ gap: 10px;
221
+ }
222
+
223
+ &-title {
224
+ height: 18px;
225
+ }
226
+
227
+ &-line {
228
+ height: 12px;
229
+ }
230
+
231
+ &-tag {
232
+ height: 18px;
233
+ width: 50px;
234
+
235
+ &:nth-child(2) {
236
+ width: 40px;
237
+ }
238
+ }
239
+
240
+ &-avatar {
241
+ width: 20px;
242
+ height: 20px;
243
+ }
244
+ }
245
+ }
@@ -0,0 +1 @@
1
+ @forward "./CardSkeleton";
@@ -0,0 +1,2 @@
1
+ export { default } from "./CardSkeleton";
2
+ export type { SkeletonAnimationType } from "./CardSkeleton";