@foodpilot/foods 2.25.2 → 2.25.4

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/README.md CHANGED
@@ -1 +1,90 @@
1
1
  <img width="2560" height="1024" alt="foods_logo_banner_clean-min" src="https://github.com/user-attachments/assets/4cfbd824-f8fe-473e-aa7a-7c789b8d2b9d" />
2
+
3
+ # foods
4
+
5
+ `@foodpilot/foods` is FoodPilot's design system for React: the MUI-based components, tenant themes and charts of
6
+ platform-app.
7
+
8
+ - **Storybook:** [foods-storybook.foodpilot.tech](https://foods-storybook.foodpilot.tech), organised like IBM
9
+ Carbon's.
10
+ - **Figma Design System:** [Design System](https://www.figma.com/design/ucJSnn3mHlv4MCnwe1oZ2Z/Design-System), the
11
+ design source of truth.
12
+ - **For AI assistants:** [`llms.txt`](llms.txt) ([llmstxt.org](https://llmstxt.org)), also served at
13
+ [foods-storybook.foodpilot.tech/llms.txt](https://foods-storybook.foodpilot.tech/llms.txt).
14
+
15
+ ## Use foods
16
+
17
+ ```bash
18
+ npm install @foodpilot/foods
19
+ ```
20
+
21
+ Peer dependencies:
22
+
23
+ - always: `react` and `react-dom` 18 or 19, `@mui/material` ^6.4, `@emotion/react` and `@emotion/styled` ^11.14,
24
+ `i18next`, `react-i18next` and `lodash`;
25
+ - only for the components that use them: `@mui/icons-material`, `@mui/lab`, the `@mui/x-*` packages, `recharts` and
26
+ `material-react-table`.
27
+
28
+ ```tsx
29
+ import { FoodsThemeProvider } from "@foodpilot/foods/themes";
30
+ import { Button } from "@foodpilot/foods/Button";
31
+
32
+ <FoodsThemeProvider theme="foodpilot">
33
+ {/* "foodpilot" | "winepilot" | "collective" */}
34
+ <App />
35
+ </FoodsThemeProvider>;
36
+ ```
37
+
38
+ Every export is named, from the root entry or a component entry: see [IMPORT_EXAMPLES.md](IMPORT_EXAMPLES.md). Style
39
+ with the theme tokens (palette, 8 px spacing, typography variants, shadows), never raw values. Components translate
40
+ their texts with `react-i18next`, the English strings being the keys; the application provides the translations.
41
+
42
+ ## Storybook
43
+
44
+ `npm run storybook` serves it on port 6006, `npm run build-storybook` builds it into `storybook-static/`. The
45
+ `demo.yml` workflow deploys it after every release.
46
+
47
+ | Section | What it holds | Folder |
48
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------- |
49
+ | Getting Started | Welcome, and the guides for designers, product and developers | `src/getting-started/` |
50
+ | Components | The components to use, by Figma Design System page: Actions, Avatar and user, Content, Data display, Feedbacks, Inputs, Modals, Navigation | `src/components/<Category>/` |
51
+ | Elements | The foundations: colours, typography, spacing, shadows, breakpoints, icons | `src/elements/` |
52
+ | Layout | Page layouts | `src/layout/` |
53
+ | Preview | Components still being built or redesigned | `src/preview/` |
54
+ | Component not used | Components platform-app no longer uses, or removed from the Figma Design System | `src/legacy/<Category>/` |
55
+ | Deprecated | Deliberate deprecations | `src/deprecated/<Category>/` |
56
+
57
+ Each component has an **Overview** page (`src/docs/DocsPage.tsx`) with:
58
+
59
+ - its description;
60
+ - the usage guidelines from Figma: do's and don'ts, anatomy, behaviour, content and states;
61
+ - every story;
62
+ - the props (Component API);
63
+ - its references.
64
+
65
+ In Storybook:
66
+
67
+ - each story has controls, logs its callbacks in **Actions** and plays its main interaction in **Interactions**;
68
+ - the toolbar switches the tenant theme (FoodPilot, WinePilot, Positive), the background and the viewport;
69
+ - the texts are in English.
70
+
71
+ ## Contribute
72
+
73
+ [AGENTS.md](AGENTS.md) holds the rules for any change. In short:
74
+
75
+ - **Stories:** a component's stories go in `src/components/<Category>/<Component>.stories.tsx`, without a `title`,
76
+ since the folder decides the sidebar. Their texts are in English, with fitting controls, `fn()` callbacks and a
77
+ `play` function. Usage guidelines come from Figma, in `parameters.guidelines`.
78
+ - **llms.txt:** when a component or its stories are added, moved or removed, run `npm run llms` and commit
79
+ `llms.txt`. CI fails when it is stale.
80
+ - **Unused components:** they move to `src/legacy/` with `git mv`. The platform-design skill of the frontend harness
81
+ lists them by comparing the stories with platform-app's imports, then refreshes `llms.txt`.
82
+ - **Checks:**
83
+ - `npm run prettier`, `npm run lint`, `npm run tsc`;
84
+ - `npm test`, which includes the stories' plays and the `llms.txt` check;
85
+ - `npm run build`, `npm run depcruise:check`.
86
+
87
+ CI is described in [docs/ci.md](docs/ci.md), size budgets in [BUNDLE_ANALYSIS.md](BUNDLE_ANALYSIS.md).
88
+
89
+ - **Releases:** `npm run publish:patch|minor|major` dispatches the release workflow from `main`. platform-app gets a
90
+ change after that release and its own dependency update.
@@ -1,7 +1,7 @@
1
- import{jsx as t,jsxs as e}from"react/jsx-runtime";import{useRef as r,useState as i,useEffect as a,useMemo as o}from"react";import{ResponsiveContainer as n,ComposedChart as s,CartesianGrid as m,XAxis as l,YAxis as d,Label as c,ReferenceLine as h}from"recharts";import{useTheme as f,useMediaQuery as p,Box as g}from"@mui/material";import{transformWaterfallData as u,calculateLabelSettings as k,wrapWaterfallLabel as v}from"./utils.js";import{WaterfallChartTick as x}from"./WaterfallChartTick.js";import{WaterfallChartBars as y}from"./WaterfallChartBars.js";import{TICK_VERTICAL_OFFSET as F,LINE_HEIGHT_PIXELS as w}from"./labelGeometry.js";const b=b=>{const W=f(),L=p(W.breakpoints.down("sm")),{reference:j,start:z,values:C,colors:M,target:D,goal:X,forcedPrecision:$,unit:A,improvement:B,targetValueFinal:E,valueFormatterFn:H=W.numbers.valueFormatterFn,precision:P,CoreOverride:S}=b,T=r(null),[G,K]=i(800);a(()=>{const t=()=>{if(T.current){const t=T.current.getBoundingClientRect().width;t>0&&K(t-60)}};t();const e=()=>t();return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[]);const N=o(()=>u(j,z,C,M,D,X,B,E,W),[j,z,C,M,D,X,B,E,W]),O=o(()=>k(N,G),[N,G]),R=Math.max(S?.XAxisHeight??40,...N.map(t=>F+v(t.label,80).length*w));/* @__PURE__ */
2
- return t(g,{ref:T,sx:{width:"100%",height:"100%",minWidth:{xs:96*N.length+100,sm:0}},children:/* @__PURE__ */t(n,{width:"100%",height:"100%",children:/* @__PURE__ */e(s,{data:N,margin:{top:45,right:0,left:30,bottom:35},children:[
1
+ import{jsx as t,jsxs as e}from"react/jsx-runtime";import{useRef as r,useState as i,useEffect as a,useMemo as o}from"react";import{ResponsiveContainer as n,ComposedChart as s,CartesianGrid as m,XAxis as l,YAxis as d,Label as c,ReferenceLine as h}from"recharts";import{useTheme as f,useMediaQuery as p,Box as u}from"@mui/material";import{transformWaterfallData as g,calculateLabelSettings as k,wrapWaterfallLabel as v}from"./utils.js";import{WaterfallChartTick as x}from"./WaterfallChartTick.js";import{WaterfallChartBars as y}from"./WaterfallChartBars.js";import{TICK_VERTICAL_OFFSET as F,LINE_HEIGHT_PIXELS as w}from"./labelGeometry.js";const b=b=>{const W=f(),L=p(W.breakpoints.down("sm")),{reference:j,start:z,values:C,colors:M,target:D,goal:$,forcedPrecision:B,unit:E,improvement:P,targetValueFinal:S,valueFormatterFn:T=W.numbers.valueFormatterFn,precision:X,CoreOverride:A}=b,G=r(null),[H,K]=i(800);a(()=>{const t=()=>{if(G.current){const t=G.current.getBoundingClientRect().width;t>0&&K(t-60)}};t();const e=()=>t();return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[]);const N=o(()=>g(j,z,C,M,D,$,P,S,W),[j,z,C,M,D,$,P,S,W]),O=o(()=>k(N,H),[N,H]),R=L?80:O.maxWidth,V=Math.max(A?.XAxisHeight??40,...N.map(t=>F+v(t.label,R).length*w));/* @__PURE__ */
2
+ return t(u,{ref:G,sx:{width:"100%",height:"100%",minWidth:{xs:96*N.length+100,sm:0}},children:/* @__PURE__ */t(n,{width:"100%",height:"100%",children:/* @__PURE__ */e(s,{data:N,margin:{top:45,right:0,left:30,bottom:35},children:[
3
3
  /* @__PURE__ */t(m,{strokeDasharray:"4 4",stroke:W.palette.divider}),
4
- /* @__PURE__ */t(l,{dataKey:"label",strokeWidth:0,strokeDasharray:"4 4",tick:e=>/* @__PURE__ */t(x,{...e,maxWidth:L?80:O.maxWidth}),axisLine:{stroke:W.palette.divider},interval:L?0:O.interval,tickLine:!1,padding:{left:0,right:0},height:L?R:S?.XAxisHeight??40}),
5
- /* @__PURE__ */t(d,{width:"auto",domain:([t,e])=>[t<0?t-.2*Math.abs(t):t,e],strokeWidth:0,tick:{fontFamily:"Montserrat",fontSize:14,style:{transform:`translateX(-${W.spacing(2)})`}},axisLine:{stroke:W.palette.divider},tickLine:!1,tickFormatter:t=>H(Number(t),P),children:/* @__PURE__ */t(c,{value:A,position:"insideTopLeft",style:{fontFamily:"Montserrat",fontSize:"14px",transform:`translate(-${W.spacing(2.75)}, -${W.spacing(6)})`}})}),
4
+ /* @__PURE__ */t(l,{dataKey:"label",strokeWidth:0,strokeDasharray:"4 4",tick:e=>/* @__PURE__ */t(x,{...e,maxWidth:R}),axisLine:{stroke:W.palette.divider},interval:L?0:O.interval,tickLine:!1,padding:{left:0,right:0},height:V}),
5
+ /* @__PURE__ */t(d,{width:"auto",domain:([t,e])=>[t<0?t-.2*Math.abs(t):t,e],strokeWidth:0,tick:{fontFamily:"Montserrat",fontSize:14,style:{transform:`translateX(-${W.spacing(2)})`}},axisLine:{stroke:W.palette.divider},tickLine:!1,tickFormatter:t=>T(Number(t),X),children:/* @__PURE__ */t(c,{value:E,position:"insideTopLeft",style:{fontFamily:"Montserrat",fontSize:"14px",transform:`translate(-${W.spacing(2.75)}, -${W.spacing(6)})`}})}),
6
6
  /* @__PURE__ */t(h,{y:0,stroke:W.custom.grey[600],strokeWidth:2}),
7
- /* @__PURE__ */t(y,{transformedData:N,valueFormatterFn:H,forcedPrecision:$,precision:P})]})})})};export{b as WaterfallChartCore};
7
+ /* @__PURE__ */t(y,{transformedData:N,valueFormatterFn:T,forcedPrecision:B,precision:X})]})})})};export{b as WaterfallChartCore};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@foodpilot/foods",
3
3
  "private": false,
4
- "version": "2.25.2",
4
+ "version": "2.25.4",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",
7
7
  "module": "./dist/main.js",
@@ -198,6 +198,7 @@
198
198
  "local-storybook": "storybook dev -p 6007",
199
199
  "test": "vitest run",
200
200
  "build-storybook": "storybook build",
201
+ "llms": "node scripts/llms-txt.mjs",
201
202
  "lint:fix": "npm run lint --fix",
202
203
  "prepare": "husky install",
203
204
  "tsc-debug": "tsgo --incremental --generateTrace debugTypescript.out",
@@ -262,6 +263,7 @@
262
263
  "@mui/x-date-pickers": "^8.27.2",
263
264
  "@size-limit/file": "^12.0.0",
264
265
  "@size-limit/preset-big-lib": "^11.2.0",
266
+ "@storybook/addon-docs": "^10.2.13",
265
267
  "@storybook/react-vite": "^10.2.13",
266
268
  "@testing-library/dom": "^10.4.1",
267
269
  "@testing-library/jest-dom": "^6.9.1",
@@ -295,6 +297,7 @@
295
297
  "react": "19.2.0",
296
298
  "react-dom": "19.2.0",
297
299
  "recharts": "^3.7.0",
300
+ "remark-gfm": "^4.0.1",
298
301
  "rollup-plugin-visualizer": "^7.0.0",
299
302
  "size-limit": "^12.0.0",
300
303
  "storybook": "^10.2.13",
@@ -328,7 +331,7 @@
328
331
  "chroma-js": "^3.2.0",
329
332
  "i18next": "^23.0.0 || ^25.0.0",
330
333
  "i18next-browser-languagedetector": "^8.2.1",
331
- "i18next-http-backend": "^3.0.5",
334
+ "i18next-http-backend": "^4.0.2",
332
335
  "lexical": "^0.41.0",
333
336
  "lodash": "^4.18.1",
334
337
  "material-ui-popup-state": "^5.3.1",