@bazous/ui 0.3.2

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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/answers/AnswerPicture.d.ts +13 -0
  4. package/dist/answers/contract.d.ts +160 -0
  5. package/dist/answers/draw.d.ts +16 -0
  6. package/dist/answers/index.d.ts +6 -0
  7. package/dist/answers/messages.d.ts +3 -0
  8. package/dist/answers.js +10 -0
  9. package/dist/answers.js.map +1 -0
  10. package/dist/canvas/index.d.ts +32 -0
  11. package/dist/canvas.js +285 -0
  12. package/dist/canvas.js.map +1 -0
  13. package/dist/contract/snapshot.d.ts +173 -0
  14. package/dist/engine/scenario.d.ts +40 -0
  15. package/dist/format/index.d.ts +37 -0
  16. package/dist/i18n/index.d.ts +25 -0
  17. package/dist/i18n/shared.d.ts +3 -0
  18. package/dist/index-yeBMtDf1.js +649 -0
  19. package/dist/index-yeBMtDf1.js.map +1 -0
  20. package/dist/index.d.ts +20 -0
  21. package/dist/index.js +1258 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/modules/Question.d.ts +18 -0
  24. package/dist/modules/available-now/index.d.ts +8 -0
  25. package/dist/modules/due-before-payday/index.d.ts +9 -0
  26. package/dist/modules/low-point/index.d.ts +12 -0
  27. package/dist/modules/margin-after-payday/index.d.ts +9 -0
  28. package/dist/modules/monthly-structure/index.d.ts +24 -0
  29. package/dist/modules/next-actions/index.d.ts +13 -0
  30. package/dist/modules/pay-cycles/index.d.ts +31 -0
  31. package/dist/modules/registry.d.ts +7 -0
  32. package/dist/modules/types.d.ts +77 -0
  33. package/dist/modules/what-if/index.d.ts +6 -0
  34. package/dist/primitives/CashflowChart.d.ts +22 -0
  35. package/dist/primitives/index.d.ts +57 -0
  36. package/dist/styles.css +1 -0
  37. package/package.json +84 -0
  38. package/schema/answers.schema.json +719 -0
  39. package/schema/canvas.json +181 -0
  40. package/schema/snapshot.schema.json +821 -0
@@ -0,0 +1,57 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Tone } from "../format";
3
+ /**
4
+ * Primitives: the only markup modules are expected to use. Every class starts
5
+ * with `bz-` so the kit never collides with the host application's styles.
6
+ */
7
+ export declare function Card({ question, title, meta, actions, children, className }: {
8
+ /** The money question, shown small above the title. */
9
+ question?: string;
10
+ title?: ReactNode;
11
+ meta?: ReactNode;
12
+ actions?: ReactNode;
13
+ children: ReactNode;
14
+ className?: string;
15
+ }): import("react").JSX.Element;
16
+ export declare function Tile({ question, label, value, unit, note, tone, emphasis }: {
17
+ question: string;
18
+ label: string;
19
+ value: string;
20
+ unit: string;
21
+ note?: ReactNode;
22
+ tone?: Tone;
23
+ /** The one number that matters most on the page (the low point): drawn in gold. */
24
+ emphasis?: boolean;
25
+ }): import("react").JSX.Element;
26
+ export declare function Row({ date, title, sub, amount, amountTone, late, children }: {
27
+ date?: string;
28
+ title: ReactNode;
29
+ sub?: ReactNode;
30
+ amount?: ReactNode;
31
+ amountTone?: Tone;
32
+ late?: boolean;
33
+ children?: ReactNode;
34
+ }): import("react").JSX.Element;
35
+ export declare function Button({ children, onClick, variant, disabled }: {
36
+ children: ReactNode;
37
+ onClick: () => void;
38
+ variant?: "primary" | "secondary" | "ghost" | "link";
39
+ disabled?: boolean;
40
+ }): import("react").JSX.Element;
41
+ export declare function Segmented<K extends string>({ options, value, onChange, label }: {
42
+ options: {
43
+ key: K;
44
+ label: string;
45
+ }[];
46
+ value: K;
47
+ onChange: (key: K) => void;
48
+ label: string;
49
+ }): import("react").JSX.Element;
50
+ export declare function Dot({ tone }: {
51
+ tone: "danger" | "warn" | "muted";
52
+ }): import("react").JSX.Element;
53
+ export declare function Empty({ children }: {
54
+ children: ReactNode;
55
+ }): import("react").JSX.Element;
56
+ /** Proportional bars (drivers, categories) in the kit's four ink shades. */
57
+ export declare const SHADES: readonly ["bz-shade-1", "bz-shade-2", "bz-shade-3", "bz-shade-4"];
@@ -0,0 +1 @@
1
+ .bz,.bz[data-theme=dark]{color-scheme:dark;--bz-bg: #0b0b0b;--bz-surface: #141414;--bz-surface-2: #1a1a1a;--bz-line: rgba(218, 175, 55, .22);--bz-line-2: #2a2926;--bz-text: #f5f3ed;--bz-text-2: #d9d6ce;--bz-muted: #b7b5ae;--bz-faint: #8a877f;--bz-accent: #daaf37;--bz-accent-2: #e8c46e;--bz-on-accent: #0b0b0b;--bz-positive: #76cca1;--bz-negative: #ff9292;--bz-warning: #e8c46e;--bz-danger-band: rgba(255, 146, 146, .1);--bz-control: #262521;--bz-control-hover: #332f25;--bz-control-on: #42351c;--bz-control-line: #655d4c;--bz-emphasis-bg: #0b0b0b;--bz-emphasis-line: #daaf37;--bz-emphasis-text: #f5f3ed;--bz-emphasis-muted: #b7b5ae;--bz-shade-1: #f5f3ed;--bz-shade-2: #c9c5bb;--bz-shade-3: #8a877f;--bz-shade-4: #5b5953;--bz-shadow: 0 24px 60px rgba(0, 0, 0, .45)}.bz[data-theme=light]{color-scheme:light;--bz-bg: #f5f3ed;--bz-surface: #ffffff;--bz-surface-2: #fbf8ee;--bz-line: #e2e3e2;--bz-line-2: #ecebe6;--bz-text: #15191f;--bz-text-2: #323943;--bz-muted: #555e6b;--bz-faint: #838a93;--bz-accent: #896313;--bz-accent-2: #daaf37;--bz-on-accent: #ffffff;--bz-positive: #1b704a;--bz-negative: #b33535;--bz-warning: #795012;--bz-danger-band: rgba(179, 53, 53, .08);--bz-control: #ffffff;--bz-control-hover: #fbf8ee;--bz-control-on: #fbf3dd;--bz-control-line: #cdd0d2;--bz-emphasis-bg: #0b0b0b;--bz-emphasis-line: #0b0b0b;--bz-emphasis-text: #f5f3ed;--bz-emphasis-muted: #b7b5ae;--bz-shade-1: #15191f;--bz-shade-2: #323943;--bz-shade-3: #6b7280;--bz-shade-4: #a8adb4;--bz-shadow: 0 1px 2px rgba(21, 25, 31, .04)}.bz{--bz-serif: "Playfair Display", Georgia, serif;--bz-sans: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;--bz-radius: 16px;--bz-radius-control: 10px;display:flex;flex-direction:column;gap:16px;background:var(--bz-bg);color:var(--bz-text);font-family:var(--bz-sans);font-size:14px;line-height:1.45;font-variant-numeric:tabular-nums}.bz *,.bz *:before,.bz *:after{box-sizing:border-box}.bz button{margin:0;letter-spacing:normal;text-transform:none;box-shadow:none}.bz h2,.bz h3,.bz p{margin:0}.bz-tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}.bz-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;align-items:start}.bz-slot{min-width:0}.bz-slot-full{grid-column:1 / -1}.bz-slot-wide{grid-column:span 2}.bz-slot-narrow{grid-column:span 1}.bz-split{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;align-items:start}.bz-span-2{grid-column:span 2}.bz-card,.bz-tile{background:var(--bz-surface);border:1px solid var(--bz-line);border-radius:var(--bz-radius);box-shadow:var(--bz-shadow);min-width:0}.bz-card{display:flex;flex-direction:column;gap:12px;padding:22px 24px}.bz-card-head{display:flex;align-items:flex-start;gap:12px 16px;flex-wrap:wrap;margin-bottom:2px}.bz-card-titles{display:flex;flex-direction:column;gap:4px;flex:1 1 auto;min-width:0}.bz-card-actions{display:flex;gap:8px;align-items:center}.bz-question,.bz-eyebrow{color:var(--bz-accent);font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase}.bz-title{font-family:var(--bz-serif);font-size:22px;font-weight:600;letter-spacing:-.01em;margin:0;line-height:1.15}.bz-meta{color:var(--bz-muted);font-size:12px;align-self:center}.bz-body{color:var(--bz-muted);font-size:13.5px;line-height:1.55}.bz-note{color:var(--bz-muted);font-size:12.5px}.bz-empty{color:var(--bz-faint);font-size:13px;padding:8px 0}.bz-rule{border:0;border-top:1px solid var(--bz-line-2);margin:4px 0;width:100%}.bz-tile{display:flex;flex-direction:column;gap:10px;padding:22px 24px}.bz-tile .bz-eyebrow{color:var(--bz-muted);letter-spacing:.08em}.bz-tile-value{font-family:var(--bz-serif);font-size:clamp(30px,3vw,40px);font-weight:600;letter-spacing:-.02em;line-height:1}.bz-unit{font-family:var(--bz-sans);font-size:13px;font-weight:500;color:var(--bz-muted);letter-spacing:.04em}.bz-tile-emphasis{background:var(--bz-emphasis-bg);border-color:var(--bz-emphasis-line);color:var(--bz-emphasis-text)}.bz-tile-emphasis .bz-eyebrow,.bz-tile-emphasis .bz-note,.bz-tile-emphasis .bz-unit{color:var(--bz-emphasis-muted)}.bz-tile-emphasis .bz-tile-value{color:#daaf37}.bz-tile-emphasis .bz-tile-value.bz-neg{color:#ff9292}.bz-neg{color:var(--bz-negative)}.bz-pos{color:var(--bz-positive)}.bz-muted{color:var(--bz-muted);font-weight:500}.bz-button{font:600 13px var(--bz-sans);height:36px;padding:0 14px;border-radius:var(--bz-radius-control);border:1px solid var(--bz-control-line);background:var(--bz-control);color:var(--bz-text);cursor:pointer;white-space:nowrap}.bz-button:hover:not(:disabled){background:var(--bz-control-hover)}.bz-button:disabled{opacity:.45;cursor:default}.bz-button:focus-visible,.bz-seg button:focus-visible,.bz-row-button:focus-visible,.bz-lever:focus-within{outline:2px solid var(--bz-accent);outline-offset:2px}.bz-primary{background:var(--bz-accent-2);border-color:var(--bz-accent-2);color:#0b0b0b}.bz-primary:hover:not(:disabled){background:#f0cf72}.bz-ghost{background:transparent;color:var(--bz-accent);border-color:var(--bz-line);height:32px;padding:0 12px}.bz-link{background:none;border:0;height:auto;padding:0;color:var(--bz-accent)}.bz-link:hover:not(:disabled){background:none;text-decoration:underline}.bz-seg{display:flex;gap:2px;padding:3px;background:var(--bz-control);border:1px solid var(--bz-line-2);border-radius:var(--bz-radius-control)}.bz-seg button{font:500 12px var(--bz-sans);height:28px;padding:0 10px;border:0;border-radius:7px;background:transparent;color:var(--bz-muted);cursor:pointer}.bz-seg button.bz-on{background:var(--bz-control-on);color:var(--bz-text);font-weight:600}.bz-row{display:flex;align-items:center;gap:12px;padding:11px 0;border-top:1px solid var(--bz-line-2);font-size:13.5px}.bz-row:first-child{border-top:0}.bz-row-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.bz-row-body strong{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bz-row-body span{color:var(--bz-muted);font-size:12px}.bz-wrap strong{white-space:normal}.bz-date{width:54px;flex:none;color:var(--bz-faint)}.bz-amount{font-weight:600;white-space:nowrap}.bz-late .bz-date,.bz-late .bz-amount{color:var(--bz-negative)}.bz-action{padding:14px 0;flex-wrap:wrap}.bz-row-button{width:100%;height:auto;min-height:0;margin:0;padding:11px 0;text-align:left;background:none;border:0;border-top:1px solid var(--bz-line-2);border-radius:0;box-shadow:none;color:inherit;font:inherit;cursor:pointer}.bz-row-button:hover .bz-row-body strong{text-decoration:underline;text-decoration-color:var(--bz-accent)}.bz-warn-row,.bz-warn-row .bz-date,.bz-warn-row strong{color:var(--bz-negative)}.bz-dot{width:10px;height:10px;border-radius:50%;flex:none}.bz-dot-danger{background:var(--bz-negative)}.bz-dot-warn{background:var(--bz-warning)}.bz-dot-muted{background:var(--bz-faint)}.bz-shade-1{background:var(--bz-shade-1)}.bz-shade-2{background:var(--bz-shade-2)}.bz-shade-3{background:var(--bz-shade-3)}.bz-shade-4{background:var(--bz-shade-4)}.bz-bars{display:flex;flex-direction:column;gap:8px}.bz-bar{display:flex;align-items:center;gap:10px;font-size:13px}.bz-bar i{display:inline-block;height:8px;border-radius:4px;flex:none}.bz-bar span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bz-bar em{color:var(--bz-faint);font-style:normal;font-size:11.5px}.bz-stack{display:flex;height:12px;border-radius:6px;overflow:hidden;background:var(--bz-line-2)}.bz-stack i{display:block;height:100%}.bz-cats{display:flex;flex-direction:column;gap:6px;font-size:13px}.bz-cats div{display:flex;align-items:center;gap:8px}.bz-cats i{width:10px;height:10px;border-radius:2px;flex:none}.bz-cats span{flex:1}.bz-inline{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}.bz-figure{font-family:var(--bz-serif);font-size:34px;font-weight:600;letter-spacing:-.02em;line-height:1}.bz-figure-s{font-size:20px;font-weight:600}.bz-levers{display:flex;flex-direction:column;gap:8px}.bz-lever{display:flex;gap:10px;align-items:flex-start;padding:12px;background:var(--bz-surface-2);border:1px solid var(--bz-line-2);border-radius:var(--bz-radius-control);cursor:pointer;font-size:13px}.bz-lever.bz-on{border-color:var(--bz-accent)}.bz-lever input{margin-top:2px;width:16px;height:16px;accent-color:#daaf37;flex:none}.bz-lever span{display:flex;flex-direction:column;gap:2px}.bz-lever em{color:var(--bz-muted);font-style:normal}.bz-chart{width:100%;height:auto;display:block;overflow:visible;font-family:var(--bz-sans)}.bz-chart-danger{fill:var(--bz-danger-band)}.bz-chart-grid{stroke:var(--bz-line-2);stroke-width:1}.bz-chart-zero{stroke:var(--bz-muted);stroke-width:1.25}.bz-chart-tick{font-size:11px;fill:var(--bz-faint)}.bz-chart-tick.bz-strong{fill:var(--bz-text);font-weight:600}.bz-chart-income{stroke:var(--bz-positive);stroke-width:1;stroke-dasharray:3 4}.bz-chart-today{stroke:var(--bz-accent);stroke-width:1.5}.bz-chart-base{fill:none;stroke:var(--bz-text);stroke-width:2.25;stroke-linejoin:round;stroke-linecap:round}.bz-chart-scenario{fill:none;stroke:var(--bz-accent-2);stroke-width:2;stroke-dasharray:5 4;stroke-linejoin:round}.bz-chart-dot{fill:var(--bz-surface);stroke:var(--bz-text);stroke-width:2}.bz-chart-low{fill:var(--bz-accent-2);stroke:var(--bz-surface);stroke-width:2}.bz-chart-label{font-size:11px;fill:var(--bz-muted)}.bz-chart-label.bz-income{fill:var(--bz-positive);font-weight:600}.bz-chart-label.bz-today{fill:var(--bz-accent);font-weight:600}.bz-chart-label.bz-low{fill:var(--bz-accent);font-weight:600;font-size:12px}.bz-legend{display:flex;gap:8px 20px;flex-wrap:wrap;font-size:12px;color:var(--bz-muted)}.bz-legend span{display:inline-flex;align-items:center;gap:6px}.bz-sw{display:inline-block;width:18px;height:3px;border-radius:2px;flex:none}.bz-sw-base{background:var(--bz-text)}.bz-sw-scenario{height:0;border-top:2px dashed var(--bz-accent-2)}.bz-sw-danger{width:14px;height:10px;background:var(--bz-danger-band);border:1px solid var(--bz-negative)}.bz-cycles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}.bz-cycle{display:flex;flex-direction:column;min-width:0}.bz-cycle-head{display:flex;justify-content:space-between;gap:8px;padding-bottom:10px;border-bottom:2px solid var(--bz-accent);font-size:13px;font-weight:600}@media(max-width:1100px){.bz-tiles{grid-template-columns:repeat(2,minmax(0,1fr))}.bz-grid,.bz-split,.bz-cycles{grid-template-columns:minmax(0,1fr)}.bz-slot-wide,.bz-slot-narrow,.bz-span-2{grid-column:auto}}@media(max-width:640px){.bz-tiles{grid-template-columns:minmax(0,1fr)}.bz-card,.bz-tile{padding:16px}.bz-action>.bz-row-body{flex-basis:calc(100% - 22px)}.bz-action>.bz-button{margin-left:22px}}@media(prefers-reduced-motion:no-preference){.bz-button,.bz-seg button,.bz-lever{transition:background-color .15s ease,border-color .15s ease}}.bz-chart-box{width:100%;min-width:0}.bz-group{display:flex;flex-direction:column}.bz-group+.bz-group{margin-top:10px}.bz-group-title{margin:6px 0 2px;font:600 11px var(--bz-sans);letter-spacing:.1em;text-transform:uppercase;color:var(--bz-muted);display:flex;gap:8px;align-items:center}.bz-group-title span{color:var(--bz-accent)}.bz-answer-picture{display:block;width:100%}.bz-answer-visual{display:block;width:100%;height:auto;max-height:190px;overflow:visible}.bz-answer-visual text{font-family:var(--bz-sans);font-variant-numeric:tabular-nums}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@bazous/ui",
3
+ "version": "0.3.2",
4
+ "description": "Bazous open UI kit — one module per money question, rendered from a public snapshot contract.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/bazousdotcom/ui.git"
10
+ },
11
+ "homepage": "https://bazousdotcom.github.io/ui/",
12
+ "keywords": [
13
+ "bazous",
14
+ "cash-flow",
15
+ "i18n",
16
+ "mcp",
17
+ "personal-finance",
18
+ "react",
19
+ "svg",
20
+ "switzerland",
21
+ "ui-kit"
22
+ ],
23
+ "files": [
24
+ "dist",
25
+ "schema"
26
+ ],
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ },
34
+ "./styles.css": "./dist/styles.css",
35
+ "./canvas": {
36
+ "types": "./dist/canvas/index.d.ts",
37
+ "import": "./dist/canvas.js"
38
+ },
39
+ "./answers": {
40
+ "types": "./dist/answers/index.d.ts",
41
+ "import": "./dist/answers.js"
42
+ },
43
+ "./schema.json": "./schema/snapshot.schema.json",
44
+ "./answers.schema.json": "./schema/answers.schema.json"
45
+ },
46
+ "scripts": {
47
+ "dev": "vite --config gallery/vite.config.ts",
48
+ "build": "npm run build:lib && npm run build:gallery",
49
+ "build:lib": "vite build && tsc -p tsconfig.build.json",
50
+ "build:gallery": "vite build --config gallery/vite.config.ts",
51
+ "typecheck": "tsc --noEmit",
52
+ "test": "vitest run",
53
+ "check": "npm run typecheck && npm run test && npm run build",
54
+ "prepare": "npm run build:lib"
55
+ },
56
+ "peerDependencies": {
57
+ "react": ">=18",
58
+ "react-dom": ">=18"
59
+ },
60
+ "devDependencies": {
61
+ "@testing-library/react": "^16.3.0",
62
+ "@types/node": "^22.15.0",
63
+ "@types/react": "^19.1.12",
64
+ "@types/react-dom": "^19.1.9",
65
+ "@vitejs/plugin-react": "^5.0.2",
66
+ "ajv": "^8.17.1",
67
+ "ajv-formats": "^3.0.1",
68
+ "jsdom": "^26.1.0",
69
+ "react": "^19.1.1",
70
+ "react-dom": "^19.1.1",
71
+ "typescript": "^5.9.2",
72
+ "vite": "^7.1.5",
73
+ "vitest": "^3.2.4"
74
+ },
75
+ "engines": {
76
+ "node": ">=20"
77
+ },
78
+ "bugs": {
79
+ "url": "https://github.com/bazousdotcom/ui/issues"
80
+ },
81
+ "publishConfig": {
82
+ "access": "public"
83
+ }
84
+ }