@stokelp/ui 2.109.0 → 2.110.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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../text/Text.cjs");let t=require("@stokelp/styled-system/jsx"),n=require("react/jsx-runtime");var r=[`origin`,`rawMaterialOrigin`,`temperature`,`cutting`,`cooking`,`treatment`,`label`,`packaging`,`grammageGsm`,`recycledPct`,`thicknessMicron`],i={egal:{bg:`#E6F3D9`,color:`#3B6D11`},proche:{bg:`#F0F6DC`,color:`#5E8516`},eloigne:{bg:`#FDF0E0`,color:`#C2740C`},non_correspondant:{bg:`#FCEBEB`,color:`#A32D2D`}};function
|
|
1
|
+
"use client";const e=require("../text/Text.cjs");let t=require("@stokelp/styled-system/jsx"),n=require("react/jsx-runtime");var r=[`origin`,`rawMaterialOrigin`,`temperature`,`cutting`,`cooking`,`treatment`,`label`,`packaging`,`grammageGsm`,`recycledPct`,`thicknessMicron`],i=[`temperature`,`cutting`,`cooking`],a=[`grammageGsm`,`recycledPct`,`thicknessMicron`],o={egal:{bg:`#E6F3D9`,color:`#3B6D11`},proche:{bg:`#F0F6DC`,color:`#5E8516`},eloigne:{bg:`#FDF0E0`,color:`#C2740C`},non_correspondant:{bg:`#FCEBEB`,color:`#A32D2D`}};function s(e){return e>=70?`#3B6D11`:e>=40?`#854F0B`:`#A32D2D`}function c(e){return e>=70?`#639922`:e>=40?`#BA7517`:`#E24B4A`}function l(e){return e?.level!=null}function u(e){return e?.matched!=null&&e?.total!=null}function d(e){return l(e)||u(e)}var f=({percent:u,detail:f,labels:p})=>{let m=a.some(e=>f[e]?.level!=null),h=new Set(m?i:a),g=r.filter(e=>!h.has(e)),_=g.filter(e=>d(f[e])),v=g.filter(e=>!d(f[e])&&p.attributes[e]!=null);return(0,n.jsxs)(t.Box,{bg:`white`,borderRadius:`radius-8`,p:`space-16`,minW:`220px`,maxW:`240px`,css:{"& *":{fontFamily:`inherit`}},children:[(0,n.jsxs)(t.HStack,{justify:`space-between`,alignItems:`baseline`,mb:`space-8`,children:[(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.md`,fontWeight:`bold`,children:p.title}),(0,n.jsxs)(e.Text,{as:`span`,fontSize:`body.lg`,fontWeight:`medium`,style:{color:s(u)},children:[Math.round(u),` %`]})]}),(0,n.jsx)(t.Box,{h:`1px`,bg:`grey.100`,mb:`space-8`}),_.length>0&&(0,n.jsxs)(t.VStack,{alignItems:`stretch`,gap:`space-4`,mb:`space-8`,children:[(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,fontWeight:`bold`,color:`grey.400`,children:p.compared}),_.map(r=>{let i=f[r];if(l(i)){let a=i.level,s=o[a];return(0,n.jsxs)(t.HStack,{alignItems:`center`,gap:`space-8`,justify:`space-between`,children:[(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,color:`grey.500`,minW:`80px`,children:p.attributes[r]}),(0,n.jsx)(t.Box,{px:`space-8`,py:`2px`,borderRadius:`full`,flexShrink:`0`,style:{backgroundColor:s.bg},children:(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,fontWeight:`medium`,style:{color:s.color,whiteSpace:`nowrap`},children:p.levels?.[a]??a})})]},r)}let a=i.matched,s=i.total,u=s>0?a/s*100:0;return(0,n.jsxs)(t.HStack,{alignItems:`center`,gap:`space-8`,children:[(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,color:`grey.500`,minW:`80px`,children:p.attributes[r]}),(0,n.jsx)(t.Box,{flex:`1`,h:`3px`,bg:`grey.100`,borderRadius:`full`,overflow:`hidden`,children:(0,n.jsx)(t.Box,{h:`100%`,borderRadius:`full`,style:{width:`${u}%`,background:c(u)}})}),(0,n.jsxs)(e.Text,{as:`span`,fontSize:`body.sm`,fontWeight:`medium`,minW:`40px`,textAlign:`right`,style:{color:c(u)},children:[a,`/`,s]})]},r)})]}),_.length>0&&v.length>0&&(0,n.jsx)(t.Box,{h:`1px`,bg:`grey.100`,mb:`space-8`}),v.length>0&&(0,n.jsxs)(t.VStack,{alignItems:`stretch`,gap:`space-4`,children:[(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,fontWeight:`bold`,color:`grey.400`,children:p.notSpecified}),(0,n.jsx)(t.HStack,{flexWrap:`wrap`,gap:`space-4`,children:v.map(t=>(0,n.jsx)(e.Text,{as:`span`,fontSize:`body.sm`,color:`grey.400`,border:`1px solid`,borderColor:`grey.100`,px:`space-8`,py:`2px`,borderRadius:`full`,children:p.attributes[t]},t))})]}),p.footer&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.Box,{h:`1px`,bg:`grey.100`,mt:`space-8`,mb:`space-8`}),(0,n.jsx)(e.Text,{as:`span`,fontSize:`9px`,color:`grey.300`,style:{lineHeight:1},children:p.footer})]})]})};exports.ChatScoreBreakdown=f;
|
|
2
2
|
//# sourceMappingURL=ChatScoreBreakdown.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatScoreBreakdown.cjs","names":[],"sources":["../../../src/components/chat/ChatScoreBreakdown.tsx"],"sourcesContent":["import { Box, HStack, VStack } from '@stokelp/styled-system/jsx'\nimport { Text } from '~/components'\n\nexport type ScoreSetAttributeKey =\n | 'origin'\n | 'rawMaterialOrigin'\n | 'temperature'\n | 'cutting'\n | 'cooking'\n | 'treatment'\n | 'label'\n | 'packaging'\n\nexport type ScoreNumericAttributeKey = 'grammageGsm' | 'recycledPct' | 'thicknessMicron'\n\nexport type ScoreAttributeKey = ScoreSetAttributeKey | ScoreNumericAttributeKey\n\n/** Proximity bucket for free numeric packaging specs: egal (equal) → non_correspondant (no match). */\nexport type ScoreLevel = 'egal' | 'proche' | 'eloigne' | 'non_correspondant'\n\nexport type ScoreAttributeDetail = {\n matched: number | null\n total: number | null\n level?: ScoreLevel | null\n}\n\nexport type ChatScoreBreakdownLabels = {\n title: string\n compared: string\n notSpecified: string\n attributes: Record<ScoreSetAttributeKey, string> & Partial<Record<ScoreNumericAttributeKey, string>>\n levels?: Record<ScoreLevel, string>\n footer?: string\n}\n\nexport type ChatScoreBreakdownProps = {\n percent: number\n detail: Record<string, ScoreAttributeDetail>\n labels: ChatScoreBreakdownLabels\n}\n\nconst ATTRIBUTE_ORDER: ScoreAttributeKey[] = [\n 'origin',\n 'rawMaterialOrigin',\n 'temperature',\n 'cutting',\n 'cooking',\n 'treatment',\n 'label',\n 'packaging',\n 'grammageGsm',\n 'recycledPct',\n 'thicknessMicron',\n]\n\nconst LEVEL_COLORS: Record<ScoreLevel, { bg: string; color: string }> = {\n egal: { bg: '#E6F3D9', color: '#3B6D11' },\n proche: { bg: '#F0F6DC', color: '#5E8516' },\n eloigne: { bg: '#FDF0E0', color: '#C2740C' },\n non_correspondant: { bg: '#FCEBEB', color: '#A32D2D' },\n}\n\nfunction getHeadlineColor(percent: number): string {\n if (percent >= 70) return '#3B6D11'\n if (percent >= 40) return '#854F0B'\n return '#A32D2D'\n}\n\nfunction getBarColor(ratioPercent: number): string {\n if (ratioPercent >= 70) return '#639922'\n if (ratioPercent >= 40) return '#BA7517'\n return '#E24B4A'\n}\n\nfunction hasLevel(detail?: ScoreAttributeDetail): boolean {\n return detail?.level != null\n}\n\nfunction isFraction(detail?: ScoreAttributeDetail): boolean {\n return detail?.matched != null && detail?.total != null\n}\n\nfunction isComparable(detail?: ScoreAttributeDetail): boolean {\n return hasLevel(detail) || isFraction(detail)\n}\n\nexport const ChatScoreBreakdown = ({ percent, detail, labels }: ChatScoreBreakdownProps) => {\n const compared = ATTRIBUTE_ORDER.filter(key => isComparable(detail[key]))\n const notSpecified = ATTRIBUTE_ORDER.filter(key => !isComparable(detail[key]) && labels.attributes[key] != null)\n\n return (\n <Box\n bg=\"white\"\n borderRadius=\"radius-8\"\n p=\"space-16\"\n minW=\"220px\"\n maxW=\"240px\"\n css={{ '& *': { fontFamily: 'inherit' } }}\n >\n <HStack justify=\"space-between\" alignItems=\"baseline\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.md\" fontWeight=\"bold\">\n {labels.title}\n </Text>\n <Text as=\"span\" fontSize=\"body.lg\" fontWeight=\"medium\" style={{ color: getHeadlineColor(percent) }}>\n {Math.round(percent)} %\n </Text>\n </HStack>\n\n <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />\n\n {compared.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.compared}\n </Text>\n {compared.map(key => {\n const entry = detail[key]\n if (hasLevel(entry)) {\n const level = entry.level as ScoreLevel\n const colors = LEVEL_COLORS[level]\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\" justify=\"space-between\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box px=\"space-8\" py=\"2px\" borderRadius=\"full\" style={{ backgroundColor: colors.bg }}>\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"medium\" style={{ color: colors.color }}>\n {labels.levels?.[level] ?? level}\n </Text>\n </Box>\n </HStack>\n )\n }\n\n const matched = entry.matched as number\n const total = entry.total as number\n const ratioPercent = total > 0 ? (matched / total) * 100 : 0\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box flex=\"1\" h=\"3px\" bg=\"grey.100\" borderRadius=\"full\" overflow=\"hidden\">\n <Box\n h=\"100%\"\n borderRadius=\"full\"\n style={{ width: `${ratioPercent}%`, background: getBarColor(ratioPercent) }}\n />\n </Box>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n minW=\"40px\"\n textAlign=\"right\"\n style={{ color: getBarColor(ratioPercent) }}\n >\n {matched}/{total}\n </Text>\n </HStack>\n )\n })}\n </VStack>\n )}\n\n {compared.length > 0 && notSpecified.length > 0 && <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />}\n\n {notSpecified.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.notSpecified}\n </Text>\n <HStack flexWrap=\"wrap\" gap=\"space-4\">\n {notSpecified.map(key => (\n <Text\n key={key}\n as=\"span\"\n fontSize=\"body.sm\"\n color=\"grey.400\"\n border=\"1px solid\"\n borderColor=\"grey.100\"\n px=\"space-8\"\n py=\"2px\"\n borderRadius=\"full\"\n >\n {labels.attributes[key]}\n </Text>\n ))}\n </HStack>\n </VStack>\n )}\n\n {labels.footer && (\n <>\n <Box h=\"1px\" bg=\"grey.100\" mt=\"space-8\" mb=\"space-8\" />\n <Text as=\"span\" fontSize=\"9px\" color=\"grey.300\" style={{ lineHeight: 1 }}>\n {labels.footer}\n </Text>\n </>\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatScoreBreakdown.cjs","names":[],"sources":["../../../src/components/chat/ChatScoreBreakdown.tsx"],"sourcesContent":["import { Box, HStack, VStack } from '@stokelp/styled-system/jsx'\nimport { Text } from '~/components'\n\nexport type ScoreSetAttributeKey =\n | 'origin'\n | 'rawMaterialOrigin'\n | 'temperature'\n | 'cutting'\n | 'cooking'\n | 'treatment'\n | 'label'\n | 'packaging'\n\nexport type ScoreNumericAttributeKey = 'grammageGsm' | 'recycledPct' | 'thicknessMicron'\n\nexport type ScoreAttributeKey = ScoreSetAttributeKey | ScoreNumericAttributeKey\n\n/** Proximity bucket for free numeric packaging specs: egal (equal) → non_correspondant (no match). */\nexport type ScoreLevel = 'egal' | 'proche' | 'eloigne' | 'non_correspondant'\n\nexport type ScoreAttributeDetail = {\n matched: number | null\n total: number | null\n level?: ScoreLevel | null\n}\n\nexport type ChatScoreBreakdownLabels = {\n title: string\n compared: string\n notSpecified: string\n attributes: Record<ScoreSetAttributeKey, string> & Partial<Record<ScoreNumericAttributeKey, string>>\n levels?: Record<ScoreLevel, string>\n footer?: string\n}\n\nexport type ChatScoreBreakdownProps = {\n percent: number\n detail: Record<string, ScoreAttributeDetail>\n labels: ChatScoreBreakdownLabels\n}\n\nconst ATTRIBUTE_ORDER: ScoreAttributeKey[] = [\n 'origin',\n 'rawMaterialOrigin',\n 'temperature',\n 'cutting',\n 'cooking',\n 'treatment',\n 'label',\n 'packaging',\n 'grammageGsm',\n 'recycledPct',\n 'thicknessMicron',\n]\n\n// Attributes that only exist for food products; hidden for packaging products.\nconst FOOD_ONLY_KEYS: ScoreAttributeKey[] = ['temperature', 'cutting', 'cooking']\n// Free numeric specs that only exist for packaging products; hidden for food products.\nconst PACKAGING_ONLY_KEYS: ScoreNumericAttributeKey[] = ['grammageGsm', 'recycledPct', 'thicknessMicron']\n\nconst LEVEL_COLORS: Record<ScoreLevel, { bg: string; color: string }> = {\n egal: { bg: '#E6F3D9', color: '#3B6D11' },\n proche: { bg: '#F0F6DC', color: '#5E8516' },\n eloigne: { bg: '#FDF0E0', color: '#C2740C' },\n non_correspondant: { bg: '#FCEBEB', color: '#A32D2D' },\n}\n\nfunction getHeadlineColor(percent: number): string {\n if (percent >= 70) return '#3B6D11'\n if (percent >= 40) return '#854F0B'\n return '#A32D2D'\n}\n\nfunction getBarColor(ratioPercent: number): string {\n if (ratioPercent >= 70) return '#639922'\n if (ratioPercent >= 40) return '#BA7517'\n return '#E24B4A'\n}\n\nfunction hasLevel(detail?: ScoreAttributeDetail): boolean {\n return detail?.level != null\n}\n\nfunction isFraction(detail?: ScoreAttributeDetail): boolean {\n return detail?.matched != null && detail?.total != null\n}\n\nfunction isComparable(detail?: ScoreAttributeDetail): boolean {\n return hasLevel(detail) || isFraction(detail)\n}\n\nexport const ChatScoreBreakdown = ({ percent, detail, labels }: ChatScoreBreakdownProps) => {\n // A packaging product exposes the numeric specs (comparable via level); food attributes\n // then come back fully null and must be hidden entirely, and vice versa.\n const isPackaging = PACKAGING_ONLY_KEYS.some(key => detail[key]?.level != null)\n const hiddenKeys = new Set<ScoreAttributeKey>(isPackaging ? FOOD_ONLY_KEYS : PACKAGING_ONLY_KEYS)\n const visibleKeys = ATTRIBUTE_ORDER.filter(key => !hiddenKeys.has(key))\n\n const compared = visibleKeys.filter(key => isComparable(detail[key]))\n const notSpecified = visibleKeys.filter(key => !isComparable(detail[key]) && labels.attributes[key] != null)\n\n return (\n <Box\n bg=\"white\"\n borderRadius=\"radius-8\"\n p=\"space-16\"\n minW=\"220px\"\n maxW=\"240px\"\n css={{ '& *': { fontFamily: 'inherit' } }}\n >\n <HStack justify=\"space-between\" alignItems=\"baseline\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.md\" fontWeight=\"bold\">\n {labels.title}\n </Text>\n <Text as=\"span\" fontSize=\"body.lg\" fontWeight=\"medium\" style={{ color: getHeadlineColor(percent) }}>\n {Math.round(percent)} %\n </Text>\n </HStack>\n\n <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />\n\n {compared.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.compared}\n </Text>\n {compared.map(key => {\n const entry = detail[key]\n if (hasLevel(entry)) {\n const level = entry.level as ScoreLevel\n const colors = LEVEL_COLORS[level]\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\" justify=\"space-between\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box px=\"space-8\" py=\"2px\" borderRadius=\"full\" flexShrink=\"0\" style={{ backgroundColor: colors.bg }}>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n style={{ color: colors.color, whiteSpace: 'nowrap' }}\n >\n {labels.levels?.[level] ?? level}\n </Text>\n </Box>\n </HStack>\n )\n }\n\n const matched = entry.matched as number\n const total = entry.total as number\n const ratioPercent = total > 0 ? (matched / total) * 100 : 0\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box flex=\"1\" h=\"3px\" bg=\"grey.100\" borderRadius=\"full\" overflow=\"hidden\">\n <Box\n h=\"100%\"\n borderRadius=\"full\"\n style={{ width: `${ratioPercent}%`, background: getBarColor(ratioPercent) }}\n />\n </Box>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n minW=\"40px\"\n textAlign=\"right\"\n style={{ color: getBarColor(ratioPercent) }}\n >\n {matched}/{total}\n </Text>\n </HStack>\n )\n })}\n </VStack>\n )}\n\n {compared.length > 0 && notSpecified.length > 0 && <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />}\n\n {notSpecified.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.notSpecified}\n </Text>\n <HStack flexWrap=\"wrap\" gap=\"space-4\">\n {notSpecified.map(key => (\n <Text\n key={key}\n as=\"span\"\n fontSize=\"body.sm\"\n color=\"grey.400\"\n border=\"1px solid\"\n borderColor=\"grey.100\"\n px=\"space-8\"\n py=\"2px\"\n borderRadius=\"full\"\n >\n {labels.attributes[key]}\n </Text>\n ))}\n </HStack>\n </VStack>\n )}\n\n {labels.footer && (\n <>\n <Box h=\"1px\" bg=\"grey.100\" mt=\"space-8\" mb=\"space-8\" />\n <Text as=\"span\" fontSize=\"9px\" color=\"grey.300\" style={{ lineHeight: 1 }}>\n {labels.footer}\n </Text>\n </>\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,15 @@ var s = [
|
|
|
15
15
|
"grammageGsm",
|
|
16
16
|
"recycledPct",
|
|
17
17
|
"thicknessMicron"
|
|
18
|
-
], c =
|
|
18
|
+
], c = [
|
|
19
|
+
"temperature",
|
|
20
|
+
"cutting",
|
|
21
|
+
"cooking"
|
|
22
|
+
], l = [
|
|
23
|
+
"grammageGsm",
|
|
24
|
+
"recycledPct",
|
|
25
|
+
"thicknessMicron"
|
|
26
|
+
], u = {
|
|
19
27
|
egal: {
|
|
20
28
|
bg: "#E6F3D9",
|
|
21
29
|
color: "#3B6D11"
|
|
@@ -33,23 +41,23 @@ var s = [
|
|
|
33
41
|
color: "#A32D2D"
|
|
34
42
|
}
|
|
35
43
|
};
|
|
36
|
-
function
|
|
44
|
+
function d(e) {
|
|
37
45
|
return e >= 70 ? "#3B6D11" : e >= 40 ? "#854F0B" : "#A32D2D";
|
|
38
46
|
}
|
|
39
|
-
function
|
|
47
|
+
function f(e) {
|
|
40
48
|
return e >= 70 ? "#639922" : e >= 40 ? "#BA7517" : "#E24B4A";
|
|
41
49
|
}
|
|
42
|
-
function
|
|
50
|
+
function p(e) {
|
|
43
51
|
return e?.level != null;
|
|
44
52
|
}
|
|
45
|
-
function
|
|
53
|
+
function m(e) {
|
|
46
54
|
return e?.matched != null && e?.total != null;
|
|
47
55
|
}
|
|
48
|
-
function
|
|
49
|
-
return
|
|
56
|
+
function h(e) {
|
|
57
|
+
return p(e) || m(e);
|
|
50
58
|
}
|
|
51
|
-
var
|
|
52
|
-
let g = s.filter((e) =>
|
|
59
|
+
var g = ({ percent: m, detail: g, labels: _ }) => {
|
|
60
|
+
let v = l.some((e) => g[e]?.level != null), y = new Set(v ? c : l), b = s.filter((e) => !y.has(e)), x = b.filter((e) => h(g[e])), S = b.filter((e) => !h(g[e]) && _.attributes[e] != null);
|
|
53
61
|
return /* @__PURE__ */ o(t, {
|
|
54
62
|
bg: "white",
|
|
55
63
|
borderRadius: "radius-8",
|
|
@@ -66,13 +74,13 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
66
74
|
as: "span",
|
|
67
75
|
fontSize: "body.md",
|
|
68
76
|
fontWeight: "bold",
|
|
69
|
-
children:
|
|
77
|
+
children: _.title
|
|
70
78
|
}), /* @__PURE__ */ o(e, {
|
|
71
79
|
as: "span",
|
|
72
80
|
fontSize: "body.lg",
|
|
73
81
|
fontWeight: "medium",
|
|
74
|
-
style: { color:
|
|
75
|
-
children: [Math.round(
|
|
82
|
+
style: { color: d(m) },
|
|
83
|
+
children: [Math.round(m), " %"]
|
|
76
84
|
})]
|
|
77
85
|
}),
|
|
78
86
|
/* @__PURE__ */ a(t, {
|
|
@@ -80,7 +88,7 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
80
88
|
bg: "grey.100",
|
|
81
89
|
mb: "space-8"
|
|
82
90
|
}),
|
|
83
|
-
|
|
91
|
+
x.length > 0 && /* @__PURE__ */ o(r, {
|
|
84
92
|
alignItems: "stretch",
|
|
85
93
|
gap: "space-4",
|
|
86
94
|
mb: "space-8",
|
|
@@ -89,11 +97,11 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
89
97
|
fontSize: "body.sm",
|
|
90
98
|
fontWeight: "bold",
|
|
91
99
|
color: "grey.400",
|
|
92
|
-
children:
|
|
93
|
-
}),
|
|
94
|
-
let i =
|
|
95
|
-
if (
|
|
96
|
-
let s = i.level,
|
|
100
|
+
children: _.compared
|
|
101
|
+
}), x.map((r) => {
|
|
102
|
+
let i = g[r];
|
|
103
|
+
if (p(i)) {
|
|
104
|
+
let s = i.level, c = u[s];
|
|
97
105
|
return /* @__PURE__ */ o(n, {
|
|
98
106
|
alignItems: "center",
|
|
99
107
|
gap: "space-8",
|
|
@@ -103,23 +111,27 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
103
111
|
fontSize: "body.sm",
|
|
104
112
|
color: "grey.500",
|
|
105
113
|
minW: "80px",
|
|
106
|
-
children:
|
|
114
|
+
children: _.attributes[r]
|
|
107
115
|
}), /* @__PURE__ */ a(t, {
|
|
108
116
|
px: "space-8",
|
|
109
117
|
py: "2px",
|
|
110
118
|
borderRadius: "full",
|
|
111
|
-
|
|
119
|
+
flexShrink: "0",
|
|
120
|
+
style: { backgroundColor: c.bg },
|
|
112
121
|
children: /* @__PURE__ */ a(e, {
|
|
113
122
|
as: "span",
|
|
114
123
|
fontSize: "body.sm",
|
|
115
124
|
fontWeight: "medium",
|
|
116
|
-
style: {
|
|
117
|
-
|
|
125
|
+
style: {
|
|
126
|
+
color: c.color,
|
|
127
|
+
whiteSpace: "nowrap"
|
|
128
|
+
},
|
|
129
|
+
children: _.levels?.[s] ?? s
|
|
118
130
|
})
|
|
119
131
|
})]
|
|
120
132
|
}, r);
|
|
121
133
|
}
|
|
122
|
-
let s = i.matched,
|
|
134
|
+
let s = i.matched, c = i.total, l = c > 0 ? s / c * 100 : 0;
|
|
123
135
|
return /* @__PURE__ */ o(n, {
|
|
124
136
|
alignItems: "center",
|
|
125
137
|
gap: "space-8",
|
|
@@ -129,7 +141,7 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
129
141
|
fontSize: "body.sm",
|
|
130
142
|
color: "grey.500",
|
|
131
143
|
minW: "80px",
|
|
132
|
-
children:
|
|
144
|
+
children: _.attributes[r]
|
|
133
145
|
}),
|
|
134
146
|
/* @__PURE__ */ a(t, {
|
|
135
147
|
flex: "1",
|
|
@@ -141,8 +153,8 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
141
153
|
h: "100%",
|
|
142
154
|
borderRadius: "full",
|
|
143
155
|
style: {
|
|
144
|
-
width: `${
|
|
145
|
-
background:
|
|
156
|
+
width: `${l}%`,
|
|
157
|
+
background: f(l)
|
|
146
158
|
}
|
|
147
159
|
})
|
|
148
160
|
}),
|
|
@@ -152,23 +164,23 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
152
164
|
fontWeight: "medium",
|
|
153
165
|
minW: "40px",
|
|
154
166
|
textAlign: "right",
|
|
155
|
-
style: { color:
|
|
167
|
+
style: { color: f(l) },
|
|
156
168
|
children: [
|
|
157
169
|
s,
|
|
158
170
|
"/",
|
|
159
|
-
|
|
171
|
+
c
|
|
160
172
|
]
|
|
161
173
|
})
|
|
162
174
|
]
|
|
163
175
|
}, r);
|
|
164
176
|
})]
|
|
165
177
|
}),
|
|
166
|
-
|
|
178
|
+
x.length > 0 && S.length > 0 && /* @__PURE__ */ a(t, {
|
|
167
179
|
h: "1px",
|
|
168
180
|
bg: "grey.100",
|
|
169
181
|
mb: "space-8"
|
|
170
182
|
}),
|
|
171
|
-
|
|
183
|
+
S.length > 0 && /* @__PURE__ */ o(r, {
|
|
172
184
|
alignItems: "stretch",
|
|
173
185
|
gap: "space-4",
|
|
174
186
|
children: [/* @__PURE__ */ a(e, {
|
|
@@ -176,11 +188,11 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
176
188
|
fontSize: "body.sm",
|
|
177
189
|
fontWeight: "bold",
|
|
178
190
|
color: "grey.400",
|
|
179
|
-
children:
|
|
191
|
+
children: _.notSpecified
|
|
180
192
|
}), /* @__PURE__ */ a(n, {
|
|
181
193
|
flexWrap: "wrap",
|
|
182
194
|
gap: "space-4",
|
|
183
|
-
children:
|
|
195
|
+
children: S.map((t) => /* @__PURE__ */ a(e, {
|
|
184
196
|
as: "span",
|
|
185
197
|
fontSize: "body.sm",
|
|
186
198
|
color: "grey.400",
|
|
@@ -189,11 +201,11 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
189
201
|
px: "space-8",
|
|
190
202
|
py: "2px",
|
|
191
203
|
borderRadius: "full",
|
|
192
|
-
children:
|
|
204
|
+
children: _.attributes[t]
|
|
193
205
|
}, t))
|
|
194
206
|
})]
|
|
195
207
|
}),
|
|
196
|
-
|
|
208
|
+
_.footer && /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a(t, {
|
|
197
209
|
h: "1px",
|
|
198
210
|
bg: "grey.100",
|
|
199
211
|
mt: "space-8",
|
|
@@ -203,12 +215,12 @@ var m = ({ percent: f, detail: m, labels: h }) => {
|
|
|
203
215
|
fontSize: "9px",
|
|
204
216
|
color: "grey.300",
|
|
205
217
|
style: { lineHeight: 1 },
|
|
206
|
-
children:
|
|
218
|
+
children: _.footer
|
|
207
219
|
})] })
|
|
208
220
|
]
|
|
209
221
|
});
|
|
210
222
|
};
|
|
211
223
|
//#endregion
|
|
212
|
-
export {
|
|
224
|
+
export { g as ChatScoreBreakdown };
|
|
213
225
|
|
|
214
226
|
//# sourceMappingURL=ChatScoreBreakdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatScoreBreakdown.js","names":[],"sources":["../../../src/components/chat/ChatScoreBreakdown.tsx"],"sourcesContent":["import { Box, HStack, VStack } from '@stokelp/styled-system/jsx'\nimport { Text } from '~/components'\n\nexport type ScoreSetAttributeKey =\n | 'origin'\n | 'rawMaterialOrigin'\n | 'temperature'\n | 'cutting'\n | 'cooking'\n | 'treatment'\n | 'label'\n | 'packaging'\n\nexport type ScoreNumericAttributeKey = 'grammageGsm' | 'recycledPct' | 'thicknessMicron'\n\nexport type ScoreAttributeKey = ScoreSetAttributeKey | ScoreNumericAttributeKey\n\n/** Proximity bucket for free numeric packaging specs: egal (equal) → non_correspondant (no match). */\nexport type ScoreLevel = 'egal' | 'proche' | 'eloigne' | 'non_correspondant'\n\nexport type ScoreAttributeDetail = {\n matched: number | null\n total: number | null\n level?: ScoreLevel | null\n}\n\nexport type ChatScoreBreakdownLabels = {\n title: string\n compared: string\n notSpecified: string\n attributes: Record<ScoreSetAttributeKey, string> & Partial<Record<ScoreNumericAttributeKey, string>>\n levels?: Record<ScoreLevel, string>\n footer?: string\n}\n\nexport type ChatScoreBreakdownProps = {\n percent: number\n detail: Record<string, ScoreAttributeDetail>\n labels: ChatScoreBreakdownLabels\n}\n\nconst ATTRIBUTE_ORDER: ScoreAttributeKey[] = [\n 'origin',\n 'rawMaterialOrigin',\n 'temperature',\n 'cutting',\n 'cooking',\n 'treatment',\n 'label',\n 'packaging',\n 'grammageGsm',\n 'recycledPct',\n 'thicknessMicron',\n]\n\nconst LEVEL_COLORS: Record<ScoreLevel, { bg: string; color: string }> = {\n egal: { bg: '#E6F3D9', color: '#3B6D11' },\n proche: { bg: '#F0F6DC', color: '#5E8516' },\n eloigne: { bg: '#FDF0E0', color: '#C2740C' },\n non_correspondant: { bg: '#FCEBEB', color: '#A32D2D' },\n}\n\nfunction getHeadlineColor(percent: number): string {\n if (percent >= 70) return '#3B6D11'\n if (percent >= 40) return '#854F0B'\n return '#A32D2D'\n}\n\nfunction getBarColor(ratioPercent: number): string {\n if (ratioPercent >= 70) return '#639922'\n if (ratioPercent >= 40) return '#BA7517'\n return '#E24B4A'\n}\n\nfunction hasLevel(detail?: ScoreAttributeDetail): boolean {\n return detail?.level != null\n}\n\nfunction isFraction(detail?: ScoreAttributeDetail): boolean {\n return detail?.matched != null && detail?.total != null\n}\n\nfunction isComparable(detail?: ScoreAttributeDetail): boolean {\n return hasLevel(detail) || isFraction(detail)\n}\n\nexport const ChatScoreBreakdown = ({ percent, detail, labels }: ChatScoreBreakdownProps) => {\n const compared = ATTRIBUTE_ORDER.filter(key => isComparable(detail[key]))\n const notSpecified = ATTRIBUTE_ORDER.filter(key => !isComparable(detail[key]) && labels.attributes[key] != null)\n\n return (\n <Box\n bg=\"white\"\n borderRadius=\"radius-8\"\n p=\"space-16\"\n minW=\"220px\"\n maxW=\"240px\"\n css={{ '& *': { fontFamily: 'inherit' } }}\n >\n <HStack justify=\"space-between\" alignItems=\"baseline\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.md\" fontWeight=\"bold\">\n {labels.title}\n </Text>\n <Text as=\"span\" fontSize=\"body.lg\" fontWeight=\"medium\" style={{ color: getHeadlineColor(percent) }}>\n {Math.round(percent)} %\n </Text>\n </HStack>\n\n <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />\n\n {compared.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.compared}\n </Text>\n {compared.map(key => {\n const entry = detail[key]\n if (hasLevel(entry)) {\n const level = entry.level as ScoreLevel\n const colors = LEVEL_COLORS[level]\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\" justify=\"space-between\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box px=\"space-8\" py=\"2px\" borderRadius=\"full\" style={{ backgroundColor: colors.bg }}>\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"medium\" style={{ color: colors.color }}>\n {labels.levels?.[level] ?? level}\n </Text>\n </Box>\n </HStack>\n )\n }\n\n const matched = entry.matched as number\n const total = entry.total as number\n const ratioPercent = total > 0 ? (matched / total) * 100 : 0\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box flex=\"1\" h=\"3px\" bg=\"grey.100\" borderRadius=\"full\" overflow=\"hidden\">\n <Box\n h=\"100%\"\n borderRadius=\"full\"\n style={{ width: `${ratioPercent}%`, background: getBarColor(ratioPercent) }}\n />\n </Box>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n minW=\"40px\"\n textAlign=\"right\"\n style={{ color: getBarColor(ratioPercent) }}\n >\n {matched}/{total}\n </Text>\n </HStack>\n )\n })}\n </VStack>\n )}\n\n {compared.length > 0 && notSpecified.length > 0 && <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />}\n\n {notSpecified.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.notSpecified}\n </Text>\n <HStack flexWrap=\"wrap\" gap=\"space-4\">\n {notSpecified.map(key => (\n <Text\n key={key}\n as=\"span\"\n fontSize=\"body.sm\"\n color=\"grey.400\"\n border=\"1px solid\"\n borderColor=\"grey.100\"\n px=\"space-8\"\n py=\"2px\"\n borderRadius=\"full\"\n >\n {labels.attributes[key]}\n </Text>\n ))}\n </HStack>\n </VStack>\n )}\n\n {labels.footer && (\n <>\n <Box h=\"1px\" bg=\"grey.100\" mt=\"space-8\" mb=\"space-8\" />\n <Text as=\"span\" fontSize=\"9px\" color=\"grey.300\" style={{ lineHeight: 1 }}>\n {labels.footer}\n </Text>\n </>\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatScoreBreakdown.js","names":[],"sources":["../../../src/components/chat/ChatScoreBreakdown.tsx"],"sourcesContent":["import { Box, HStack, VStack } from '@stokelp/styled-system/jsx'\nimport { Text } from '~/components'\n\nexport type ScoreSetAttributeKey =\n | 'origin'\n | 'rawMaterialOrigin'\n | 'temperature'\n | 'cutting'\n | 'cooking'\n | 'treatment'\n | 'label'\n | 'packaging'\n\nexport type ScoreNumericAttributeKey = 'grammageGsm' | 'recycledPct' | 'thicknessMicron'\n\nexport type ScoreAttributeKey = ScoreSetAttributeKey | ScoreNumericAttributeKey\n\n/** Proximity bucket for free numeric packaging specs: egal (equal) → non_correspondant (no match). */\nexport type ScoreLevel = 'egal' | 'proche' | 'eloigne' | 'non_correspondant'\n\nexport type ScoreAttributeDetail = {\n matched: number | null\n total: number | null\n level?: ScoreLevel | null\n}\n\nexport type ChatScoreBreakdownLabels = {\n title: string\n compared: string\n notSpecified: string\n attributes: Record<ScoreSetAttributeKey, string> & Partial<Record<ScoreNumericAttributeKey, string>>\n levels?: Record<ScoreLevel, string>\n footer?: string\n}\n\nexport type ChatScoreBreakdownProps = {\n percent: number\n detail: Record<string, ScoreAttributeDetail>\n labels: ChatScoreBreakdownLabels\n}\n\nconst ATTRIBUTE_ORDER: ScoreAttributeKey[] = [\n 'origin',\n 'rawMaterialOrigin',\n 'temperature',\n 'cutting',\n 'cooking',\n 'treatment',\n 'label',\n 'packaging',\n 'grammageGsm',\n 'recycledPct',\n 'thicknessMicron',\n]\n\n// Attributes that only exist for food products; hidden for packaging products.\nconst FOOD_ONLY_KEYS: ScoreAttributeKey[] = ['temperature', 'cutting', 'cooking']\n// Free numeric specs that only exist for packaging products; hidden for food products.\nconst PACKAGING_ONLY_KEYS: ScoreNumericAttributeKey[] = ['grammageGsm', 'recycledPct', 'thicknessMicron']\n\nconst LEVEL_COLORS: Record<ScoreLevel, { bg: string; color: string }> = {\n egal: { bg: '#E6F3D9', color: '#3B6D11' },\n proche: { bg: '#F0F6DC', color: '#5E8516' },\n eloigne: { bg: '#FDF0E0', color: '#C2740C' },\n non_correspondant: { bg: '#FCEBEB', color: '#A32D2D' },\n}\n\nfunction getHeadlineColor(percent: number): string {\n if (percent >= 70) return '#3B6D11'\n if (percent >= 40) return '#854F0B'\n return '#A32D2D'\n}\n\nfunction getBarColor(ratioPercent: number): string {\n if (ratioPercent >= 70) return '#639922'\n if (ratioPercent >= 40) return '#BA7517'\n return '#E24B4A'\n}\n\nfunction hasLevel(detail?: ScoreAttributeDetail): boolean {\n return detail?.level != null\n}\n\nfunction isFraction(detail?: ScoreAttributeDetail): boolean {\n return detail?.matched != null && detail?.total != null\n}\n\nfunction isComparable(detail?: ScoreAttributeDetail): boolean {\n return hasLevel(detail) || isFraction(detail)\n}\n\nexport const ChatScoreBreakdown = ({ percent, detail, labels }: ChatScoreBreakdownProps) => {\n // A packaging product exposes the numeric specs (comparable via level); food attributes\n // then come back fully null and must be hidden entirely, and vice versa.\n const isPackaging = PACKAGING_ONLY_KEYS.some(key => detail[key]?.level != null)\n const hiddenKeys = new Set<ScoreAttributeKey>(isPackaging ? FOOD_ONLY_KEYS : PACKAGING_ONLY_KEYS)\n const visibleKeys = ATTRIBUTE_ORDER.filter(key => !hiddenKeys.has(key))\n\n const compared = visibleKeys.filter(key => isComparable(detail[key]))\n const notSpecified = visibleKeys.filter(key => !isComparable(detail[key]) && labels.attributes[key] != null)\n\n return (\n <Box\n bg=\"white\"\n borderRadius=\"radius-8\"\n p=\"space-16\"\n minW=\"220px\"\n maxW=\"240px\"\n css={{ '& *': { fontFamily: 'inherit' } }}\n >\n <HStack justify=\"space-between\" alignItems=\"baseline\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.md\" fontWeight=\"bold\">\n {labels.title}\n </Text>\n <Text as=\"span\" fontSize=\"body.lg\" fontWeight=\"medium\" style={{ color: getHeadlineColor(percent) }}>\n {Math.round(percent)} %\n </Text>\n </HStack>\n\n <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />\n\n {compared.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\" mb=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.compared}\n </Text>\n {compared.map(key => {\n const entry = detail[key]\n if (hasLevel(entry)) {\n const level = entry.level as ScoreLevel\n const colors = LEVEL_COLORS[level]\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\" justify=\"space-between\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box px=\"space-8\" py=\"2px\" borderRadius=\"full\" flexShrink=\"0\" style={{ backgroundColor: colors.bg }}>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n style={{ color: colors.color, whiteSpace: 'nowrap' }}\n >\n {labels.levels?.[level] ?? level}\n </Text>\n </Box>\n </HStack>\n )\n }\n\n const matched = entry.matched as number\n const total = entry.total as number\n const ratioPercent = total > 0 ? (matched / total) * 100 : 0\n return (\n <HStack key={key} alignItems=\"center\" gap=\"space-8\">\n <Text as=\"span\" fontSize=\"body.sm\" color=\"grey.500\" minW=\"80px\">\n {labels.attributes[key]}\n </Text>\n <Box flex=\"1\" h=\"3px\" bg=\"grey.100\" borderRadius=\"full\" overflow=\"hidden\">\n <Box\n h=\"100%\"\n borderRadius=\"full\"\n style={{ width: `${ratioPercent}%`, background: getBarColor(ratioPercent) }}\n />\n </Box>\n <Text\n as=\"span\"\n fontSize=\"body.sm\"\n fontWeight=\"medium\"\n minW=\"40px\"\n textAlign=\"right\"\n style={{ color: getBarColor(ratioPercent) }}\n >\n {matched}/{total}\n </Text>\n </HStack>\n )\n })}\n </VStack>\n )}\n\n {compared.length > 0 && notSpecified.length > 0 && <Box h=\"1px\" bg=\"grey.100\" mb=\"space-8\" />}\n\n {notSpecified.length > 0 && (\n <VStack alignItems=\"stretch\" gap=\"space-4\">\n <Text as=\"span\" fontSize=\"body.sm\" fontWeight=\"bold\" color=\"grey.400\">\n {labels.notSpecified}\n </Text>\n <HStack flexWrap=\"wrap\" gap=\"space-4\">\n {notSpecified.map(key => (\n <Text\n key={key}\n as=\"span\"\n fontSize=\"body.sm\"\n color=\"grey.400\"\n border=\"1px solid\"\n borderColor=\"grey.100\"\n px=\"space-8\"\n py=\"2px\"\n borderRadius=\"full\"\n >\n {labels.attributes[key]}\n </Text>\n ))}\n </HStack>\n </VStack>\n )}\n\n {labels.footer && (\n <>\n <Box h=\"1px\" bg=\"grey.100\" mt=\"space-8\" mb=\"space-8\" />\n <Text as=\"span\" fontSize=\"9px\" color=\"grey.300\" style={{ lineHeight: 1 }}>\n {labels.footer}\n </Text>\n </>\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|