paneltir 0.8.0 → 0.10.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/dist/style.css CHANGED
@@ -841,6 +841,128 @@
841
841
  color: var(--pt-color-success);
842
842
  }
843
843
 
844
+ /* src/components/Setup/SetupWizard.css */
845
+ .pt-wizard {
846
+ display: flex;
847
+ flex-direction: column;
848
+ gap: var(--pt-space-lg);
849
+ }
850
+ .pt-wizard__head {
851
+ display: flex;
852
+ align-items: baseline;
853
+ justify-content: space-between;
854
+ gap: var(--pt-space-sm);
855
+ flex-wrap: wrap;
856
+ }
857
+ .pt-wizard__progress {
858
+ margin: 0;
859
+ font-family: var(--pt-font-mono);
860
+ font-size: 12px;
861
+ color: var(--pt-color-ink-faint);
862
+ }
863
+ .pt-wizard__step {
864
+ padding: var(--pt-space-lg);
865
+ border: var(--pt-border-width) solid var(--pt-color-line);
866
+ border-radius: var(--pt-radius-panel);
867
+ background: var(--pt-color-panel);
868
+ }
869
+ .pt-wizard__step--done {
870
+ border-color: var(--pt-color-success);
871
+ }
872
+ .pt-wizard__now {
873
+ margin: 0 0 var(--pt-space-xs);
874
+ font-size: 11px;
875
+ letter-spacing: var(--pt-label-tracking);
876
+ text-transform: uppercase;
877
+ color: var(--pt-color-ink-faint);
878
+ }
879
+ .pt-wizard__label {
880
+ margin: 0 0 var(--pt-space-xs);
881
+ font-size: 16px;
882
+ color: var(--pt-color-ink);
883
+ }
884
+ .pt-wizard__var {
885
+ margin: 0 0 var(--pt-space-sm);
886
+ font-family: var(--pt-font-mono);
887
+ font-size: 12.5px;
888
+ color: var(--pt-color-accent);
889
+ overflow-wrap: anywhere;
890
+ }
891
+ .pt-wizard__enables {
892
+ margin: 0 0 var(--pt-space-sm);
893
+ font-size: 13px;
894
+ line-height: 1.5;
895
+ color: var(--pt-color-ink-dim);
896
+ }
897
+ .pt-wizard__fix {
898
+ font-size: 13px;
899
+ line-height: 1.55;
900
+ color: var(--pt-color-ink-dim);
901
+ }
902
+ .pt-wizard__fix ol,
903
+ .pt-wizard__fix ul {
904
+ margin: 0;
905
+ padding-left: 18px;
906
+ }
907
+ .pt-wizard__fix li {
908
+ margin-bottom: 4px;
909
+ }
910
+ .pt-wizard__fix code,
911
+ .pt-wizard__prompt {
912
+ font-family: var(--pt-font-mono);
913
+ background: var(--pt-color-raised);
914
+ color: var(--pt-color-ink);
915
+ border-radius: var(--pt-radius-square);
916
+ overflow-wrap: anywhere;
917
+ }
918
+ .pt-wizard__fix code {
919
+ font-size: 12px;
920
+ padding: 1px 5px;
921
+ }
922
+ .pt-wizard__actions {
923
+ display: flex;
924
+ align-items: center;
925
+ gap: var(--pt-space-sm);
926
+ flex-wrap: wrap;
927
+ margin-top: var(--pt-space-md);
928
+ }
929
+ .pt-wizard__said {
930
+ margin: 0;
931
+ font-size: 12.5px;
932
+ color: var(--pt-color-warning);
933
+ }
934
+ .pt-wizard__verify {
935
+ margin: var(--pt-space-sm) 0 0;
936
+ padding-left: 18px;
937
+ font-size: 13px;
938
+ line-height: 1.55;
939
+ color: var(--pt-color-ink-dim);
940
+ }
941
+ .pt-wizard__done-title {
942
+ margin: 0 0 var(--pt-space-xs);
943
+ font-size: 11px;
944
+ letter-spacing: var(--pt-label-tracking);
945
+ text-transform: uppercase;
946
+ color: var(--pt-color-ink-faint);
947
+ }
948
+ .pt-wizard__done ul {
949
+ margin: 0;
950
+ padding-left: 18px;
951
+ font-size: 13px;
952
+ color: var(--pt-color-ink-dim);
953
+ }
954
+ .pt-wizard__stuck {
955
+ padding-top: var(--pt-space-md);
956
+ border-top: var(--pt-border-width) solid var(--pt-color-line-faint);
957
+ }
958
+ .pt-wizard__prompt {
959
+ margin: 0 0 var(--pt-space-sm);
960
+ padding: var(--pt-space-sm);
961
+ font-size: 12px;
962
+ line-height: 1.5;
963
+ white-space: pre-wrap;
964
+ }
965
+
844
966
  /* src/components/Notifications/Notifications.css */
845
967
  .pt-bell {
846
968
  position: relative;
package/fingerprint.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "paneltir",
3
- "version": "0.8.0",
4
- "hash": "sha256:a252ef2a015240e0e8463c0ebb0ef7a8af80ad7ade66f2c48e71657500d506d5",
5
- "fileCount": 153,
6
- "generatedAt": "2026-09-07T12:59:14.850Z"
3
+ "version": "0.10.0",
4
+ "hash": "sha256:4de7ef7076563e4c3118ac16b645737a44c4c0675115d9a9d7bbff562d5ecb74",
5
+ "fileCount": 163,
6
+ "templateHash": "sha256:7f9accd11920a0c189dd683bdb96635a606960afeca71e02c2a26a0257acefd8",
7
+ "generatedAt": "2026-09-11T02:49:51.562Z"
7
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paneltir",
3
- "version": "0.8.0",
3
+ "version": "0.10.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)",
@@ -64,7 +64,7 @@
64
64
  "check:boards": "node scripts/check-boards.mjs",
65
65
  "demo:install": "npm --prefix examples/demo ci",
66
66
  "demo:build": "npm --prefix examples/demo run build",
67
- "verify": "npm run typecheck && npm run build && npm run icons:check && npm run seo:check && npm run test:auth && npm run test:marketplace && npm run test:init && npm run test:board && npm run test:updates && npm run check:boards && npm run check:docs && npm run check:package && npm run fingerprint:check",
67
+ "verify": "npm run typecheck && npm run build && npm run icons:check && npm run seo:check && npm run test:auth && npm run test:marketplace && npm run test:init && npm run test:board && npm run test:gate && npm run test:move && npm run test:theme && npm run test:setup && npm run test:updates && npm run release-notes:check && npm run check:boards && npm run check:docs && npm run check:package && npm run fingerprint:check",
68
68
  "site:install": "npm --prefix site ci",
69
69
  "site:dev": "npm --prefix site run dev",
70
70
  "site:build": "npm --prefix site run build",
@@ -72,8 +72,14 @@
72
72
  "check:docs": "node scripts/check-docs.mjs",
73
73
  "check:package": "node scripts/check-package.mjs",
74
74
  "test:init": "node scripts/test-init.mjs",
75
+ "release-notes": "node scripts/release-notes.mjs",
76
+ "release-notes:check": "node scripts/release-notes.mjs --check",
75
77
  "test:updates": "node scripts/test-updates.mjs",
76
- "test:board": "node scripts/test-board.mjs"
78
+ "test:board": "node scripts/test-board.mjs",
79
+ "test:move": "node scripts/test-move.mjs",
80
+ "test:theme": "node scripts/test-theme.mjs",
81
+ "test:setup": "node scripts/test-setup.mjs",
82
+ "test:gate": "node scripts/test-gate.mjs"
77
83
  },
78
84
  "peerDependencies": {
79
85
  "react": ">=18",
@@ -91,5 +97,46 @@
91
97
  },
92
98
  "engines": {
93
99
  "node": ">=20"
100
+ },
101
+ "paneltirRelease": {
102
+ "version": "0.10.0",
103
+ "date": "2026-09-11",
104
+ "entries": [
105
+ {
106
+ "kind": "feature",
107
+ "text": {
108
+ "en": "`paneltir doctor` says whether the files this project copied are still the ones the installed kit ships — and separates \"you edited it\" from \"we changed it underneath you\", which a diff cannot.",
109
+ "es": "`paneltir doctor` dice si los archivos que copió este proyecto siguen siendo los del kit instalado — y separa «lo editaste tú» de «lo cambiamos nosotros debajo», que un diff no puede."
110
+ }
111
+ },
112
+ {
113
+ "kind": "feature",
114
+ "text": {
115
+ "en": "The setup list can carry a row for the copied gate. Import `.paneltir/gate.json` and pass it as `gate`; without it the panel says nothing about those files rather than guessing.",
116
+ "es": "La lista de configuración puede llevar una fila para la puerta copiada. Importa `.paneltir/gate.json` y pásalo como `gate`; sin él el panel no dice nada de esos archivos en vez de suponer."
117
+ }
118
+ },
119
+ {
120
+ "kind": "feature",
121
+ "text": {
122
+ "en": "`paneltir run \"what this pass did\"` appends to the board's revisions, so the record does not depend on anyone remembering at the end of a session.",
123
+ "es": "`paneltir run \"qué hizo esta pasada\"` añade una entrada a las revisiones del tablero, así el registro no depende de que alguien se acuerde al final de la sesión."
124
+ }
125
+ },
126
+ {
127
+ "kind": "fix",
128
+ "text": {
129
+ "en": "`paneltir init` and `paneltir doctor` no longer need React installed. They loaded the component bundle at startup, so they failed in a project that had not installed it yet — which is exactly when `init` is run.",
130
+ "es": "`paneltir init` y `paneltir doctor` ya no necesitan React instalado. Cargaban el bundle de componentes al arrancar, así que fallaban en un proyecto que aún no lo tenía — que es justo cuando se ejecuta `init`."
131
+ }
132
+ },
133
+ {
134
+ "kind": "chore",
135
+ "text": {
136
+ "en": "The rules a project needs are checked to actually reach it: the documents a project keeps must name `extraThemes` and `paneltir doctor`, or the build fails saying why.",
137
+ "es": "Se comprueba que las reglas que un proyecto necesita le lleguen de verdad: los documentos que el proyecto conserva tienen que nombrar `extraThemes` y `paneltir doctor`, o la build falla diciendo por qué."
138
+ }
139
+ }
140
+ ]
94
141
  }
95
142
  }
@@ -132,6 +132,76 @@ Never invent a palette. If the project has no colours of its own, say so and
132
132
  leave the theme alone — the kit ships presets for exactly that case, and one
133
133
  of them is a light theme.
134
134
 
135
+ And when you hand this project's own theme to `PanelApp`, it goes in
136
+ **`extraThemes`** and never in `themes`. `extraThemes` offers it as well as the
137
+ kit's four; `themes` means "exactly these", so one theme passed there deletes
138
+ every preset and the settings sheet shows a single row. Two projects were
139
+ installed that way before the distinction existed, and the symptom reads as the
140
+ kit having no themes rather than as a prop being wrong.
141
+
142
+ ## When the panel behaves oddly for no visible reason
143
+
144
+ The gate — `middleware.ts`, `lib/session.ts`, `api/*.ts` — was copied into this
145
+ project once and does **not** update when the kit does. So a fix released
146
+ upstream can be missing here while every version number on the screen looks
147
+ current, and nothing says so: the `HTTP 500` on saving lived in
148
+ `api/panel-state.ts` and stayed in projects installed before the fix.
149
+
150
+ npx paneltir doctor
151
+
152
+ `.paneltir/gate.json` is what makes that answer sharp, and it belongs in git:
153
+ it records what `init` copied and from where. Ignored, it vanishes on the next
154
+ clone and every file degrades to "differs" — the one answer that cannot say
155
+ whether you moved it or we did.
156
+
157
+ It separates the three answers that need different actions: *yours* (you edited
158
+ it), *BEHIND* (you did not touch it and the template moved), and *BOTH*. The
159
+ middle one is invisible to `git diff`, because there is nothing in this
160
+ project's history to compare against. `paneltir init --force` replaces the gate
161
+ and never the board — read the diff first when a file is marked BOTH, or the
162
+ edit is lost.
163
+
164
+ ## Setting the panel up in the first place
165
+
166
+ The panel is asked for this by name: its walkthrough carries a line the owner
167
+ can paste into a session here, and it points at this file. So when somebody
168
+ arrives asking you to set up the Paneltir panel, this is the answer, and the
169
+ job is to walk them through it rather than to hand them a list.
170
+
171
+ Four things live in the **hosting environment** — never in this repository, and
172
+ never in the board.
173
+
174
+ | | What it is | Without it |
175
+ | --- | --- | --- |
176
+ | `ADMIN_PASSWORD` | The panel's password. | The gate answers 503 rather than letting anyone in. It fails closed on purpose: a panel with no password must not become a public one. |
177
+ | `GH_TOKEN` | A GitHub fine-grained token, **Contents: read and write, on this repository only**. | Everything works and Save fails. |
178
+ | `PANEL_REPO` | This project's `owner/repo`. | Save has nowhere to write. There is no default, because writing to the wrong repository is worse than not writing. |
179
+ | `SESSION_SECRET` | Optional; signs the session cookie. Defaults to `ADMIN_PASSWORD`. | Nothing, until the password changes — at which point every session already issued ends, which is usually what was wanted. |
180
+
181
+ `PANEL_FILE` is there too, and only matters when the board is somewhere other
182
+ than `src/data/panel-state.json`.
183
+
184
+ Three things are worth saying while you walk somebody through it:
185
+
186
+ - **Environment variables are read at deploy time.** Adding one to a running
187
+ deployment changes nothing until it redeploys. More than half of "I added it
188
+ and it still says missing" is this.
189
+ - **Scope the token to this repository alone.** A token that can write to
190
+ everything is a token whose blast radius is everything, and this one only
191
+ ever commits one file.
192
+ - **Check, do not assume.** The panel's Help screen asks the server what is
193
+ actually set and reports *whether*, never the value. That answer is worth
194
+ more than a screenshot of a settings page.
195
+
196
+ Then two things to try before the gate is trusted, because a door nobody has
197
+ pushed is not known to be shut:
198
+
199
+ 1. Open `/admin` signed out. It must land on the sign-in screen.
200
+ 2. Signed out, request the panel's own JavaScript bundle. It must answer 401.
201
+ A page that is protected while its bundle is not leaves the board readable
202
+ by anyone who opens the HTML — and that is the failure that looks exactly
203
+ like everything working.
204
+
135
205
  ## When the board will not open
136
206
 
137
207
  Run `npx paneltir board`. It reads the file and names every problem by