paneltir 0.7.0 → 0.8.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/INSTALL.md +2 -2
- package/README.md +1 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +115 -3
- package/fingerprint.json +4 -4
- package/package.json +3 -2
package/INSTALL.md
CHANGED
|
@@ -19,7 +19,7 @@ identity** — never another project's.
|
|
|
19
19
|
npm install paneltir
|
|
20
20
|
|
|
21
21
|
# or, without npm access, straight from the repository:
|
|
22
|
-
# npm install github:daifukus/paneltir#v0.
|
|
22
|
+
# npm install github:daifukus/paneltir#v0.8.0
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
(Use the tag you were given; never install without pinning a version.)
|
|
@@ -181,7 +181,7 @@ identity** — never another project's.
|
|
|
181
181
|
|
|
182
182
|
```bash
|
|
183
183
|
npx paneltir version # version, fingerprint, where it came from
|
|
184
|
-
npx paneltir check 0.
|
|
184
|
+
npx paneltir check 0.8.0 # exits non-zero if that is not what is installed
|
|
185
185
|
npx paneltir board # read the board and say what is wrong with it
|
|
186
186
|
```
|
|
187
187
|
|
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ tag rather than a branch, so an unfinished push cannot reach a project:
|
|
|
54
54
|
npm install paneltir
|
|
55
55
|
|
|
56
56
|
# or, without npm access, straight from the repository:
|
|
57
|
-
# npm install github:daifukus/paneltir#v0.
|
|
57
|
+
# npm install github:daifukus/paneltir#v0.8.0
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
Installing from Git runs the `prepare` script, which builds `dist/`, so the
|
package/dist/index.d.ts
CHANGED
|
@@ -872,6 +872,14 @@ interface Preferences {
|
|
|
872
872
|
seen?: string[];
|
|
873
873
|
/** Ids of guide notes already dismissed. */
|
|
874
874
|
guideDismissed?: string[];
|
|
875
|
+
/**
|
|
876
|
+
* Whether an update card is written as an order rather than a suggestion.
|
|
877
|
+
*
|
|
878
|
+
* It does not make anything automatic — the panel cannot run npm, and this
|
|
879
|
+
* changes `order` on the card it offers to write, nothing else. Off means
|
|
880
|
+
* the card asks; on means it tells.
|
|
881
|
+
*/
|
|
882
|
+
updateAsOrder?: boolean;
|
|
875
883
|
}
|
|
876
884
|
interface PanelState {
|
|
877
885
|
v: 2;
|
|
@@ -1117,6 +1125,19 @@ interface UiStrings {
|
|
|
1117
1125
|
analysis: string;
|
|
1118
1126
|
/** The Revisions tab. Short, because it sits beside Board and Analysis. */
|
|
1119
1127
|
history: string;
|
|
1128
|
+
updateTitle: string;
|
|
1129
|
+
updateSubtitle: string;
|
|
1130
|
+
updateCurrent: (version: string) => string;
|
|
1131
|
+
updateAvailable: (version: string) => string;
|
|
1132
|
+
updateUpToDate: string;
|
|
1133
|
+
updateUnknown: string;
|
|
1134
|
+
updateCreateCard: string;
|
|
1135
|
+
updateCardExists: string;
|
|
1136
|
+
updateAsOrder: string;
|
|
1137
|
+
updateAsOrderHow: string;
|
|
1138
|
+
notifUpdate: string;
|
|
1139
|
+
updateCardTitle: (version: string) => string;
|
|
1140
|
+
updateCardBody: (version: string) => string;
|
|
1120
1141
|
cardDetail: string;
|
|
1121
1142
|
panelSettings: string;
|
|
1122
1143
|
title: string;
|
|
@@ -1419,6 +1440,14 @@ interface PanelAppProps {
|
|
|
1419
1440
|
showLanguage?: boolean;
|
|
1420
1441
|
/** The revision log: one entry per session, newest first. */
|
|
1421
1442
|
showHistory?: boolean;
|
|
1443
|
+
/**
|
|
1444
|
+
* Ask the public npm registry whether a newer kit has been published.
|
|
1445
|
+
*
|
|
1446
|
+
* Opt-in, because it is a request leaving the reader's browser and that is
|
|
1447
|
+
* the caller's decision rather than the kit's. Nothing is installed either
|
|
1448
|
+
* way: the panel offers to write a card, and a session acts on it.
|
|
1449
|
+
*/
|
|
1450
|
+
checkForUpdates?: boolean;
|
|
1422
1451
|
/** Endpoint that commits the board back to the repository, when there is one. */
|
|
1423
1452
|
saveEndpoint?: string;
|
|
1424
1453
|
/**
|
|
@@ -1436,7 +1465,7 @@ interface PanelAppProps {
|
|
|
1436
1465
|
fileCount: number;
|
|
1437
1466
|
};
|
|
1438
1467
|
}
|
|
1439
|
-
declare function PanelApp({ state: initialState, themes, defaultTheme, brand, decoration, className, footer, links, capabilities, extras, showLanguage, showHistory, saveEndpoint, marketplaceEndpoint, marketplaceReport, fingerprint, }: PanelAppProps): React.JSX.Element;
|
|
1468
|
+
declare function PanelApp({ state: initialState, themes, defaultTheme, brand, decoration, className, footer, links, capabilities, extras, showLanguage, showHistory, checkForUpdates, saveEndpoint, marketplaceEndpoint, marketplaceReport, fingerprint, }: PanelAppProps): React.JSX.Element;
|
|
1440
1469
|
|
|
1441
1470
|
/**
|
|
1442
1471
|
* Applies a board move to the flat card list.
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var PANELTIR_VERSION = "0.
|
|
3
|
-
var PANELTIR_FINGERPRINT = "sha256:
|
|
4
|
-
var PANELTIR_FILE_COUNT =
|
|
2
|
+
var PANELTIR_VERSION = "0.8.0";
|
|
3
|
+
var PANELTIR_FINGERPRINT = "sha256:a252ef2a015240e0e8463c0ebb0ef7a8af80ad7ade66f2c48e71657500d506d5";
|
|
4
|
+
var PANELTIR_FILE_COUNT = 153;
|
|
5
5
|
var paneltirBuild = {
|
|
6
6
|
version: PANELTIR_VERSION,
|
|
7
7
|
fingerprint: PANELTIR_FINGERPRINT,
|
|
@@ -1302,6 +1302,37 @@ function isCard(value) {
|
|
|
1302
1302
|
// src/panel/PanelApp.tsx
|
|
1303
1303
|
import React12, { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo5, useState as useState9 } from "react";
|
|
1304
1304
|
|
|
1305
|
+
// src/panel/updates.ts
|
|
1306
|
+
var REGISTRY_URL = "https://registry.npmjs.org/paneltir/latest";
|
|
1307
|
+
function isNewer(candidate, current) {
|
|
1308
|
+
const parts = (value) => value.trim().replace(/^v/, "").split(/[-+]/)[0].split(".").map((piece) => Number.parseInt(piece, 10));
|
|
1309
|
+
const left = parts(candidate);
|
|
1310
|
+
const right = parts(current);
|
|
1311
|
+
if (left.some(Number.isNaN) || right.some(Number.isNaN)) return false;
|
|
1312
|
+
for (let i = 0; i < 3; i += 1) {
|
|
1313
|
+
const a = left[i] ?? 0;
|
|
1314
|
+
const b = right[i] ?? 0;
|
|
1315
|
+
if (a !== b) return a > b;
|
|
1316
|
+
}
|
|
1317
|
+
return false;
|
|
1318
|
+
}
|
|
1319
|
+
async function checkForUpdate(current, fetchImpl = fetch) {
|
|
1320
|
+
try {
|
|
1321
|
+
const response = await fetchImpl(REGISTRY_URL, { headers: { accept: "application/json" } });
|
|
1322
|
+
if (!response.ok) return null;
|
|
1323
|
+
const body = await response.json();
|
|
1324
|
+
const latest = typeof body.version === "string" ? body.version : null;
|
|
1325
|
+
if (!latest) return null;
|
|
1326
|
+
return { current, latest, behind: isNewer(latest, current) };
|
|
1327
|
+
} catch {
|
|
1328
|
+
return null;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
function updateCardId(version) {
|
|
1332
|
+
const found = /\d+\.\d+\.\d+/.exec(version);
|
|
1333
|
+
return `paneltir-update-${found ? found[0] : "unknown"}`;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1305
1336
|
// src/panel/themes.ts
|
|
1306
1337
|
var PRESET_FORM = {
|
|
1307
1338
|
midnight: THEME_FORMS.panel,
|
|
@@ -1356,6 +1387,19 @@ var UI = {
|
|
|
1356
1387
|
board: "Board",
|
|
1357
1388
|
analysis: "Analysis",
|
|
1358
1389
|
history: "Revisions",
|
|
1390
|
+
updateTitle: "The kit this panel runs on",
|
|
1391
|
+
updateSubtitle: "What is installed, and what has been published since.",
|
|
1392
|
+
updateCurrent: (version) => `Installed: v${version}`,
|
|
1393
|
+
updateAvailable: (version) => `v${version} has been published.`,
|
|
1394
|
+
updateUpToDate: "This is the newest published version.",
|
|
1395
|
+
updateUnknown: "The registry could not be reached, so there is nothing to report either way.",
|
|
1396
|
+
updateCreateCard: "Add a card asking for it",
|
|
1397
|
+
updateCardExists: "The board already carries a card for this version.",
|
|
1398
|
+
updateAsOrder: "Write it as an order, not a suggestion",
|
|
1399
|
+
updateAsOrderHow: "This does not update anything on its own \u2014 the panel cannot run npm. It decides whether the card it writes asks for the update or instructs it.",
|
|
1400
|
+
notifUpdate: "A newer Paneltir has been published",
|
|
1401
|
+
updateCardTitle: (version) => `Update Paneltir to v${version}`,
|
|
1402
|
+
updateCardBody: (version) => `Run \`npm install paneltir@${version}\` in this project, then check the panel still builds and renders. The version in use is reported by \`paneltirBuild\`, so it can be confirmed rather than assumed.`,
|
|
1359
1403
|
cardDetail: "Card",
|
|
1360
1404
|
panelSettings: "Panel settings",
|
|
1361
1405
|
title: "Title",
|
|
@@ -1617,6 +1661,19 @@ var UI = {
|
|
|
1617
1661
|
board: "Tablero",
|
|
1618
1662
|
analysis: "An\xE1lisis",
|
|
1619
1663
|
history: "Revisiones",
|
|
1664
|
+
updateTitle: "El kit sobre el que corre este panel",
|
|
1665
|
+
updateSubtitle: "Qu\xE9 hay instalado, y qu\xE9 se ha publicado desde entonces.",
|
|
1666
|
+
updateCurrent: (version) => `Instalada: v${version}`,
|
|
1667
|
+
updateAvailable: (version) => `Se ha publicado la v${version}.`,
|
|
1668
|
+
updateUpToDate: "Esta es la versi\xF3n publicada m\xE1s reciente.",
|
|
1669
|
+
updateUnknown: "No se pudo consultar el registro, as\xED que no hay nada que decir en ning\xFAn sentido.",
|
|
1670
|
+
updateCreateCard: "A\xF1adir una tarjeta pidi\xE9ndolo",
|
|
1671
|
+
updateCardExists: "El tablero ya lleva una tarjeta para esta versi\xF3n.",
|
|
1672
|
+
updateAsOrder: "Escribirla como orden, no como sugerencia",
|
|
1673
|
+
updateAsOrderHow: "Esto no actualiza nada por su cuenta \u2014 el panel no puede ejecutar npm. Decide si la tarjeta que escribe pide la actualizaci\xF3n o la manda.",
|
|
1674
|
+
notifUpdate: "Se ha publicado un Paneltir m\xE1s nuevo",
|
|
1675
|
+
updateCardTitle: (version) => `Actualizar Paneltir a la v${version}`,
|
|
1676
|
+
updateCardBody: (version) => `Ejecuta \`npm install paneltir@${version}\` en este proyecto y comprueba que el panel sigue construy\xE9ndose y dibuj\xE1ndose. La versi\xF3n en uso la reporta \`paneltirBuild\`, as\xED que se puede confirmar en vez de darla por hecha.`,
|
|
1620
1677
|
cardDetail: "Tarjeta",
|
|
1621
1678
|
panelSettings: "Ajustes del panel",
|
|
1622
1679
|
title: "T\xEDtulo",
|
|
@@ -2685,6 +2742,7 @@ function PanelApp({
|
|
|
2685
2742
|
extras,
|
|
2686
2743
|
showLanguage,
|
|
2687
2744
|
showHistory,
|
|
2745
|
+
checkForUpdates,
|
|
2688
2746
|
saveEndpoint,
|
|
2689
2747
|
marketplaceEndpoint,
|
|
2690
2748
|
marketplaceReport,
|
|
@@ -2702,6 +2760,7 @@ function PanelApp({
|
|
|
2702
2760
|
const [filter, setFilter] = useState9("all");
|
|
2703
2761
|
const [openCardId, setOpenCardId] = useState9(null);
|
|
2704
2762
|
const [settingsOpen, setSettingsOpen] = useState9(false);
|
|
2763
|
+
const [update, setUpdate] = useState9(null);
|
|
2705
2764
|
const [helpOpen, setHelpOpen] = useState9(false);
|
|
2706
2765
|
const [setup, setSetup] = useState9(null);
|
|
2707
2766
|
const [signOut, setSignOut] = useState9("idle");
|
|
@@ -2810,6 +2869,15 @@ function PanelApp({
|
|
|
2810
2869
|
onOpen: () => setOpenCardId(card.id)
|
|
2811
2870
|
});
|
|
2812
2871
|
}
|
|
2872
|
+
if (update?.behind && !state.cards.some((card) => card.id === updateCardId(update.latest))) {
|
|
2873
|
+
items.push({
|
|
2874
|
+
id: `paneltir-update:${update.latest}`,
|
|
2875
|
+
tone: "info",
|
|
2876
|
+
title: ui.notifUpdate,
|
|
2877
|
+
detail: ui.updateAvailable(update.latest),
|
|
2878
|
+
onOpen: () => setSettingsOpen(true)
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2813
2881
|
if (state.importedTheme?.refreshRequested) {
|
|
2814
2882
|
items.push({
|
|
2815
2883
|
id: `theme-refresh:${state.importedTheme.refreshRequested}`,
|
|
@@ -2889,6 +2957,23 @@ function PanelApp({
|
|
|
2889
2957
|
},
|
|
2890
2958
|
[state.areas]
|
|
2891
2959
|
);
|
|
2960
|
+
const addUpdateCard = useCallback5(() => {
|
|
2961
|
+
if (!update?.behind) return;
|
|
2962
|
+
const id = updateCardId(update.latest);
|
|
2963
|
+
if (state.cards.some((card2) => card2.id === id)) return;
|
|
2964
|
+
const card = {
|
|
2965
|
+
...emptyCard("next", state.areas[0]?.id ?? "general"),
|
|
2966
|
+
id,
|
|
2967
|
+
title: { en: UI.en.updateCardTitle(update.latest), es: UI.es.updateCardTitle(update.latest) },
|
|
2968
|
+
body: { en: UI.en.updateCardBody(update.latest), es: UI.es.updateCardBody(update.latest) },
|
|
2969
|
+
priority: "medium",
|
|
2970
|
+
risk: "low",
|
|
2971
|
+
owner: "claude",
|
|
2972
|
+
order: state.preferences?.updateAsOrder === true
|
|
2973
|
+
};
|
|
2974
|
+
setState((current) => ({ ...current, updatedAt: today(), cards: [...current.cards, card] }));
|
|
2975
|
+
setOpenCardId(id);
|
|
2976
|
+
}, [update, state.cards, state.areas, state.preferences?.updateAsOrder]);
|
|
2892
2977
|
const moveCard = useCallback5(
|
|
2893
2978
|
(move) => {
|
|
2894
2979
|
setState((current) => {
|
|
@@ -3008,6 +3093,16 @@ function PanelApp({
|
|
|
3008
3093
|
setMarketAsked(true);
|
|
3009
3094
|
loadMarketplace(false);
|
|
3010
3095
|
}, [view, marketAsked, marketplaceEndpoint, loadMarketplace]);
|
|
3096
|
+
useEffect9(() => {
|
|
3097
|
+
if (!checkForUpdates || !fingerprint?.version) return;
|
|
3098
|
+
let cancelled = false;
|
|
3099
|
+
void checkForUpdate(fingerprint.version).then((status2) => {
|
|
3100
|
+
if (!cancelled) setUpdate(status2);
|
|
3101
|
+
});
|
|
3102
|
+
return () => {
|
|
3103
|
+
cancelled = true;
|
|
3104
|
+
};
|
|
3105
|
+
}, [checkForUpdates, fingerprint?.version]);
|
|
3011
3106
|
useEffect9(() => {
|
|
3012
3107
|
if (!helpOpen || !saveEndpoint || setup) return;
|
|
3013
3108
|
let cancelled = false;
|
|
@@ -3512,6 +3607,23 @@ function PanelApp({
|
|
|
3512
3607
|
/* @__PURE__ */ jsx19("p", { className: "pt-marketplace__detail", children: ui.importedRefreshHow })
|
|
3513
3608
|
] })
|
|
3514
3609
|
] }),
|
|
3610
|
+
checkForUpdates && fingerprint?.version && /* @__PURE__ */ jsxs17(DetailSection, { title: ui.updateTitle, subtitle: ui.updateSubtitle, children: [
|
|
3611
|
+
/* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.updateCurrent(fingerprint.version) }),
|
|
3612
|
+
/* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: !update ? ui.updateUnknown : update.behind ? ui.updateAvailable(update.latest) : ui.updateUpToDate }),
|
|
3613
|
+
update?.behind && (state.cards.some((card) => card.id === updateCardId(update.latest)) ? /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.updateCardExists }) : /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", style: { marginTop: 12 }, children: /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn", onClick: addUpdateCard, children: ui.updateCreateCard }) })),
|
|
3614
|
+
/* @__PURE__ */ jsxs17("label", { className: "pt-panel-row", style: { marginTop: 12 }, children: [
|
|
3615
|
+
/* @__PURE__ */ jsx19(
|
|
3616
|
+
"input",
|
|
3617
|
+
{
|
|
3618
|
+
type: "checkbox",
|
|
3619
|
+
checked: state.preferences?.updateAsOrder === true,
|
|
3620
|
+
onChange: (event) => setPreference("updateAsOrder", event.target.checked)
|
|
3621
|
+
}
|
|
3622
|
+
),
|
|
3623
|
+
/* @__PURE__ */ jsx19("span", { className: "pt-panel-text", children: ui.updateAsOrder })
|
|
3624
|
+
] }),
|
|
3625
|
+
/* @__PURE__ */ jsx19("p", { className: "pt-marketplace__detail", children: ui.updateAsOrderHow })
|
|
3626
|
+
] }),
|
|
3515
3627
|
fingerprint && /* @__PURE__ */ jsxs17(DetailSection, { title: ui.fingerprint, subtitle: ui.fingerprintSubtitle, children: [
|
|
3516
3628
|
/* @__PURE__ */ jsx19("p", { className: "pt-panel-mono", children: fingerprint.hash }),
|
|
3517
3629
|
/* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.trackedFiles(fingerprint.fileCount, fingerprint.version) })
|
package/fingerprint.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paneltir",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"hash": "sha256:
|
|
5
|
-
"fileCount":
|
|
6
|
-
"generatedAt": "2026-09-07T12:
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"hash": "sha256:a252ef2a015240e0e8463c0ebb0ef7a8af80ad7ade66f2c48e71657500d506d5",
|
|
5
|
+
"fileCount": 153,
|
|
6
|
+
"generatedAt": "2026-09-07T12:59:14.850Z"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paneltir",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.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 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:updates && 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,6 +72,7 @@
|
|
|
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
|
+
"test:updates": "node scripts/test-updates.mjs",
|
|
75
76
|
"test:board": "node scripts/test-board.mjs"
|
|
76
77
|
},
|
|
77
78
|
"peerDependencies": {
|