@schandlergarcia/sf-web-components 1.9.88 → 2.1.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.
Files changed (44) hide show
  1. package/.a4drules/features/command-center-dashboard-rule.md +1 -1
  2. package/.a4drules/skills/command-center-builder/SKILL.md +33 -36
  3. package/.a4drules/skills/command-center-builder/getting-started.md +64 -104
  4. package/.a4drules/skills/command-center-builder/improved-build-process.md +28 -34
  5. package/.a4drules/skills/command-center-guide/SKILL.md +9 -9
  6. package/.a4drules/skills/command-center-project/SKILL.md +4 -5
  7. package/.a4drules/skills/component-library/SKILL.md +8 -10
  8. package/.a4drules/skills/component-library/card-components.md +3 -3
  9. package/.a4drules/skills/component-library/chat-data.md +4 -6
  10. package/.a4drules/troubleshooting/codegen-overwrites-types.md +21 -162
  11. package/.a4drules/troubleshooting/graphql-introspection-failure.md +13 -264
  12. package/.a4drules/validation-requirements.md +3 -5
  13. package/.a4drules/webapp-data.md +1 -1
  14. package/CHANGELOG.md +33 -0
  15. package/CLAUDE.md +42 -39
  16. package/brands/engine/brand.css +40 -0
  17. package/brands/engine/global.css +234 -0
  18. package/dist/components/library/cards/ActivityCard.js +9 -9
  19. package/dist/components/library/cards/ActivityCard.js.map +1 -1
  20. package/dist/styles/base.css +112 -27
  21. package/dist/styles/global.css +15 -30
  22. package/package.json +7 -4
  23. package/scripts/apply-brand.mjs +178 -0
  24. package/scripts/postinstall.mjs +24 -201
  25. package/scripts/reset-command-center.sh +53 -411
  26. package/scripts/validate-dashboard.sh +4 -4
  27. package/src/components/library/cards/ActivityCard.jsx +2 -2
  28. package/src/styles/base.css +223 -0
  29. package/src/styles/global.css +223 -0
  30. package/src/templates/config/vite.config.ts.template +0 -18
  31. package/.a4drules/features/engine-dashboard-rule.md +0 -63
  32. package/.a4drules/features/phase2-data-pattern.md +0 -15
  33. package/data/README.md +0 -202
  34. package/data/USAGE.md +0 -81
  35. package/data/copy-to-webapp.sh +0 -61
  36. package/scripts/generate-schema-from-sample.mjs +0 -370
  37. /package/{data → brands/engine}/agentApiConfig.ts +0 -0
  38. /package/{data → brands/engine}/engine-command-center-prd.md +0 -0
  39. /package/{data → brands/engine}/engine-live-data.js +0 -0
  40. /package/{data → brands/engine}/engine-sample-data.js +0 -0
  41. /package/{assets/images → brands/engine}/engine_logo.png +0 -0
  42. /package/{data → brands/engine}/schema.graphql +0 -0
  43. /package/{data → brands/engine}/useEngineLiveData.ts +0 -0
  44. /package/{data → brands/engine}/useEvaAgent.ts +0 -0
@@ -0,0 +1,234 @@
1
+ @import '@heroui/styles';
2
+
3
+ @layer base {
4
+ html,
5
+ body,
6
+ #root {
7
+ @apply min-h-screen;
8
+ }
9
+
10
+ body {
11
+ @apply antialiased bg-white;
12
+ }
13
+ }
14
+
15
+ @import 'tw-animate-css';
16
+ @import 'shadcn/tailwind.css';
17
+
18
+ @custom-variant dark (&:is(.dark *));
19
+
20
+ @source "../components/library";
21
+ @source "../components/pages";
22
+
23
+ @theme inline {
24
+ --color-background: var(--background);
25
+ --color-foreground: var(--foreground);
26
+ --color-card: var(--card);
27
+ --color-card-foreground: var(--card-foreground);
28
+ --color-popover: var(--popover);
29
+ --color-popover-foreground: var(--popover-foreground);
30
+ --color-primary: var(--primary);
31
+ --color-primary-foreground: var(--primary-foreground);
32
+ --color-secondary: var(--secondary);
33
+ --color-secondary-foreground: var(--secondary-foreground);
34
+ --color-muted: var(--muted);
35
+ --color-muted-foreground: var(--muted-foreground);
36
+ --color-accent: var(--accent);
37
+ --color-accent-foreground: var(--accent-foreground);
38
+ --color-destructive: var(--destructive);
39
+ --color-destructive-foreground: var(--destructive-foreground);
40
+ --color-border: var(--border);
41
+ --color-input: var(--input);
42
+ --color-ring: var(--ring);
43
+ --color-chart-1: var(--chart-1);
44
+ --color-chart-2: var(--chart-2);
45
+ --color-chart-3: var(--chart-3);
46
+ --color-chart-4: var(--chart-4);
47
+ --color-chart-5: var(--chart-5);
48
+ --radius-sm: calc(var(--radius) - 4px);
49
+ --radius-md: calc(var(--radius) - 2px);
50
+ --radius-lg: var(--radius);
51
+ --radius-xl: calc(var(--radius) + 4px);
52
+ --color-sidebar: var(--sidebar);
53
+ --color-sidebar-foreground: var(--sidebar-foreground);
54
+ --color-sidebar-primary: var(--sidebar-primary);
55
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
56
+ --color-sidebar-accent: var(--sidebar-accent);
57
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
58
+ --color-sidebar-border: var(--sidebar-border);
59
+ --color-sidebar-ring: var(--sidebar-ring);
60
+
61
+ /* Engine brand palette — official guidelines */
62
+ --color-engine-black: #0D1117;
63
+ --color-engine-cyan: #7DCBD9;
64
+ --color-engine-green: #1E9D6D;
65
+ --color-engine-blue: #157DE5;
66
+ --color-engine-orange: #FD4B23;
67
+ --color-engine-amber: #FFB200;
68
+ --color-engine-bg: #F3F3F4;
69
+ --color-engine-border: #B0B1B3;
70
+ --color-engine-text: #0D1117;
71
+ --color-engine-muted: #616368;
72
+ --color-engine-label: #B0B1B3;
73
+
74
+ /* Engine Cyan brand ramp */
75
+ --color-brand-50: #F0FAFB;
76
+ --color-brand-100: #D9F2F5;
77
+ --color-brand-200: #B3E5EB;
78
+ --color-brand-300: #7DCBD9;
79
+ --color-brand-400: #5BB8CA;
80
+ --color-brand-500: #3AA0B5;
81
+ --color-brand-600: #2D849A;
82
+ --color-brand-700: #266B7E;
83
+ --color-brand-800: #235768;
84
+ --color-brand-900: #1F4858;
85
+ --color-brand-950: #112E3A;
86
+
87
+ --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
88
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
89
+
90
+ --radius-pill: 9999px;
91
+ --radius-card: 10px;
92
+ }
93
+
94
+ :root {
95
+ --radius: 0.625rem;
96
+ --background: oklch(1 0 0);
97
+ --foreground: oklch(0.145 0 0);
98
+ --card: oklch(1 0 0);
99
+ --card-foreground: oklch(0.145 0 0);
100
+ --popover: oklch(1 0 0);
101
+ --popover-foreground: oklch(0.145 0 0);
102
+ --primary: oklch(0.205 0 0);
103
+ --primary-foreground: oklch(0.985 0 0);
104
+ --secondary: oklch(0.97 0 0);
105
+ --secondary-foreground: oklch(0.205 0 0);
106
+ --muted: oklch(0.97 0 0);
107
+ --muted-foreground: oklch(0.556 0 0);
108
+ --accent: oklch(0.97 0 0);
109
+ --accent-foreground: oklch(0.205 0 0);
110
+ --destructive: oklch(0.577 0.245 27.325);
111
+ --border: oklch(0.922 0 0);
112
+ --input: oklch(0.922 0 0);
113
+ --ring: oklch(0.708 0 0);
114
+ --chart-1: oklch(0.646 0.222 41.116);
115
+ --chart-2: oklch(0.6 0.118 184.704);
116
+ --chart-3: oklch(0.398 0.07 227.392);
117
+ --chart-4: oklch(0.828 0.189 84.429);
118
+ --chart-5: oklch(0.769 0.188 70.08);
119
+ --sidebar: oklch(0.985 0 0);
120
+ --sidebar-foreground: oklch(0.145 0 0);
121
+ --sidebar-primary: oklch(0.205 0 0);
122
+ --sidebar-primary-foreground: oklch(0.985 0 0);
123
+ --sidebar-accent: oklch(0.97 0 0);
124
+ --sidebar-accent-foreground: oklch(0.205 0 0);
125
+ --sidebar-border: oklch(0.922 0 0);
126
+ --sidebar-ring: oklch(0.708 0 0);
127
+ }
128
+
129
+ .dark {
130
+ --background: oklch(0.145 0 0);
131
+ --foreground: oklch(0.985 0 0);
132
+ --card: oklch(0.205 0 0);
133
+ --card-foreground: oklch(0.985 0 0);
134
+ --popover: oklch(0.205 0 0);
135
+ --popover-foreground: oklch(0.985 0 0);
136
+ --primary: oklch(0.922 0 0);
137
+ --primary-foreground: oklch(0.205 0 0);
138
+ --secondary: oklch(0.269 0 0);
139
+ --secondary-foreground: oklch(0.985 0 0);
140
+ --muted: oklch(0.269 0 0);
141
+ --muted-foreground: oklch(0.708 0 0);
142
+ --accent: oklch(0.269 0 0);
143
+ --accent-foreground: oklch(0.985 0 0);
144
+ --destructive: oklch(0.704 0.191 22.216);
145
+ --border: oklch(1 0 0 / 10%);
146
+ --input: oklch(1 0 0 / 15%);
147
+ --ring: oklch(0.556 0 0);
148
+ --chart-1: oklch(0.488 0.243 264.376);
149
+ --chart-2: oklch(0.696 0.17 162.48);
150
+ --chart-3: oklch(0.769 0.188 70.08);
151
+ --chart-4: oklch(0.627 0.265 303.9);
152
+ --chart-5: oklch(0.645 0.246 16.439);
153
+ --sidebar: oklch(0.205 0 0);
154
+ --sidebar-foreground: oklch(0.985 0 0);
155
+ --sidebar-primary: oklch(0.488 0.243 264.376);
156
+ --sidebar-primary-foreground: oklch(0.985 0 0);
157
+ --sidebar-accent: oklch(0.269 0 0);
158
+ --sidebar-accent-foreground: oklch(0.985 0 0);
159
+ --sidebar-border: oklch(1 0 0 / 10%);
160
+ --sidebar-ring: oklch(0.556 0 0);
161
+ }
162
+
163
+ @layer base {
164
+ * {
165
+ @apply border-border outline-ring/50;
166
+ }
167
+ body {
168
+ @apply bg-background text-foreground;
169
+ }
170
+ }
171
+
172
+ /*
173
+ * Restore HeroUI theme variables inside the Command Center scope.
174
+ * Uses Engine brand colors: Cyan #7DCBD9 as secondary, Orange-Red #FD4B23 as danger.
175
+ */
176
+ .heroui-scope {
177
+ --primary: #0D1117;
178
+ --primary-foreground: oklch(0.9911 0 0);
179
+ --secondary: #7DCBD9;
180
+ --secondary-foreground: #0D1117;
181
+ --success: #1E9D6D;
182
+ --success-foreground: oklch(0.9911 0 0);
183
+ --warning: #FFB200;
184
+ --warning-foreground: #0D1117;
185
+ --danger: #FD4B23;
186
+ --danger-foreground: oklch(0.9911 0 0);
187
+
188
+ --muted: oklch(0.5517 0.0138 285.94);
189
+ --accent: oklch(0.6204 0.195 253.83);
190
+ --accent-foreground: oklch(0.9911 0 0);
191
+ --background: #F3F3F4;
192
+ --foreground: #0D1117;
193
+ --default: oklch(94% 0.001 286.375);
194
+ --default-foreground: #0D1117;
195
+ --border: #B0B1B3;
196
+ --separator: oklch(92% 0.004 286.32);
197
+ --segment: oklch(100% 0 0);
198
+ --segment-foreground: #0D1117;
199
+ --surface: oklch(100% 0 0);
200
+ --surface-foreground: #0D1117;
201
+ --overlay: oklch(100% 0 0);
202
+ --overlay-foreground: #0D1117;
203
+ --focus: #157DE5;
204
+ --link: #0D1117;
205
+ }
206
+
207
+ /* ChatBar expanded overlay — horizontal padding so it doesn't hit window edges */
208
+ body > .fixed.inset-x-0.rounded-2xl {
209
+ left: 1.5rem !important;
210
+ right: 1.5rem !important;
211
+ }
212
+
213
+ .dark .heroui-scope,
214
+ .heroui-scope.dark {
215
+ --muted: oklch(70.5% 0.015 286.067);
216
+ --background: oklch(12% 0.005 285.823);
217
+ --foreground: oklch(0.9911 0 0);
218
+ --default: oklch(27.4% 0.006 286.033);
219
+ --default-foreground: oklch(0.9911 0 0);
220
+ --border: oklch(28% 0.006 286.033);
221
+ --separator: oklch(25% 0.006 286.033);
222
+ --segment: oklch(0.3964 0.01 285.93);
223
+ --segment-foreground: oklch(0.9911 0 0);
224
+ --surface: oklch(0.2103 0.0059 285.89);
225
+ --surface-foreground: oklch(0.9911 0 0);
226
+ --overlay: oklch(0.2103 0.0059 285.89);
227
+ --overlay-foreground: oklch(0.9911 0 0);
228
+ --warning: oklch(0.8203 0.1388 76.34);
229
+ --warning-foreground: #0D1117;
230
+ --danger: oklch(0.594 0.1967 24.63);
231
+ --danger-foreground: oklch(0.9911 0 0);
232
+ --focus: #157DE5;
233
+ --link: oklch(0.9911 0 0);
234
+ }
@@ -1,4 +1,4 @@
1
- import { jsxs as i, jsx as t } from "react/jsx-runtime";
1
+ import { jsxs as r, jsx as t } from "react/jsx-runtime";
2
2
  import "react";
3
3
  import { AnimatePresence as n, motion as o } from "framer-motion";
4
4
  import { ExclamationCircleIcon as c, CheckCircleIcon as d, ClockIcon as m, ArrowPathIcon as p } from "@heroicons/react/24/outline";
@@ -10,7 +10,7 @@ const l = {
10
10
  error: { Icon: c, color: "text-red-500", spin: !1 }
11
11
  };
12
12
  function u({ action: e }) {
13
- const r = l[e.status] ?? l.pending;
13
+ const i = l[e.status] ?? l.pending;
14
14
  return /* @__PURE__ */ t(
15
15
  o.div,
16
16
  {
@@ -18,20 +18,20 @@ function u({ action: e }) {
18
18
  animate: { y: 0, opacity: 1 },
19
19
  exit: { y: -12, opacity: 0 },
20
20
  className: "rounded-lg border border-slate-100 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-950/40",
21
- children: /* @__PURE__ */ i("div", { className: "flex items-start gap-2", children: [
22
- /* @__PURE__ */ t(r.Icon, { className: `mt-0.5 h-4 w-4 shrink-0 ${r.color} ${r.spin ? "animate-spin" : ""}` }),
23
- /* @__PURE__ */ i("div", { className: "min-w-0", children: [
21
+ children: /* @__PURE__ */ r("div", { className: "flex items-start gap-2", children: [
22
+ /* @__PURE__ */ t(i.Icon, { className: `mt-0.5 h-4 w-4 shrink-0 ${i.color} ${i.spin ? "animate-spin" : ""}` }),
23
+ /* @__PURE__ */ r("div", { className: "min-w-0", children: [
24
24
  /* @__PURE__ */ t("div", { className: "text-xs font-medium text-slate-700 dark:text-slate-200", children: e.title ?? e.action }),
25
- (e.subtitle ?? e.traveler ?? e.timestamp ?? e.startedAt) && /* @__PURE__ */ t("div", { className: "mt-0.5 text-[10px] text-slate-400", children: [e.subtitle, e.traveler, e.timestamp ?? e.startedAt].filter(Boolean).join(" · ") })
25
+ (e.subtitle ?? e.description ?? e.timestamp ?? e.startedAt) && /* @__PURE__ */ t("div", { className: "mt-0.5 text-[10px] text-slate-400", children: [e.subtitle, e.description, e.timestamp ?? e.startedAt].filter(Boolean).join(" · ") })
26
26
  ] })
27
27
  ] })
28
28
  }
29
29
  );
30
30
  }
31
- function b({ title: e = "Activity", actions: r = [], className: a = "" }) {
32
- return r.length === 0 ? null : /* @__PURE__ */ i("div", { className: a, children: [
31
+ function b({ title: e = "Activity", actions: i = [], className: a = "" }) {
32
+ return i.length === 0 ? null : /* @__PURE__ */ r("div", { className: a, children: [
33
33
  e && /* @__PURE__ */ t(x, { as: "div", size: "xs", weight: "semibold", muted: !0, className: "mb-2 uppercase tracking-wider", children: e }),
34
- /* @__PURE__ */ t("div", { className: "space-y-2", children: /* @__PURE__ */ t(n, { children: r.map((s) => /* @__PURE__ */ t(u, { action: s }, s.id)) }) })
34
+ /* @__PURE__ */ t("div", { className: "space-y-2", children: /* @__PURE__ */ t(n, { children: i.map((s) => /* @__PURE__ */ t(u, { action: s }, s.id)) }) })
35
35
  ] });
36
36
  }
37
37
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"ActivityCard.js","sources":["../../../../src/components/library/cards/ActivityCard.jsx"],"sourcesContent":["import React from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport { ArrowPathIcon, CheckCircleIcon, ExclamationCircleIcon, ClockIcon } from \"@heroicons/react/24/outline\";\nimport UIText from \"../ui/Text\";\n\nconst STATUS_ICON = {\n working: { Icon: ArrowPathIcon, color: \"text-indigo-500\", spin: true },\n pending: { Icon: ClockIcon, color: \"text-slate-400\", spin: false },\n complete: { Icon: CheckCircleIcon, color: \"text-emerald-500\", spin: false },\n error: { Icon: ExclamationCircleIcon, color: \"text-red-500\", spin: false },\n};\n\nfunction ActionItem({ action }) {\n const s = STATUS_ICON[action.status] ?? STATUS_ICON.pending;\n return (\n <motion.div\n initial={{ y: 12, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={{ y: -12, opacity: 0 }}\n className=\"rounded-lg border border-slate-100 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-950/40\"\n >\n <div className=\"flex items-start gap-2\">\n <s.Icon className={`mt-0.5 h-4 w-4 shrink-0 ${s.color} ${s.spin ? \"animate-spin\" : \"\"}`} />\n <div className=\"min-w-0\">\n <div className=\"text-xs font-medium text-slate-700 dark:text-slate-200\">{action.title ?? action.action}</div>\n {(action.subtitle ?? action.traveler ?? action.timestamp ?? action.startedAt) && (\n <div className=\"mt-0.5 text-[10px] text-slate-400\">\n {[action.subtitle, action.traveler, action.timestamp ?? action.startedAt].filter(Boolean).join(\" · \")}\n </div>\n )}\n </div>\n </div>\n </motion.div>\n );\n}\n\nexport default function ActivityCard({ title = \"Activity\", actions = [], className = \"\" }) {\n if (actions.length === 0) return null;\n\n return (\n <div className={className}>\n {title && (\n <UIText as=\"div\" size=\"xs\" weight=\"semibold\" muted className=\"mb-2 uppercase tracking-wider\">\n {title}\n </UIText>\n )}\n <div className=\"space-y-2\">\n <AnimatePresence>\n {actions.map(a => (\n <ActionItem key={a.id} action={a} />\n ))}\n </AnimatePresence>\n </div>\n </div>\n );\n}\n"],"names":["STATUS_ICON","ArrowPathIcon","ClockIcon","CheckCircleIcon","ExclamationCircleIcon","ActionItem","action","s","jsx","motion","jsxs","ActivityCard","title","actions","className","UIText","AnimatePresence","a"],"mappings":";;;;;AAKA,MAAMA,IAAc;AAAA,EAClB,SAAU,EAAE,MAAMC,GAAsB,OAAO,mBAAoB,MAAM,GAAA;AAAA,EACzE,SAAU,EAAE,MAAMC,GAAsB,OAAO,kBAAoB,MAAM,GAAA;AAAA,EACzE,UAAU,EAAE,MAAMC,GAAsB,OAAO,oBAAoB,MAAM,GAAA;AAAA,EACzE,OAAU,EAAE,MAAMC,GAAuB,OAAO,gBAAoB,MAAM,GAAA;AAC5E;AAEA,SAASC,EAAW,EAAE,QAAAC,KAAU;AAC9B,QAAMC,IAAIP,EAAYM,EAAO,MAAM,KAAKN,EAAY;AACpD,SACE,gBAAAQ;AAAA,IAACC,EAAO;AAAA,IAAP;AAAA,MACC,SAAS,EAAE,GAAG,IAAI,SAAS,EAAA;AAAA,MAC3B,SAAS,EAAE,GAAG,GAAG,SAAS,EAAA;AAAA,MAC1B,MAAM,EAAE,GAAG,KAAK,SAAS,EAAA;AAAA,MACzB,WAAU;AAAA,MAEV,UAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,QAAA,gBAAAF,EAACD,EAAE,MAAF,EAAO,WAAW,2BAA2BA,EAAE,KAAK,IAAIA,EAAE,OAAO,iBAAiB,EAAE,GAAA,CAAI;AAAA,QACzF,gBAAAG,EAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,UAAA,gBAAAF,EAAC,SAAI,WAAU,0DAA0D,UAAAF,EAAO,SAASA,EAAO,QAAO;AAAA,WACrGA,EAAO,YAAYA,EAAO,YAAYA,EAAO,aAAaA,EAAO,cACjE,gBAAAE,EAAC,OAAA,EAAI,WAAU,qCACZ,UAAA,CAACF,EAAO,UAAUA,EAAO,UAAUA,EAAO,aAAaA,EAAO,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,EAAA,CACtG;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAwBK,EAAa,EAAE,OAAAC,IAAQ,YAAY,SAAAC,IAAU,IAAI,WAAAC,IAAY,MAAM;AACzF,SAAID,EAAQ,WAAW,IAAU,OAG/B,gBAAAH,EAAC,SAAI,WAAAI,GACF,UAAA;AAAA,IAAAF,KACC,gBAAAJ,EAACO,GAAA,EAAO,IAAG,OAAM,MAAK,MAAK,QAAO,YAAW,OAAK,IAAC,WAAU,iCAC1D,UAAAH,GACH;AAAA,sBAED,OAAA,EAAI,WAAU,aACb,UAAA,gBAAAJ,EAACQ,KACE,UAAAH,EAAQ,IAAI,CAAAI,MACX,gBAAAT,EAACH,KAAsB,QAAQY,EAAA,GAAdA,EAAE,EAAe,CACnC,GACH,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;"}
1
+ {"version":3,"file":"ActivityCard.js","sources":["../../../../src/components/library/cards/ActivityCard.jsx"],"sourcesContent":["import React from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport { ArrowPathIcon, CheckCircleIcon, ExclamationCircleIcon, ClockIcon } from \"@heroicons/react/24/outline\";\nimport UIText from \"../ui/Text\";\n\nconst STATUS_ICON = {\n working: { Icon: ArrowPathIcon, color: \"text-indigo-500\", spin: true },\n pending: { Icon: ClockIcon, color: \"text-slate-400\", spin: false },\n complete: { Icon: CheckCircleIcon, color: \"text-emerald-500\", spin: false },\n error: { Icon: ExclamationCircleIcon, color: \"text-red-500\", spin: false },\n};\n\nfunction ActionItem({ action }) {\n const s = STATUS_ICON[action.status] ?? STATUS_ICON.pending;\n return (\n <motion.div\n initial={{ y: 12, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={{ y: -12, opacity: 0 }}\n className=\"rounded-lg border border-slate-100 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-950/40\"\n >\n <div className=\"flex items-start gap-2\">\n <s.Icon className={`mt-0.5 h-4 w-4 shrink-0 ${s.color} ${s.spin ? \"animate-spin\" : \"\"}`} />\n <div className=\"min-w-0\">\n <div className=\"text-xs font-medium text-slate-700 dark:text-slate-200\">{action.title ?? action.action}</div>\n {(action.subtitle ?? action.description ?? action.timestamp ?? action.startedAt) && (\n <div className=\"mt-0.5 text-[10px] text-slate-400\">\n {[action.subtitle, action.description, action.timestamp ?? action.startedAt].filter(Boolean).join(\" · \")}\n </div>\n )}\n </div>\n </div>\n </motion.div>\n );\n}\n\nexport default function ActivityCard({ title = \"Activity\", actions = [], className = \"\" }) {\n if (actions.length === 0) return null;\n\n return (\n <div className={className}>\n {title && (\n <UIText as=\"div\" size=\"xs\" weight=\"semibold\" muted className=\"mb-2 uppercase tracking-wider\">\n {title}\n </UIText>\n )}\n <div className=\"space-y-2\">\n <AnimatePresence>\n {actions.map(a => (\n <ActionItem key={a.id} action={a} />\n ))}\n </AnimatePresence>\n </div>\n </div>\n );\n}\n"],"names":["STATUS_ICON","ArrowPathIcon","ClockIcon","CheckCircleIcon","ExclamationCircleIcon","ActionItem","action","s","jsx","motion","jsxs","ActivityCard","title","actions","className","UIText","AnimatePresence","a"],"mappings":";;;;;AAKA,MAAMA,IAAc;AAAA,EAClB,SAAU,EAAE,MAAMC,GAAsB,OAAO,mBAAoB,MAAM,GAAA;AAAA,EACzE,SAAU,EAAE,MAAMC,GAAsB,OAAO,kBAAoB,MAAM,GAAA;AAAA,EACzE,UAAU,EAAE,MAAMC,GAAsB,OAAO,oBAAoB,MAAM,GAAA;AAAA,EACzE,OAAU,EAAE,MAAMC,GAAuB,OAAO,gBAAoB,MAAM,GAAA;AAC5E;AAEA,SAASC,EAAW,EAAE,QAAAC,KAAU;AAC9B,QAAMC,IAAIP,EAAYM,EAAO,MAAM,KAAKN,EAAY;AACpD,SACE,gBAAAQ;AAAA,IAACC,EAAO;AAAA,IAAP;AAAA,MACC,SAAS,EAAE,GAAG,IAAI,SAAS,EAAA;AAAA,MAC3B,SAAS,EAAE,GAAG,GAAG,SAAS,EAAA;AAAA,MAC1B,MAAM,EAAE,GAAG,KAAK,SAAS,EAAA;AAAA,MACzB,WAAU;AAAA,MAEV,UAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,QAAA,gBAAAF,EAACD,EAAE,MAAF,EAAO,WAAW,2BAA2BA,EAAE,KAAK,IAAIA,EAAE,OAAO,iBAAiB,EAAE,GAAA,CAAI;AAAA,QACzF,gBAAAG,EAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,UAAA,gBAAAF,EAAC,SAAI,WAAU,0DAA0D,UAAAF,EAAO,SAASA,EAAO,QAAO;AAAA,WACrGA,EAAO,YAAYA,EAAO,eAAeA,EAAO,aAAaA,EAAO,cACpE,gBAAAE,EAAC,OAAA,EAAI,WAAU,qCACZ,UAAA,CAACF,EAAO,UAAUA,EAAO,aAAaA,EAAO,aAAaA,EAAO,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,EAAA,CACzG;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAwBK,EAAa,EAAE,OAAAC,IAAQ,YAAY,SAAAC,IAAU,IAAI,WAAAC,IAAY,MAAM;AACzF,SAAID,EAAQ,WAAW,IAAU,OAG/B,gBAAAH,EAAC,SAAI,WAAAI,GACF,UAAA;AAAA,IAAAF,KACC,gBAAAJ,EAACO,GAAA,EAAO,IAAG,OAAM,MAAK,MAAK,QAAO,YAAW,OAAK,IAAC,WAAU,iCAC1D,UAAAH,GACH;AAAA,sBAED,OAAA,EAAI,WAAU,aACb,UAAA,gBAAAJ,EAACQ,KACE,UAAAH,EAAQ,IAAI,CAAAI,MACX,gBAAAT,EAACH,KAAsB,QAAQY,EAAA,GAAdA,EAAE,EAAe,CACnC,GACH,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;"}
@@ -1,3 +1,25 @@
1
+ @import '@heroui/styles';
2
+
3
+ @layer base {
4
+ html,
5
+ body,
6
+ #root {
7
+ @apply min-h-screen;
8
+ }
9
+
10
+ body {
11
+ @apply antialiased bg-white;
12
+ }
13
+ }
14
+
15
+ @import 'tw-animate-css';
16
+ @import 'shadcn/tailwind.css';
17
+
18
+ @custom-variant dark (&:is(.dark *));
19
+
20
+ @source "../components/library";
21
+ @source "../components/pages";
22
+
1
23
  @theme inline {
2
24
  --color-background: var(--background);
3
25
  --color-foreground: var(--foreground);
@@ -36,39 +58,26 @@
36
58
  --color-sidebar-border: var(--sidebar-border);
37
59
  --color-sidebar-ring: var(--sidebar-ring);
38
60
 
39
- /* Engine brand palette */
40
- --color-engine-black: #111111;
41
- --color-engine-teal: #5BC8C8;
42
- --color-engine-green: #3DAB5F;
43
- --color-engine-coral: #FF5722;
44
- --color-engine-orange: #F59E0B;
45
- --color-engine-savings: #16A34A;
46
- --color-engine-bg: #F7F8FA;
47
- --color-engine-border: #E5E7EB;
48
- --color-engine-text: #111111;
49
- --color-engine-muted: #6B7280;
50
- --color-engine-label: #9CA3AF;
51
-
52
- /* Engine teal brand palette */
53
- --color-brand-50: #ECFDF9;
54
- --color-brand-100: #D1FAF0;
55
- --color-brand-200: #A7F3E1;
56
- --color-brand-300: #6EE7C8;
57
- --color-brand-400: #34D3AB;
58
- --color-brand-500: #5BC8C8;
59
- --color-brand-600: #0D9488;
60
- --color-brand-700: #0F766E;
61
- --color-brand-800: #115E59;
62
- --color-brand-900: #134E4A;
63
- --color-brand-950: #042F2E;
61
+ /* Brand palette — customize these to match your brand */
62
+ --color-brand-50: #F0F9FF;
63
+ --color-brand-100: #E0F2FE;
64
+ --color-brand-200: #BAE6FD;
65
+ --color-brand-300: #7DD3FC;
66
+ --color-brand-400: #38BDF8;
67
+ --color-brand-500: #0EA5E9;
68
+ --color-brand-600: #0284C7;
69
+ --color-brand-700: #0369A1;
70
+ --color-brand-800: #075985;
71
+ --color-brand-900: #0C4A6E;
72
+ --color-brand-950: #082F49;
64
73
 
65
74
  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
66
75
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
67
76
 
68
- /* Engine border radius tokens */
69
77
  --radius-pill: 9999px;
70
78
  --radius-card: 10px;
71
79
  }
80
+
72
81
  :root {
73
82
  --radius: 0.625rem;
74
83
  --background: oklch(1 0 0);
@@ -103,6 +112,7 @@
103
112
  --sidebar-border: oklch(0.922 0 0);
104
113
  --sidebar-ring: oklch(0.708 0 0);
105
114
  }
115
+
106
116
  .dark {
107
117
  --background: oklch(0.145 0 0);
108
118
  --foreground: oklch(0.985 0 0);
@@ -135,4 +145,79 @@
135
145
  --sidebar-accent-foreground: oklch(0.985 0 0);
136
146
  --sidebar-border: oklch(1 0 0 / 10%);
137
147
  --sidebar-ring: oklch(0.556 0 0);
138
- }
148
+ }
149
+
150
+ @layer base {
151
+ * {
152
+ @apply border-border outline-ring/50;
153
+ }
154
+ body {
155
+ @apply bg-background text-foreground;
156
+ }
157
+ }
158
+
159
+ /*
160
+ * Restore HeroUI theme variables inside the Command Center scope.
161
+ * shadcn redefines --muted, --accent, --accent-foreground with different
162
+ * semantics (bg colors vs text colors). This scope restores HeroUI's values
163
+ * so HeroUI components render correctly.
164
+ */
165
+ .heroui-scope {
166
+ --primary: #000000;
167
+ --primary-foreground: oklch(0.9911 0 0);
168
+ --secondary: #0EA5E9;
169
+ --secondary-foreground: oklch(0.9911 0 0);
170
+ --success: #16A34A;
171
+ --success-foreground: oklch(0.9911 0 0);
172
+ --warning: #F59E0B;
173
+ --warning-foreground: oklch(0.2103 0.0059 285.89);
174
+ --danger: #EF4444;
175
+ --danger-foreground: oklch(0.9911 0 0);
176
+
177
+ --muted: oklch(0.5517 0.0138 285.94);
178
+ --accent: oklch(0.6204 0.195 253.83);
179
+ --accent-foreground: oklch(0.9911 0 0);
180
+ --background: oklch(0.9702 0 0);
181
+ --foreground: oklch(0.2103 0.0059 285.89);
182
+ --default: oklch(94% 0.001 286.375);
183
+ --default-foreground: oklch(0.2103 0.0059 285.89);
184
+ --border: oklch(90% 0.004 286.32);
185
+ --separator: oklch(92% 0.004 286.32);
186
+ --segment: oklch(100% 0 0);
187
+ --segment-foreground: oklch(0.2103 0.0059 285.89);
188
+ --surface: oklch(100% 0 0);
189
+ --surface-foreground: oklch(0.2103 0.0059 285.89);
190
+ --overlay: oklch(100% 0 0);
191
+ --overlay-foreground: oklch(0.2103 0.0059 285.89);
192
+ --focus: oklch(0.6204 0.195 253.83);
193
+ --link: oklch(0.2103 0.0059 285.89);
194
+ }
195
+
196
+ /* ChatBar expanded overlay — horizontal padding so it doesn't hit window edges */
197
+ body > .fixed.inset-x-0.rounded-2xl {
198
+ left: 1.5rem !important;
199
+ right: 1.5rem !important;
200
+ }
201
+
202
+ .dark .heroui-scope,
203
+ .heroui-scope.dark {
204
+ --muted: oklch(70.5% 0.015 286.067);
205
+ --background: oklch(12% 0.005 285.823);
206
+ --foreground: oklch(0.9911 0 0);
207
+ --default: oklch(27.4% 0.006 286.033);
208
+ --default-foreground: oklch(0.9911 0 0);
209
+ --border: oklch(28% 0.006 286.033);
210
+ --separator: oklch(25% 0.006 286.033);
211
+ --segment: oklch(0.3964 0.01 285.93);
212
+ --segment-foreground: oklch(0.9911 0 0);
213
+ --surface: oklch(0.2103 0.0059 285.89);
214
+ --surface-foreground: oklch(0.9911 0 0);
215
+ --overlay: oklch(0.2103 0.0059 285.89);
216
+ --overlay-foreground: oklch(0.9911 0 0);
217
+ --warning: oklch(0.8203 0.1388 76.34);
218
+ --warning-foreground: oklch(0.2103 0.0059 285.89);
219
+ --danger: oklch(0.594 0.1967 24.63);
220
+ --danger-foreground: oklch(0.9911 0 0);
221
+ --focus: oklch(0.6204 0.195 253.83);
222
+ --link: oklch(0.9911 0 0);
223
+ }
@@ -58,36 +58,22 @@
58
58
  --color-sidebar-border: var(--sidebar-border);
59
59
  --color-sidebar-ring: var(--sidebar-ring);
60
60
 
61
- /* Engine brand palette */
62
- --color-engine-black: #111111;
63
- --color-engine-teal: #5BC8C8;
64
- --color-engine-green: #3DAB5F;
65
- --color-engine-coral: #FF5722;
66
- --color-engine-orange: #F59E0B;
67
- --color-engine-savings: #16A34A;
68
- --color-engine-bg: #F7F8FA;
69
- --color-engine-border: #E5E7EB;
70
- --color-engine-text: #111111;
71
- --color-engine-muted: #6B7280;
72
- --color-engine-label: #9CA3AF;
73
-
74
- /* Engine teal brand palette */
75
- --color-brand-50: #ECFDF9;
76
- --color-brand-100: #D1FAF0;
77
- --color-brand-200: #A7F3E1;
78
- --color-brand-300: #6EE7C8;
79
- --color-brand-400: #34D3AB;
80
- --color-brand-500: #5BC8C8;
81
- --color-brand-600: #0D9488;
82
- --color-brand-700: #0F766E;
83
- --color-brand-800: #115E59;
84
- --color-brand-900: #134E4A;
85
- --color-brand-950: #042F2E;
61
+ /* Brand palette — customize these to match your brand */
62
+ --color-brand-50: #F0F9FF;
63
+ --color-brand-100: #E0F2FE;
64
+ --color-brand-200: #BAE6FD;
65
+ --color-brand-300: #7DD3FC;
66
+ --color-brand-400: #38BDF8;
67
+ --color-brand-500: #0EA5E9;
68
+ --color-brand-600: #0284C7;
69
+ --color-brand-700: #0369A1;
70
+ --color-brand-800: #075985;
71
+ --color-brand-900: #0C4A6E;
72
+ --color-brand-950: #082F49;
86
73
 
87
74
  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
88
75
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
89
76
 
90
- /* Engine border radius tokens */
91
77
  --radius-pill: 9999px;
92
78
  --radius-card: 10px;
93
79
  }
@@ -177,16 +163,15 @@
177
163
  * so HeroUI components render correctly.
178
164
  */
179
165
  .heroui-scope {
180
- /* Engine HeroUI theme overrides */
181
166
  --primary: #000000;
182
167
  --primary-foreground: oklch(0.9911 0 0);
183
- --secondary: #5BC8C8;
184
- --secondary-foreground: oklch(0.2103 0.0059 285.89);
168
+ --secondary: #0EA5E9;
169
+ --secondary-foreground: oklch(0.9911 0 0);
185
170
  --success: #16A34A;
186
171
  --success-foreground: oklch(0.9911 0 0);
187
172
  --warning: #F59E0B;
188
173
  --warning-foreground: oklch(0.2103 0.0059 285.89);
189
- --danger: #FF5722;
174
+ --danger: #EF4444;
190
175
  --danger-foreground: oklch(0.9911 0 0);
191
176
 
192
177
  --muted: oklch(0.5517 0.0138 285.94);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schandlergarcia/sf-web-components",
3
- "version": "1.9.88",
3
+ "version": "2.1.0",
4
4
  "description": "Reusable Salesforce web components library with Tailwind CSS v4 and shadcn/ui",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,11 +27,11 @@
27
27
  "files": [
28
28
  "dist",
29
29
  "scripts",
30
- "data",
31
- "assets",
30
+ "brands",
32
31
  "src/templates",
33
32
  "src/components",
34
33
  "src/lib",
34
+ "src/styles",
35
35
  "src/types",
36
36
  "README.md",
37
37
  "INSTALL.md",
@@ -51,7 +51,10 @@
51
51
  "postinstall": "node scripts/postinstall.mjs",
52
52
  "reset:command-center": "bash scripts/reset-command-center.sh",
53
53
  "validate:dashboard": "bash scripts/validate-dashboard.sh",
54
- "graphql:schema": "node scripts/get-graphql-schema.mjs"
54
+ "graphql:schema": "node scripts/get-graphql-schema.mjs",
55
+ "brand:engine": "node node_modules/@schandlergarcia/sf-web-components/scripts/apply-brand.mjs engine",
56
+ "brand:reset": "node node_modules/@schandlergarcia/sf-web-components/scripts/apply-brand.mjs --reset",
57
+ "brand:list": "node node_modules/@schandlergarcia/sf-web-components/scripts/apply-brand.mjs --list"
55
58
  },
56
59
  "peerDependencies": {
57
60
  "@heroicons/react": "^2.0.0",