@boxa-devops/depo-shared 1.0.1

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 (51) hide show
  1. package/README.md +72 -0
  2. package/dist/LangSwitch.d.ts +22 -0
  3. package/dist/LangSwitch.d.ts.map +1 -0
  4. package/dist/LangSwitch.js +26 -0
  5. package/dist/LangSwitch.js.map +1 -0
  6. package/dist/PartPhoto.d.ts +13 -0
  7. package/dist/PartPhoto.d.ts.map +1 -0
  8. package/dist/PartPhoto.js +21 -0
  9. package/dist/PartPhoto.js.map +1 -0
  10. package/dist/api.d.ts +20739 -0
  11. package/dist/api.d.ts.map +1 -0
  12. package/dist/api.js +6 -0
  13. package/dist/api.js.map +1 -0
  14. package/dist/errors.d.ts +18 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +18 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/i18nGuard.d.ts +29 -0
  19. package/dist/i18nGuard.d.ts.map +1 -0
  20. package/dist/i18nGuard.js +75 -0
  21. package/dist/i18nGuard.js.map +1 -0
  22. package/dist/i18nKeys.d.ts +16 -0
  23. package/dist/i18nKeys.d.ts.map +1 -0
  24. package/dist/i18nKeys.js +16 -0
  25. package/dist/i18nKeys.js.map +1 -0
  26. package/dist/index.d.ts +96 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +39 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lang.d.ts +7 -0
  31. package/dist/lang.d.ts.map +1 -0
  32. package/dist/lang.js +24 -0
  33. package/dist/lang.js.map +1 -0
  34. package/dist/status.d.ts +3 -0
  35. package/dist/status.d.ts.map +1 -0
  36. package/dist/status.js +23 -0
  37. package/dist/status.js.map +1 -0
  38. package/error_codes.json +699 -0
  39. package/openapi.json +42042 -0
  40. package/package.json +53 -0
  41. package/permissions.json +70 -0
  42. package/src/LangSwitch.tsx +44 -0
  43. package/src/PartPhoto.tsx +48 -0
  44. package/src/api.ts +20739 -0
  45. package/src/errors.ts +25 -0
  46. package/src/i18nGuard.ts +77 -0
  47. package/src/i18nKeys.ts +15 -0
  48. package/src/index.ts +168 -0
  49. package/src/lang.ts +26 -0
  50. package/src/status.ts +23 -0
  51. package/tokens.css +141 -0
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@boxa-devops/depo-shared",
3
+ "version": "1.0.1",
4
+ "description": "Wire contract between depo-api, depo-terminal and depo-admin: generated API types, design tokens, shared guards.",
5
+ "type": "module",
6
+ "license": "UNLICENSED",
7
+ "repository": "github:boxa-devops/depo-contract",
8
+ "publishConfig": {
9
+ "registry": "https://registry.npmjs.org",
10
+ "access": "public"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "src",
15
+ "!src/**/*.test.ts",
16
+ "tokens.css",
17
+ "permissions.json",
18
+ "error_codes.json",
19
+ "openapi.json"
20
+ ],
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ },
27
+ "./tokens.css": "./tokens.css",
28
+ "./permissions.json": "./permissions.json",
29
+ "./error_codes.json": "./error_codes.json",
30
+ "./openapi.json": "./openapi.json"
31
+ },
32
+ "peerDependencies": {
33
+ "i18next": "^24.2.2",
34
+ "react": "^18.3.1",
35
+ "react-i18next": "^15.4.0"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^9.18.0",
39
+ "@types/react": "^18.3.18",
40
+ "eslint": "^9.18.0",
41
+ "openapi-typescript": "^7.5.2",
42
+ "typescript": "^5.7.3",
43
+ "typescript-eslint": "^8.20.0",
44
+ "vitest": "^3.2.7"
45
+ },
46
+ "scripts": {
47
+ "generate": "openapi-typescript openapi.json -o src/api.ts",
48
+ "build": "tsc -p tsconfig.build.json",
49
+ "typecheck": "tsc --noEmit",
50
+ "lint": "eslint src",
51
+ "test": "vitest run"
52
+ }
53
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "ADMIN": [
3
+ "count_inventory",
4
+ "edit_dictionaries",
5
+ "edit_passport",
6
+ "import_items",
7
+ "start_inventory",
8
+ "storno_event",
9
+ "view_dashboard",
10
+ "view_defects",
11
+ "view_dictionaries",
12
+ "view_inventory",
13
+ "view_items",
14
+ "view_orders",
15
+ "view_reports"
16
+ ],
17
+ "CHIEF": [
18
+ "approve_discrepancies",
19
+ "approve_disposition",
20
+ "approve_scrap",
21
+ "count_inventory",
22
+ "edit_passport",
23
+ "import_items",
24
+ "propose_disposition",
25
+ "start_inventory",
26
+ "storno_event",
27
+ "view_dashboard",
28
+ "view_defects",
29
+ "view_inventory",
30
+ "view_items",
31
+ "view_orders",
32
+ "view_reports"
33
+ ],
34
+ "FITTER": [
35
+ "view_dashboard",
36
+ "view_defects",
37
+ "view_inventory",
38
+ "view_items",
39
+ "view_orders",
40
+ "view_reports"
41
+ ],
42
+ "MASTER": [
43
+ "count_inventory",
44
+ "propose_disposition",
45
+ "view_dashboard",
46
+ "view_defects",
47
+ "view_inventory",
48
+ "view_items",
49
+ "view_orders",
50
+ "view_reports"
51
+ ],
52
+ "QC": [
53
+ "propose_disposition",
54
+ "view_dashboard",
55
+ "view_defects",
56
+ "view_inventory",
57
+ "view_items",
58
+ "view_orders",
59
+ "view_reports"
60
+ ],
61
+ "STOREKEEPER": [
62
+ "count_inventory",
63
+ "view_dashboard",
64
+ "view_defects",
65
+ "view_inventory",
66
+ "view_items",
67
+ "view_orders",
68
+ "view_reports"
69
+ ]
70
+ }
@@ -0,0 +1,44 @@
1
+ import { useTranslation } from "react-i18next";
2
+
3
+ import { LANGS, setLanguage } from "./lang.js";
4
+
5
+ /** RU/UZ toggle. i18next re-renders every consumer on change, so no reload.
6
+ * Two sizes: "desk" for the admin header, "kiosk" for 48px monoblock targets.
7
+ * `type` is part of the preset on purpose — the desk switch sits inside the
8
+ * login <form> and has always rendered a default (submit) button; changing
9
+ * that is a behaviour change, see docs/DEBT.md. */
10
+ const PRESET = {
11
+ desk: {
12
+ wrap: "gap-0.5",
13
+ type: "submit" as const,
14
+ cls: (on: boolean) =>
15
+ `rounded-md px-2 py-1 text-xs font-medium uppercase transition ${
16
+ on ? "bg-accent-tint text-accent" : "text-ink-3 hover:bg-hover hover:text-ink"
17
+ }`,
18
+ },
19
+ kiosk: {
20
+ wrap: "gap-1",
21
+ type: "button" as const,
22
+ cls: (on: boolean) => `chip font-semibold uppercase ${on ? "chip-active" : ""}`,
23
+ },
24
+ };
25
+
26
+ export function LangSwitch({ size = "desk" }: { size?: keyof typeof PRESET }) {
27
+ const { i18n, t } = useTranslation();
28
+ const p = PRESET[size];
29
+ return (
30
+ <div className={`flex items-center ${p.wrap}`} role="group" aria-label={t("lang.switch")}>
31
+ {LANGS.map((l) => (
32
+ <button
33
+ key={l}
34
+ type={p.type}
35
+ onClick={() => setLanguage(l)}
36
+ aria-pressed={i18n.language === l}
37
+ className={p.cls(i18n.language === l)}
38
+ >
39
+ {l}
40
+ </button>
41
+ ))}
42
+ </div>
43
+ );
44
+ }
@@ -0,0 +1,48 @@
1
+ /** The picture of a part TYPE, with the fallback that matters more than the
2
+ * picture: a type with no photo gets its CODE on a coloured plate, not an
3
+ * empty frame. The colour is derived from the code, so the same type keeps
4
+ * the same plate on every screen and a master recognises it by shape+colour
5
+ * long before reading it. */
6
+
7
+ /** Stable hue for a code — plain FNV-ish walk, no hashing library. */
8
+ function hueOf(code: string): number {
9
+ let h = 0;
10
+ for (const ch of code) h = (h * 31 + ch.codePointAt(0)!) % 360;
11
+ return h;
12
+ }
13
+
14
+ export function PartPhoto({
15
+ photoKey,
16
+ code,
17
+ name,
18
+ className = "",
19
+ }: {
20
+ photoKey: string | null | undefined;
21
+ code: string;
22
+ name?: string;
23
+ /** sizing/rounding of the box — the caller owns the geometry */
24
+ className?: string;
25
+ }) {
26
+ if (photoKey) {
27
+ return (
28
+ <img
29
+ src={`/api/v1/attachments/${photoKey}`}
30
+ alt={name ?? code}
31
+ loading="lazy"
32
+ className={`object-cover ${className}`}
33
+ />
34
+ );
35
+ }
36
+ const hue = hueOf(code);
37
+ return (
38
+ <div
39
+ role="img"
40
+ aria-label={name ?? code}
41
+ data-placeholder={code}
42
+ className={`flex items-center justify-center overflow-hidden px-1 text-center font-mono font-bold leading-none tracking-tight ${className}`}
43
+ style={{ background: `hsl(${hue} 55% 88%)`, color: `hsl(${hue} 70% 26%)` }}
44
+ >
45
+ {code}
46
+ </div>
47
+ );
48
+ }