@mosaicoo/kanban 0.1.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.
- package/LICENSE +201 -0
- package/README.md +44 -0
- package/fesm2022/mosaicoo-kanban-adapters.mjs +417 -0
- package/fesm2022/mosaicoo-kanban-core.mjs +1483 -0
- package/fesm2022/mosaicoo-kanban-ui.mjs +2299 -0
- package/fesm2022/mosaicoo-kanban.mjs +13 -0
- package/package.json +60 -0
- package/styles/kanban-tokens.css +66 -0
- package/types/mosaicoo-kanban-adapters.d.ts +166 -0
- package/types/mosaicoo-kanban-core.d.ts +689 -0
- package/types/mosaicoo-kanban-ui.d.ts +538 -0
- package/types/mosaicoo-kanban.d.ts +2 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from '@mosaicoo/kanban/core';
|
|
2
|
+
export * from '@mosaicoo/kanban/ui';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* @mosaicoo/kanban — entry primário: re-exporta o caminho comum (core + ui).
|
|
6
|
+
*
|
|
7
|
+
* Consumidores headless usam '@mosaicoo/kanban/core'; integrações de
|
|
8
|
+
* persistência usam '@mosaicoo/kanban/adapters'.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generated bundle index. Do not edit.
|
|
13
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mosaicoo/kanban",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Flexible board engine and Angular UI for Kanban-style visual organization — configurable columns, swimlanes and dynamic grouping, with a headless zero-dependency core.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://github.com/mosaicoo/mosaicoo-kanban#readme",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/mosaicoo/mosaicoo-kanban/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/mosaicoo/mosaicoo-kanban.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"kanban",
|
|
16
|
+
"board",
|
|
17
|
+
"swimlane",
|
|
18
|
+
"drag-and-drop",
|
|
19
|
+
"angular",
|
|
20
|
+
"headless",
|
|
21
|
+
"mosaicoo"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
"./styles/*.css": "./styles/*.css",
|
|
28
|
+
"./package.json": {
|
|
29
|
+
"default": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./types/mosaicoo-kanban.d.ts",
|
|
33
|
+
"default": "./fesm2022/mosaicoo-kanban.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./adapters": {
|
|
36
|
+
"types": "./types/mosaicoo-kanban-adapters.d.ts",
|
|
37
|
+
"default": "./fesm2022/mosaicoo-kanban-adapters.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./core": {
|
|
40
|
+
"types": "./types/mosaicoo-kanban-core.d.ts",
|
|
41
|
+
"default": "./fesm2022/mosaicoo-kanban-core.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./ui": {
|
|
44
|
+
"types": "./types/mosaicoo-kanban-ui.d.ts",
|
|
45
|
+
"default": "./fesm2022/mosaicoo-kanban-ui.mjs"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@angular/cdk": ">=21.0.0 <23.0.0",
|
|
50
|
+
"@angular/common": ">=21.0.0 <23.0.0",
|
|
51
|
+
"@angular/core": ">=21.0.0 <23.0.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"tslib": "^2.3.0"
|
|
55
|
+
},
|
|
56
|
+
"sideEffects": false,
|
|
57
|
+
"module": "fesm2022/mosaicoo-kanban.mjs",
|
|
58
|
+
"typings": "types/mosaicoo-kanban.d.ts",
|
|
59
|
+
"type": "module"
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @mosaicoo/kanban — Design Tokens (--mkb-*)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* Este arquivo é OPCIONAL. Os componentes já funcionam sem ele, porque todo
|
|
5
|
+
* uso interno segue a cadeia de fallback (docs/01-arquitetura.md §12):
|
|
6
|
+
*
|
|
7
|
+
* var(--mkb-token, var(--token-do-DS-mosaicoo, default-embutido))
|
|
8
|
+
*
|
|
9
|
+
* - Dentro da plataforma Mosaicoo: NÃO importe este arquivo — o tema do DS
|
|
10
|
+
* (claro/escuro via [data-theme]) é herdado automaticamente.
|
|
11
|
+
* - Fora do ecossistema: importe-o para ter o tema default do produto e
|
|
12
|
+
* redefina os tokens abaixo para personalizar.
|
|
13
|
+
*
|
|
14
|
+
* import '@mosaicoo/kanban/styles/kanban-tokens.css';
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
:root {
|
|
18
|
+
/* Superfícies e bordas */
|
|
19
|
+
--mkb-surface: #f6f5f8; /* fundo do board */
|
|
20
|
+
--mkb-column-bg: #efedf3; /* fundo de coluna */
|
|
21
|
+
--mkb-card-bg: #ffffff; /* fundo de cartão */
|
|
22
|
+
--mkb-border: #e3e0ea;
|
|
23
|
+
--mkb-border-strong: #c9c4d4;
|
|
24
|
+
|
|
25
|
+
/* Texto */
|
|
26
|
+
--mkb-foreground: #241f33;
|
|
27
|
+
--mkb-muted: #6f6a7c;
|
|
28
|
+
|
|
29
|
+
/* Marca / realce (violeta Mosaicoo como default de fábrica) */
|
|
30
|
+
--mkb-accent: #5e35b1;
|
|
31
|
+
--mkb-accent-contrast: #ffffff;
|
|
32
|
+
|
|
33
|
+
/* Estados */
|
|
34
|
+
--mkb-danger: #b3261e;
|
|
35
|
+
--mkb-warning: #9a6b00;
|
|
36
|
+
--mkb-success: #1b6e3c;
|
|
37
|
+
|
|
38
|
+
/* Forma e tipografia */
|
|
39
|
+
--mkb-radius: 10px;
|
|
40
|
+
--mkb-radius-sm: 6px;
|
|
41
|
+
--mkb-font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
42
|
+
|
|
43
|
+
/* Densidade / espaçamentos (docs/02 §10 — configuráveis pelo host) */
|
|
44
|
+
--mkb-gap: 12px; /* base p/ colunas e lanes (retrocompat) */
|
|
45
|
+
--mkb-column-gap: var(--mkb-gap); /* horizontal entre colunas */
|
|
46
|
+
--mkb-lane-gap: var(--mkb-gap); /* vertical entre lanes */
|
|
47
|
+
--mkb-card-gap: 8px; /* entre cartões */
|
|
48
|
+
--mkb-entry-gap: 4px; /* entre itens internos (entries) do card */
|
|
49
|
+
--mkb-block-gap: 8px; /* entre blocos do cartão declarativo */
|
|
50
|
+
--mkb-fact-gap: 10px; /* entre fatos inline (facts) */
|
|
51
|
+
--mkb-card-padding: 10px 12px; /* interno do cartão */
|
|
52
|
+
--mkb-cell-padding: 4px 8px 10px; /* interno do container de cartões */
|
|
53
|
+
--mkb-header-padding: 10px 12px; /* interno do cabeçalho de coluna/lane */
|
|
54
|
+
--mkb-lane-label-width: 140px; /* largura do rótulo da lane na grade */
|
|
55
|
+
--mkb-column-width: clamp(220px, 26vw, 320px); /* largura da coluna */
|
|
56
|
+
/* colunas da grade de lanes: por padrão, MESMA largura das colunas */
|
|
57
|
+
--mkb-grid-column-width: var(--mkb-column-width);
|
|
58
|
+
|
|
59
|
+
/* Movimento */
|
|
60
|
+
--mkb-dur: 150ms;
|
|
61
|
+
--mkb-dur-move: 180ms; /* reordenação/settle (FLIP) */
|
|
62
|
+
--mkb-ease: cubic-bezier(0.2, 0, 0, 1);
|
|
63
|
+
|
|
64
|
+
/* Foco (a11y) */
|
|
65
|
+
--mkb-focus-ring: 0 0 0 3px color-mix(in srgb, var(--mkb-accent) 35%, transparent);
|
|
66
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { KanbanItem, CellRef, KanbanAxis, KanbanEntry, EntryRef, BoardConfig, KanbanBoard, CreateBoardOptions } from '@mosaicoo/kanban/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mudança de dados do board, SERIALIZÁVEL — é o que viaja para o adapter
|
|
5
|
+
* (persistência) e o que chega dele (tempo real).
|
|
6
|
+
*
|
|
7
|
+
* `items` é o snapshot completo dos itens APÓS a mudança: adapters de
|
|
8
|
+
* snapshot (localStorage, arquivo) salvam direto; adapters granulares
|
|
9
|
+
* (REST) usam os campos específicos e ignoram o snapshot.
|
|
10
|
+
*/
|
|
11
|
+
type KanbanChange = {
|
|
12
|
+
items: readonly KanbanItem[];
|
|
13
|
+
} & ({
|
|
14
|
+
type: 'move';
|
|
15
|
+
item: KanbanItem;
|
|
16
|
+
from: CellRef;
|
|
17
|
+
to: CellRef;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'add';
|
|
20
|
+
item: KanbanItem;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'update';
|
|
23
|
+
item: KanbanItem;
|
|
24
|
+
previous: KanbanItem;
|
|
25
|
+
changes: Record<string, unknown>;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'remove';
|
|
28
|
+
item: KanbanItem;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'move-group';
|
|
31
|
+
axis: KanbanAxis;
|
|
32
|
+
groupId: string;
|
|
33
|
+
from: number;
|
|
34
|
+
to: number;
|
|
35
|
+
/** Nova ordem completa dos ids do eixo (para adapters de snapshot). */
|
|
36
|
+
order: readonly string[];
|
|
37
|
+
} | {
|
|
38
|
+
type: 'move-entry';
|
|
39
|
+
entry: KanbanEntry;
|
|
40
|
+
from: EntryRef;
|
|
41
|
+
to: EntryRef;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'update-entry';
|
|
44
|
+
op: 'add' | 'update' | 'remove';
|
|
45
|
+
cardId: string;
|
|
46
|
+
field: string;
|
|
47
|
+
entry: KanbanEntry;
|
|
48
|
+
previous?: KanbanEntry;
|
|
49
|
+
changes?: Record<string, unknown>;
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Contrato de persistência (docs/01 §7-8). O host entrega o adapter JÁ
|
|
53
|
+
* contextualizado (URL/chaves do tenant corrente, quando aplicável) — a lib
|
|
54
|
+
* não conhece tenant nem autenticação e NUNCA persiste por conta própria.
|
|
55
|
+
*/
|
|
56
|
+
interface KanbanDataAdapter {
|
|
57
|
+
/** Carrega a configuração completa do board (com os itens). */
|
|
58
|
+
load(): Promise<BoardConfig>;
|
|
59
|
+
/** Persiste uma mudança aplicada localmente (fluxo otimista: a UI já
|
|
60
|
+
* refletiu; rejeição gera rollback automático no binder). */
|
|
61
|
+
persist(change: KanbanChange): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Tempo real (opcional): o adapter chama `push` a cada evento REMOTO
|
|
64
|
+
* (nunca com eco das mudanças locais); retorna a função de desinscrição.
|
|
65
|
+
*/
|
|
66
|
+
connect?(push: (change: KanbanChange) => void): () => void;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface BindAdapterOptions {
|
|
70
|
+
/** Desfazer localmente a mudança cujo persist foi rejeitado (default true). */
|
|
71
|
+
rollbackOnError?: boolean;
|
|
72
|
+
/** Notificação de falha de persistência (toast/log do host). */
|
|
73
|
+
onPersistError?(error: unknown, change: KanbanChange): void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Liga um board a um adapter (docs/01 §7):
|
|
77
|
+
*
|
|
78
|
+
* - FLUXO OTIMISTA: cada after:* vira um KanbanChange e entra numa FILA
|
|
79
|
+
* sequencial de persist (ordem garantida); rejeição → rollback automático
|
|
80
|
+
* via applyRemote (fora do histórico de undo) + onPersistError.
|
|
81
|
+
* - TEMPO REAL: se o adapter tem connect(), eventos remotos entram como
|
|
82
|
+
* applyRemote — não disparam persist (sem eco), não entram no undo local
|
|
83
|
+
* e não passam por regras/permissões (last-write-wins, o evento já
|
|
84
|
+
* aconteceu na origem).
|
|
85
|
+
*
|
|
86
|
+
* Retorna a função que desliga tudo (chamar antes de board.destroy()).
|
|
87
|
+
*/
|
|
88
|
+
declare function bindAdapter(board: KanbanBoard, adapter: KanbanDataAdapter, options?: BindAdapterOptions): () => void;
|
|
89
|
+
/**
|
|
90
|
+
* Caminho feliz: carrega a config do adapter, cria o board (validação do
|
|
91
|
+
* createBoard incluída) e já liga a persistência/tempo real.
|
|
92
|
+
*/
|
|
93
|
+
declare function loadBoard(adapter: KanbanDataAdapter, options?: CreateBoardOptions & BindAdapterOptions): Promise<KanbanBoard>;
|
|
94
|
+
|
|
95
|
+
interface MemoryAdapterOptions {
|
|
96
|
+
/** Simula rejeição do backend para a mudança (testes/demos de rollback). */
|
|
97
|
+
failOn?(change: KanbanChange): boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Adapter em memória — referência para demos e testes. Guarda a config como
|
|
101
|
+
* fonte da verdade e aceita `emitRemote()` para simular um evento vindo do
|
|
102
|
+
* servidor (exercita o caminho de tempo real sem rede).
|
|
103
|
+
*/
|
|
104
|
+
declare class MemoryKanbanAdapter implements KanbanDataAdapter {
|
|
105
|
+
private readonly options;
|
|
106
|
+
private config;
|
|
107
|
+
private readonly pushes;
|
|
108
|
+
constructor(seed: BoardConfig, options?: MemoryAdapterOptions);
|
|
109
|
+
load(): Promise<BoardConfig>;
|
|
110
|
+
persist(change: KanbanChange): Promise<void>;
|
|
111
|
+
connect(push: (change: KanbanChange) => void): () => void;
|
|
112
|
+
/** Simula um evento REMOTO: atualiza a fonte da verdade e avisa os
|
|
113
|
+
* conectados (como um servidor faria). */
|
|
114
|
+
emitRemote(change: KanbanChange): void;
|
|
115
|
+
/** Itens atualmente persistidos (inspeção em testes). */
|
|
116
|
+
get items(): readonly KanbanItem[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Adapter de localStorage — referência de persistência local (playground,
|
|
121
|
+
* protótipos). A CHAVE vem pronta do host (é ele que contextualiza tenant/
|
|
122
|
+
* usuário, docs/01 §8); a lib não inventa chave nenhuma.
|
|
123
|
+
*
|
|
124
|
+
* Tempo real de verdade entre ABAS: o evento nativo 'storage' só dispara nas
|
|
125
|
+
* outras abas — cada gravação local vira push remoto para as demais.
|
|
126
|
+
*/
|
|
127
|
+
declare class LocalStorageKanbanAdapter implements KanbanDataAdapter {
|
|
128
|
+
private readonly storageKey;
|
|
129
|
+
private readonly seed;
|
|
130
|
+
constructor(storageKey: string, seed: BoardConfig);
|
|
131
|
+
load(): Promise<BoardConfig>;
|
|
132
|
+
persist(change: KanbanChange): Promise<void>;
|
|
133
|
+
connect(push: (change: KanbanChange) => void): () => void;
|
|
134
|
+
/** Apaga o estado salvo (ex.: botão "resetar demo" do host). */
|
|
135
|
+
clear(): void;
|
|
136
|
+
private read;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface RestAdapterOptions {
|
|
140
|
+
/** GET daqui deve devolver um BoardConfig (JSON). */
|
|
141
|
+
loadUrl: string;
|
|
142
|
+
/** POST para cá recebe o KanbanChange (JSON). */
|
|
143
|
+
persistUrl: string;
|
|
144
|
+
/** Headers extras (ex.: Authorization) — o host entrega prontos. */
|
|
145
|
+
headers?: Record<string, string>;
|
|
146
|
+
/** Injetável para testes/ambientes sem fetch global. */
|
|
147
|
+
fetchImpl?: typeof fetch;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Adapter REST de referência — ESQUELETO documentado (docs/01 §7): dois
|
|
151
|
+
* endpoints, payloads JSON diretos. Casos reais tendem a envolver mapeamento
|
|
152
|
+
* de DTOs, autenticação e retry — faça um adapter próprio usando este como
|
|
153
|
+
* molde. Tempo real (connect) fica com o host: WebSocket/SSE são específicos
|
|
154
|
+
* demais para uma referência genérica; veja LocalStorageKanbanAdapter para o
|
|
155
|
+
* formato do push.
|
|
156
|
+
*/
|
|
157
|
+
declare class RestKanbanAdapter implements KanbanDataAdapter {
|
|
158
|
+
private readonly options;
|
|
159
|
+
constructor(options: RestAdapterOptions);
|
|
160
|
+
load(): Promise<BoardConfig>;
|
|
161
|
+
persist(change: KanbanChange): Promise<void>;
|
|
162
|
+
private doFetch;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { LocalStorageKanbanAdapter, MemoryKanbanAdapter, RestKanbanAdapter, bindAdapter, loadBoard };
|
|
166
|
+
export type { BindAdapterOptions, KanbanChange, KanbanDataAdapter, MemoryAdapterOptions, RestAdapterOptions };
|