paneltir 0.11.0 → 0.12.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/CLAUDE_MD_SNIPPET.md +17 -1
- package/INSTALL.md +2 -2
- package/README.md +1 -1
- package/dist/index.d.ts +98 -9
- package/dist/index.js +642 -534
- package/dist/style.css +234 -0
- package/fingerprint.json +5 -5
- package/package.json +30 -9
- package/template/.claude/skills/panel/SKILL.md +23 -0
package/dist/style.css
CHANGED
|
@@ -308,6 +308,133 @@
|
|
|
308
308
|
font-weight: 700;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/* src/components/Situation/Situation.css */
|
|
312
|
+
.pt-situation {
|
|
313
|
+
display: grid;
|
|
314
|
+
grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
|
|
315
|
+
gap: var(--pt-space-page);
|
|
316
|
+
align-items: start;
|
|
317
|
+
padding: var(--pt-space-lg);
|
|
318
|
+
border: 1px solid var(--pt-color-line-faint);
|
|
319
|
+
border-radius: var(--pt-radius-panel);
|
|
320
|
+
background: var(--pt-color-panel);
|
|
321
|
+
}
|
|
322
|
+
.pt-situation__half {
|
|
323
|
+
display: flex;
|
|
324
|
+
flex-direction: column;
|
|
325
|
+
gap: var(--pt-space-sm);
|
|
326
|
+
min-width: 0;
|
|
327
|
+
}
|
|
328
|
+
.pt-situation__clear {
|
|
329
|
+
margin: 0;
|
|
330
|
+
color: var(--pt-color-ink-dim);
|
|
331
|
+
font-size: 13px;
|
|
332
|
+
}
|
|
333
|
+
.pt-situation__items {
|
|
334
|
+
display: flex;
|
|
335
|
+
flex-wrap: wrap;
|
|
336
|
+
gap: var(--pt-space-md);
|
|
337
|
+
}
|
|
338
|
+
.pt-situation__item {
|
|
339
|
+
display: grid;
|
|
340
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
341
|
+
grid-template-rows: auto auto;
|
|
342
|
+
column-gap: var(--pt-space-sm);
|
|
343
|
+
align-items: center;
|
|
344
|
+
min-width: 0;
|
|
345
|
+
margin: 0;
|
|
346
|
+
padding: var(--pt-space-sm) var(--pt-space-md);
|
|
347
|
+
border: 1px solid var(--pt-color-line-faint);
|
|
348
|
+
border-left: 3px solid var(--pt-color-neutral);
|
|
349
|
+
border-radius: var(--pt-radius-control);
|
|
350
|
+
background: var(--pt-color-raised);
|
|
351
|
+
color: inherit;
|
|
352
|
+
font: inherit;
|
|
353
|
+
text-align: left;
|
|
354
|
+
}
|
|
355
|
+
button.pt-situation__item {
|
|
356
|
+
cursor: pointer;
|
|
357
|
+
}
|
|
358
|
+
button.pt-situation__item:hover,
|
|
359
|
+
button.pt-situation__item:focus-visible {
|
|
360
|
+
border-color: var(--pt-color-line);
|
|
361
|
+
}
|
|
362
|
+
.pt-situation__count {
|
|
363
|
+
grid-row: 1 / span 2;
|
|
364
|
+
font-family: var(--pt-font-mono);
|
|
365
|
+
font-size: 26px;
|
|
366
|
+
line-height: 1;
|
|
367
|
+
font-weight: 700;
|
|
368
|
+
font-variant-numeric: tabular-nums;
|
|
369
|
+
}
|
|
370
|
+
.pt-situation__label {
|
|
371
|
+
font-size: 12px;
|
|
372
|
+
font-weight: 700;
|
|
373
|
+
letter-spacing: 0.02em;
|
|
374
|
+
}
|
|
375
|
+
.pt-situation__hint {
|
|
376
|
+
font-size: 11px;
|
|
377
|
+
color: var(--pt-color-ink-faint);
|
|
378
|
+
}
|
|
379
|
+
.pt-situation__item--clear {
|
|
380
|
+
border-left-color: var(--pt-color-line);
|
|
381
|
+
}
|
|
382
|
+
.pt-situation__item--clear .pt-situation__count {
|
|
383
|
+
color: var(--pt-color-ink-faint);
|
|
384
|
+
}
|
|
385
|
+
.pt-situation__item--attention {
|
|
386
|
+
border-left-color: var(--pt-color-warning);
|
|
387
|
+
}
|
|
388
|
+
.pt-situation__item--attention .pt-situation__count {
|
|
389
|
+
color: var(--pt-color-warning);
|
|
390
|
+
}
|
|
391
|
+
.pt-situation__item--alarm {
|
|
392
|
+
border-left-color: var(--pt-color-danger);
|
|
393
|
+
}
|
|
394
|
+
.pt-situation__item--alarm .pt-situation__count {
|
|
395
|
+
color: var(--pt-color-danger);
|
|
396
|
+
}
|
|
397
|
+
[data-pt-form=warRoom] .pt-situation {
|
|
398
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
399
|
+
border-color: var(--pt-color-line);
|
|
400
|
+
border-radius: var(--pt-radius-panel);
|
|
401
|
+
background: var(--pt-color-ground-raised);
|
|
402
|
+
}
|
|
403
|
+
[data-pt-form=warRoom] .pt-situation__item {
|
|
404
|
+
border-radius: 0;
|
|
405
|
+
border-left-width: 4px;
|
|
406
|
+
background: var(--pt-color-panel);
|
|
407
|
+
}
|
|
408
|
+
[data-pt-form=warRoom] .pt-situation__count {
|
|
409
|
+
font-size: 30px;
|
|
410
|
+
}
|
|
411
|
+
[data-pt-form=warRoom] .pt-situation__label {
|
|
412
|
+
text-transform: uppercase;
|
|
413
|
+
letter-spacing: var(--pt-label-tracking);
|
|
414
|
+
}
|
|
415
|
+
[data-pt-form=warRoom] .pt-health-pill {
|
|
416
|
+
border-radius: 0;
|
|
417
|
+
border-color: var(--pt-color-line);
|
|
418
|
+
}
|
|
419
|
+
[data-pt-form=warRoom] .pt-health-pill::before {
|
|
420
|
+
width: 3px;
|
|
421
|
+
height: 12px;
|
|
422
|
+
border-radius: 0;
|
|
423
|
+
}
|
|
424
|
+
[data-pt-form=warRoom] .pt-health-pill__value {
|
|
425
|
+
font-family: var(--pt-font-mono);
|
|
426
|
+
font-variant-numeric: tabular-nums;
|
|
427
|
+
}
|
|
428
|
+
@media (max-width: 860px) {
|
|
429
|
+
.pt-situation,
|
|
430
|
+
[data-pt-form] .pt-situation {
|
|
431
|
+
grid-template-columns: minmax(0, 1fr);
|
|
432
|
+
}
|
|
433
|
+
.pt-situation__items {
|
|
434
|
+
flex-direction: column;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
311
438
|
/* src/components/FilterChips/FilterChips.css */
|
|
312
439
|
.pt-filter-row {
|
|
313
440
|
display: flex;
|
|
@@ -616,6 +743,74 @@
|
|
|
616
743
|
.pt-column__list > * {
|
|
617
744
|
flex-shrink: 0;
|
|
618
745
|
}
|
|
746
|
+
[data-pt-form=warRoom] .pt-board {
|
|
747
|
+
gap: var(--pt-space-md);
|
|
748
|
+
}
|
|
749
|
+
[data-pt-form=warRoom] .pt-column {
|
|
750
|
+
background: var(--pt-color-ground-raised, var(--pt-color-panel));
|
|
751
|
+
border: var(--pt-border-width) solid var(--pt-color-line);
|
|
752
|
+
border-top: 2px solid var(--pt-color-line);
|
|
753
|
+
}
|
|
754
|
+
[data-pt-form=warRoom] .pt-column__header {
|
|
755
|
+
padding: var(--pt-space-sm) var(--pt-space-sm);
|
|
756
|
+
border-bottom: var(--pt-border-width) solid var(--pt-color-line);
|
|
757
|
+
background: var(--pt-color-panel);
|
|
758
|
+
}
|
|
759
|
+
[data-pt-form=warRoom] .pt-column__title {
|
|
760
|
+
font-size: 10.5px;
|
|
761
|
+
font-weight: 700;
|
|
762
|
+
}
|
|
763
|
+
[data-pt-form=warRoom] .pt-column__count {
|
|
764
|
+
font-family: var(--pt-font-mono);
|
|
765
|
+
font-size: 11px;
|
|
766
|
+
padding: 1px 5px;
|
|
767
|
+
border: var(--pt-border-width) solid var(--pt-color-line-faint);
|
|
768
|
+
color: var(--pt-color-ink-dim);
|
|
769
|
+
}
|
|
770
|
+
[data-pt-form=warRoom] .pt-column__add {
|
|
771
|
+
border-radius: 0;
|
|
772
|
+
background: none;
|
|
773
|
+
}
|
|
774
|
+
[data-pt-form=warRoom] .pt-column__list {
|
|
775
|
+
padding: 0;
|
|
776
|
+
gap: 0;
|
|
777
|
+
}
|
|
778
|
+
[data-pt-form=warRoom] .pt-card {
|
|
779
|
+
background: none;
|
|
780
|
+
border-radius: 0;
|
|
781
|
+
border-bottom: var(--pt-border-width) solid var(--pt-color-line-faint);
|
|
782
|
+
padding: var(--pt-space-sm) var(--pt-space-sm) var(--pt-space-sm) calc(var(--pt-space-sm) + 5px);
|
|
783
|
+
}
|
|
784
|
+
[data-pt-form=warRoom] .pt-card:hover {
|
|
785
|
+
background: var(--pt-color-raised);
|
|
786
|
+
}
|
|
787
|
+
[data-pt-form=warRoom] .pt-card::before {
|
|
788
|
+
width: 3px;
|
|
789
|
+
border-radius: 0;
|
|
790
|
+
}
|
|
791
|
+
[data-pt-form=warRoom] .pt-card__title {
|
|
792
|
+
font-weight: 500;
|
|
793
|
+
font-size: 13px;
|
|
794
|
+
}
|
|
795
|
+
[data-pt-form=warRoom] .pt-card__progress {
|
|
796
|
+
font-family: var(--pt-font-mono);
|
|
797
|
+
}
|
|
798
|
+
[data-pt-form=warRoom] .pt-card-placeholder {
|
|
799
|
+
border: none;
|
|
800
|
+
border-bottom: 2px dashed var(--pt-color-accent);
|
|
801
|
+
border-radius: 0;
|
|
802
|
+
min-height: 28px;
|
|
803
|
+
}
|
|
804
|
+
[data-pt-form=warRoom] .pt-tag {
|
|
805
|
+
border-radius: 0;
|
|
806
|
+
font-size: 10px;
|
|
807
|
+
letter-spacing: var(--pt-label-tracking);
|
|
808
|
+
text-transform: uppercase;
|
|
809
|
+
}
|
|
810
|
+
[data-pt-form=warRoom] .pt-column__footer {
|
|
811
|
+
font-family: var(--pt-font-mono);
|
|
812
|
+
padding: var(--pt-space-sm);
|
|
813
|
+
}
|
|
619
814
|
|
|
620
815
|
/* src/components/DetailSheet/DetailSheet.css */
|
|
621
816
|
.pt-sheet-backdrop {
|
|
@@ -2113,5 +2308,44 @@
|
|
|
2113
2308
|
margin-top: auto;
|
|
2114
2309
|
padding-top: 4px;
|
|
2115
2310
|
}
|
|
2311
|
+
.pt-archive {
|
|
2312
|
+
margin: 0;
|
|
2313
|
+
padding: 0;
|
|
2314
|
+
list-style: none;
|
|
2315
|
+
display: grid;
|
|
2316
|
+
border-top: 1px solid var(--pt-color-line-faint);
|
|
2317
|
+
}
|
|
2318
|
+
.pt-archive__row {
|
|
2319
|
+
display: flex;
|
|
2320
|
+
align-items: baseline;
|
|
2321
|
+
justify-content: space-between;
|
|
2322
|
+
gap: var(--pt-space-md);
|
|
2323
|
+
width: 100%;
|
|
2324
|
+
margin: 0;
|
|
2325
|
+
padding: 9px var(--pt-space-sm);
|
|
2326
|
+
border: 0;
|
|
2327
|
+
border-bottom: 1px solid var(--pt-color-line-faint);
|
|
2328
|
+
background: transparent;
|
|
2329
|
+
color: inherit;
|
|
2330
|
+
font: inherit;
|
|
2331
|
+
text-align: left;
|
|
2332
|
+
cursor: pointer;
|
|
2333
|
+
}
|
|
2334
|
+
.pt-archive__row:hover,
|
|
2335
|
+
.pt-archive__row:focus-visible {
|
|
2336
|
+
background: var(--pt-color-raised);
|
|
2337
|
+
}
|
|
2338
|
+
.pt-archive__title {
|
|
2339
|
+
color: var(--pt-color-ink-dim);
|
|
2340
|
+
font-size: 13px;
|
|
2341
|
+
min-width: 0;
|
|
2342
|
+
}
|
|
2343
|
+
.pt-archive__meta {
|
|
2344
|
+
flex: 0 0 auto;
|
|
2345
|
+
font-family: var(--pt-font-mono);
|
|
2346
|
+
font-size: 11px;
|
|
2347
|
+
color: var(--pt-color-ink-faint);
|
|
2348
|
+
font-variant-numeric: tabular-nums;
|
|
2349
|
+
}
|
|
2116
2350
|
|
|
2117
2351
|
/* src/style.css */
|
package/fingerprint.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paneltir",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"hash": "sha256:
|
|
5
|
-
"fileCount":
|
|
6
|
-
"templateHash": "sha256:
|
|
7
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"hash": "sha256:ea981bdb1de721f4d2afd279244a7298b025773fb4a5abf8ffa33868c0d73f7d",
|
|
5
|
+
"fileCount": 166,
|
|
6
|
+
"templateHash": "sha256:c0c1a1678d860212ff82d55c7e7c0ee3eaf8be623621cadbb6ca5bf51b31e2ba",
|
|
7
|
+
"generatedAt": "2026-09-14T04:42:15.291Z"
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paneltir",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "A React UI kit for admin panels: page frame, a board with touch-ready drag and drop, detail sheets, and a whole panel in one component. Structure and behaviour are fixed; colour and brand belong to each project.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "DFKlabs (https://DFKlabs.com)",
|
|
@@ -99,28 +99,49 @@
|
|
|
99
99
|
"node": ">=20"
|
|
100
100
|
},
|
|
101
101
|
"paneltirRelease": {
|
|
102
|
-
"version": "0.
|
|
103
|
-
"date": "2026-09-
|
|
102
|
+
"version": "0.12.0",
|
|
103
|
+
"date": "2026-09-14",
|
|
104
104
|
"entries": [
|
|
105
105
|
{
|
|
106
106
|
"kind": "feature",
|
|
107
107
|
"text": {
|
|
108
|
-
"en": "A card finished more than a week ago
|
|
109
|
-
"es": "Una tarjeta terminada hace más de una semana
|
|
108
|
+
"en": "Archived cards leave the board and get a place of their own. A card finished more than a week ago is no longer drawn in its column at all — it is listed in the record view, under what each pass did, with the date it was finished. The count in its column was still the board carrying it: one tap put fifteen finished cards back in the way.",
|
|
109
|
+
"es": "Las tarjetas archivadas salen del tablero y tienen su propio sitio. Una tarjeta terminada hace más de una semana ya no se dibuja en su columna: aparece en la vista de revisiones, debajo de lo que hizo cada pasada, con la fecha en que se terminó. El contador en la columna seguía siendo el tablero cargando con ellas: un toque devolvía quince tarjetas terminadas a en medio."
|
|
110
110
|
}
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
"kind": "feature",
|
|
114
114
|
"text": {
|
|
115
|
-
"en": "A board
|
|
116
|
-
"es": "Una
|
|
115
|
+
"en": "A new strip at the top of the board says what is waiting on you and whether the system is working. The two questions a board is opened to answer were on the screen and neither was prominent — three of six identical tiles, and a line of small grey pills under them. The counts are now large and are controls: tapping one filters the board or opens the question.",
|
|
116
|
+
"es": "Una franja nueva encima del tablero dice qué te está esperando y si el sistema funciona. Las dos preguntas por las que se abre un tablero estaban en pantalla y ninguna destacaba: tres de seis casillas iguales, y una línea de pastillas grises debajo. Ahora los números son grandes y son controles: tocar uno filtra el tablero o abre la pregunta."
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"kind": "feature",
|
|
121
|
+
"text": {
|
|
122
|
+
"en": "A third board shape, `warRoom`: square, hairline-ruled, tight, priority carried as a full-height bar down the left edge of every row and counts set in the monospace face. It is the only form that tightens rather than loosens the spacing — a board somebody is watching wants as many rows on the screen as will fit. Ask for it with `THEME_FORMS.warRoom` on a theme's `form`.",
|
|
123
|
+
"es": "Una tercera forma de tablero, `warRoom`: cuadrada, reglada a un pelo, apretada, con la prioridad como una barra de alto completo en el borde izquierdo de cada fila y los números en la tipografía monoespaciada. Es la única forma que aprieta el espaciado en vez de soltarlo: un tablero que se vigila quiere tantas filas en pantalla como quepan. Se pide con `THEME_FORMS.warRoom` en el `form` de un tema."
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"kind": "feature",
|
|
128
|
+
"text": {
|
|
129
|
+
"en": "`SituationRow` is exported, so a project building its own screen out of the components can draw the same strip.",
|
|
130
|
+
"es": "`SituationRow` se exporta, así que un proyecto que construye su propia pantalla con los componentes puede dibujar la misma franja."
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"kind": "fix",
|
|
135
|
+
"text": {
|
|
136
|
+
"en": "The open decisions counter counts questions nobody has answered, not cards about deciding. Those are different numbers and the one that holds work up is the first.",
|
|
137
|
+
"es": "El contador de decisiones abiertas cuenta preguntas que nadie ha contestado, no tarjetas sobre decidir. Son números distintos y el que frena el trabajo es el primero."
|
|
117
138
|
}
|
|
118
139
|
},
|
|
119
140
|
{
|
|
120
141
|
"kind": "chore",
|
|
121
142
|
"text": {
|
|
122
|
-
"en": "A
|
|
123
|
-
"es": "Una
|
|
143
|
+
"en": "A shape declared with no drawing now fails the checks. A form whose CSS is missing renders exactly as the default, which does not look like a missing stylesheet — it looks like the `form` prop being ignored.",
|
|
144
|
+
"es": "Una forma declarada sin dibujo ahora falla las comprobaciones. Una forma a la que le falta el CSS se dibuja igual que la de por defecto, y eso no parece una hoja de estilos que falta: parece que la prop `form` se está ignorando."
|
|
124
145
|
}
|
|
125
146
|
}
|
|
126
147
|
]
|
|
@@ -96,6 +96,19 @@ becomes a card in the owner's column, when only they can do it.
|
|
|
96
96
|
A card carrying `completedAt` with no `startedAt` was declared finished
|
|
97
97
|
without ever being picked up, and the panel marks it. Never create that shape.
|
|
98
98
|
|
|
99
|
+
**A card finished more than a week ago leaves the board.** It is not deleted
|
|
100
|
+
and it is still in the file: the panel simply stops drawing it in its column
|
|
101
|
+
and lists it in the record view instead, under what each pass did, with the
|
|
102
|
+
date it was finished. So a done column that looks short is not a done column
|
|
103
|
+
that lost anything — read the file, not the screen, when counting what has been
|
|
104
|
+
finished.
|
|
105
|
+
|
|
106
|
+
This is derived from `completedAt` on every render and never written, so
|
|
107
|
+
nothing marks it and nothing ages. The one card it never applies to is a card
|
|
108
|
+
in a done column with **no `completedAt` at all**: its age is unknown, so it
|
|
109
|
+
stays on the board. That is another reason to stamp the date when you move a
|
|
110
|
+
card to done.
|
|
111
|
+
|
|
99
112
|
## Writing back
|
|
100
113
|
|
|
101
114
|
The board is a conversation. Leave it saying what happened:
|
|
@@ -139,6 +152,16 @@ every preset and the settings sheet shows a single row. Two projects were
|
|
|
139
152
|
installed that way before the distinction existed, and the symptom reads as the
|
|
140
153
|
kit having no themes rather than as a prop being wrong.
|
|
141
154
|
|
|
155
|
+
A theme also carries a **form**, which is the shape it is drawn in rather than
|
|
156
|
+
its colours. `THEME_FORMS.panel` is the default — raised cards floating in a
|
|
157
|
+
rounded column. `THEME_FORMS.ledger` is a book: squared, hairline-ruled, set in
|
|
158
|
+
a serif. `THEME_FORMS.warRoom` is an operations console: square, tight, with
|
|
159
|
+
priority as a bar down the left edge of every row and counts in the monospace
|
|
160
|
+
face, and it is the only one that tightens the spacing rather than loosening
|
|
161
|
+
it — so it fits more rows on a screen, which is what a board somebody watches
|
|
162
|
+
wants. Pick one by putting it on the theme's `form`; leaving it out draws the
|
|
163
|
+
board the way it did before forms existed.
|
|
164
|
+
|
|
142
165
|
## When the panel behaves oddly for no visible reason
|
|
143
166
|
|
|
144
167
|
The gate — `middleware.ts`, `lib/session.ts`, `api/*.ts` — was copied into this
|