@fayz-ai/ui 0.19.0 → 0.22.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 (63) hide show
  1. package/dist/{chunk-5NEADAIP.js → chunk-7G3O54CC.js} +140 -16
  2. package/dist/chunk-7G3O54CC.js.map +1 -0
  3. package/dist/{chunk-SB6DWHXI.js → chunk-DHNUZF2X.js} +10 -3
  4. package/dist/chunk-DHNUZF2X.js.map +1 -0
  5. package/dist/{chunk-6YFPPK7X.js → chunk-PQUS22JE.js} +146 -38
  6. package/dist/chunk-PQUS22JE.js.map +1 -0
  7. package/dist/{chunk-ERSX3C7T.js → chunk-SUSW4LSW.js} +37 -6
  8. package/dist/chunk-SUSW4LSW.js.map +1 -0
  9. package/dist/{chunk-5WSKZU7M.js → chunk-ZSOT7KTE.js} +85 -118
  10. package/dist/chunk-ZSOT7KTE.js.map +1 -0
  11. package/dist/dashboard/OnboardingWidget.d.ts +4 -1
  12. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  13. package/dist/dashboard/SidebarOnboarding.d.ts +11 -1
  14. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -1
  15. package/dist/dashboard/index.js +2 -2
  16. package/dist/icons.js +1 -1
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +445 -87
  20. package/dist/index.js.map +1 -1
  21. package/dist/layout/AppShell.d.ts +3 -1
  22. package/dist/layout/AppShell.d.ts.map +1 -1
  23. package/dist/layout/ModulePage.d.ts +13 -0
  24. package/dist/layout/ModulePage.d.ts.map +1 -1
  25. package/dist/layout/SaveBar.d.ts.map +1 -1
  26. package/dist/layout/Sidebar.d.ts +7 -1
  27. package/dist/layout/Sidebar.d.ts.map +1 -1
  28. package/dist/layout/Takeover.d.ts +31 -0
  29. package/dist/layout/Takeover.d.ts.map +1 -0
  30. package/dist/layout/index.d.ts +1 -0
  31. package/dist/layout/index.d.ts.map +1 -1
  32. package/dist/layout/index.js +3 -3
  33. package/dist/primitives/header-tabs.d.ts +23 -1
  34. package/dist/primitives/header-tabs.d.ts.map +1 -1
  35. package/dist/primitives/index.js +3 -3
  36. package/dist/primitives/list-view.d.ts.map +1 -1
  37. package/dist/primitives/page-actions.d.ts.map +1 -1
  38. package/dist/primitives/refresh-button.d.ts.map +1 -1
  39. package/dist/primitives/row-actions.d.ts.map +1 -1
  40. package/dist/primitives/search-select.d.ts +3 -1
  41. package/dist/primitives/search-select.d.ts.map +1 -1
  42. package/dist/primitives/stock-entry-form.d.ts +4 -1
  43. package/dist/primitives/stock-entry-form.d.ts.map +1 -1
  44. package/dist/styles.css +99 -0
  45. package/dist/tour/PracticeOverlay.d.ts +12 -0
  46. package/dist/tour/PracticeOverlay.d.ts.map +1 -0
  47. package/dist/tour/TourSpotlight.d.ts.map +1 -1
  48. package/dist/tour/confetti.d.ts +17 -0
  49. package/dist/tour/confetti.d.ts.map +1 -0
  50. package/dist/tour/index.d.ts +3 -0
  51. package/dist/tour/index.d.ts.map +1 -1
  52. package/dist/tour/practice.store.d.ts +28 -0
  53. package/dist/tour/practice.store.d.ts.map +1 -0
  54. package/dist/tour/tour.store.d.ts +4 -0
  55. package/dist/tour/tour.store.d.ts.map +1 -1
  56. package/dist/tour/types.d.ts +17 -0
  57. package/dist/tour/types.d.ts.map +1 -1
  58. package/package.json +2 -2
  59. package/dist/chunk-5NEADAIP.js.map +0 -1
  60. package/dist/chunk-5WSKZU7M.js.map +0 -1
  61. package/dist/chunk-6YFPPK7X.js.map +0 -1
  62. package/dist/chunk-ERSX3C7T.js.map +0 -1
  63. package/dist/chunk-SB6DWHXI.js.map +0 -1
@@ -1,8 +1,10 @@
1
- import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody } from './chunk-6YFPPK7X.js';
1
+ import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody } from './chunk-PQUS22JE.js';
2
2
  import { cn, Button } from './chunk-OKZ6WQB3.js';
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
- import * as React from 'react';
5
- import { PanelRightOpen, PanelRightClose, PanelRight } from 'lucide-react';
4
+ import * as React2 from 'react';
5
+ import { createContext, useContext, useState, useRef, useEffect, useCallback } from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import { X, PanelRightOpen, PanelRightClose, PanelRight } from 'lucide-react';
6
8
 
7
9
  function BootSpinner({ className }) {
8
10
  return /* @__PURE__ */ jsx(
@@ -32,27 +34,149 @@ function AppShellSkeleton({ label, className }) {
32
34
  );
33
35
  }
34
36
  AppShellSkeleton.displayName = "AppShellSkeleton";
37
+ var TakeoverCloseContext = createContext(() => {
38
+ });
39
+ function useTakeoverClose() {
40
+ return useContext(TakeoverCloseContext);
41
+ }
42
+ var EXIT_MS = 220;
43
+ function Takeover({
44
+ open,
45
+ onClose,
46
+ label,
47
+ origin,
48
+ closeLabel = "Fechar",
49
+ route,
50
+ corner,
51
+ children
52
+ }) {
53
+ const [phase, setPhase] = useState(open ? "open" : "closed");
54
+ const panelRef = useRef(null);
55
+ const pushed = useRef(false);
56
+ const prevUrl = useRef("");
57
+ useEffect(() => {
58
+ if (open) {
59
+ setPhase((p) => p === "closed" || p === "closing" ? "opening" : p);
60
+ const id = requestAnimationFrame(() => setPhase("open"));
61
+ return () => cancelAnimationFrame(id);
62
+ }
63
+ setPhase((p) => p === "closed" ? "closed" : "closing");
64
+ const t = setTimeout(() => setPhase("closed"), EXIT_MS);
65
+ return () => clearTimeout(t);
66
+ }, [open]);
67
+ useEffect(() => {
68
+ if (phase === "closed") return;
69
+ const prev = document.body.style.overflow;
70
+ document.body.style.overflow = "hidden";
71
+ return () => {
72
+ document.body.style.overflow = prev;
73
+ };
74
+ }, [phase]);
75
+ useEffect(() => {
76
+ if (!open) return;
77
+ prevUrl.current = location.href;
78
+ history.pushState({ ...history.state, fzTakeover: label }, "", route ? `#${route}` : void 0);
79
+ pushed.current = true;
80
+ const onPop = () => {
81
+ pushed.current = false;
82
+ onClose();
83
+ };
84
+ window.addEventListener("popstate", onPop);
85
+ return () => window.removeEventListener("popstate", onPop);
86
+ }, [open, label, route, onClose]);
87
+ const close = useCallback(() => {
88
+ if (pushed.current) {
89
+ pushed.current = false;
90
+ if (prevUrl.current) history.replaceState(history.state, "", prevUrl.current);
91
+ }
92
+ onClose();
93
+ }, [onClose]);
94
+ useEffect(() => {
95
+ if (!open) return;
96
+ const onKey = (e) => {
97
+ if (e.key === "Escape" && e.shiftKey) {
98
+ e.preventDefault();
99
+ close();
100
+ }
101
+ };
102
+ window.addEventListener("keydown", onKey);
103
+ return () => window.removeEventListener("keydown", onKey);
104
+ }, [open, close]);
105
+ useEffect(() => {
106
+ if (phase === "open") panelRef.current?.focus({ preventScroll: true });
107
+ }, [phase]);
108
+ if (phase === "closed") return null;
109
+ const active = phase === "open";
110
+ const originStyle = origin ? { transformOrigin: `${origin.x}px ${origin.y}px` } : void 0;
111
+ return createPortal(
112
+ /* @__PURE__ */ jsx(TakeoverCloseContext.Provider, { value: close, children: /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[120]", role: "dialog", "aria-modal": "true", "aria-label": label, children: [
113
+ /* @__PURE__ */ jsx(
114
+ "div",
115
+ {
116
+ "aria-hidden": true,
117
+ className: cn(
118
+ "absolute inset-0 bg-black/60 backdrop-blur-[2px] transition-opacity duration-200",
119
+ active ? "opacity-100" : "opacity-0"
120
+ )
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsx(
124
+ "div",
125
+ {
126
+ ref: panelRef,
127
+ tabIndex: -1,
128
+ style: originStyle,
129
+ className: cn(
130
+ "saas-takeover-panel absolute inset-0 overflow-hidden bg-background outline-none",
131
+ active ? "saas-takeover-in" : "saas-takeover-out"
132
+ ),
133
+ children
134
+ }
135
+ ),
136
+ /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute right-0 top-0 z-10 flex items-center gap-2 p-3", children: [
137
+ corner,
138
+ /* @__PURE__ */ jsx(
139
+ "button",
140
+ {
141
+ type: "button",
142
+ onClick: close,
143
+ "aria-label": closeLabel,
144
+ title: `${closeLabel} \xB7 Shift+Esc`,
145
+ className: cn(
146
+ "fz-tap pointer-events-auto flex h-10 w-10 items-center justify-center rounded-full",
147
+ "bg-black/40 text-white/80 backdrop-blur transition-colors",
148
+ "hover:bg-black/60 hover:text-white",
149
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60"
150
+ ),
151
+ children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
152
+ }
153
+ )
154
+ ] })
155
+ ] }) }),
156
+ document.body
157
+ );
158
+ }
35
159
  var EMPTY = [];
36
- var PageTrailContext = React.createContext(EMPTY);
160
+ var PageTrailContext = React2.createContext(EMPTY);
37
161
  function PageTrail({
38
162
  label,
39
163
  href,
40
164
  onNavigate,
41
165
  children
42
166
  }) {
43
- const parent = React.useContext(PageTrailContext);
44
- const trail = React.useMemo(
167
+ const parent = React2.useContext(PageTrailContext);
168
+ const trail = React2.useMemo(
45
169
  () => [...parent, { label, href, onNavigate }],
46
170
  [parent, label, href, onNavigate]
47
171
  );
48
172
  return /* @__PURE__ */ jsx(PageTrailContext.Provider, { value: trail, children });
49
173
  }
50
174
  function usePageTrail() {
51
- return React.useContext(PageTrailContext);
175
+ return React2.useContext(PageTrailContext);
52
176
  }
53
177
  function usePageTrailParent(href) {
54
- const trail = React.useContext(PageTrailContext);
55
- return React.useMemo(() => {
178
+ const trail = React2.useContext(PageTrailContext);
179
+ return React2.useMemo(() => {
56
180
  const above = href ? trail.filter((c) => c.href !== href) : trail;
57
181
  return above[above.length - 1];
58
182
  }, [trail, href]);
@@ -61,7 +185,7 @@ function navigateToCrumb(crumb) {
61
185
  if (crumb.onNavigate) crumb.onNavigate();
62
186
  else window.location.hash = crumb.href;
63
187
  }
64
- var ContentSplitContext = React.createContext(null);
188
+ var ContentSplitContext = React2.createContext(null);
65
189
  function ContentSplit({
66
190
  children,
67
191
  aside,
@@ -74,10 +198,10 @@ function ContentSplit({
74
198
  defaultCollapsed = false,
75
199
  className
76
200
  }) {
77
- const [internalOpen, setInternalOpen] = React.useState(false);
201
+ const [internalOpen, setInternalOpen] = React2.useState(false);
78
202
  const open = asideOpen ?? internalOpen;
79
203
  const setOpen = onAsideOpenChange ?? setInternalOpen;
80
- const [collapsed, setCollapsed] = React.useState(collapsible && defaultCollapsed);
204
+ const [collapsed, setCollapsed] = React2.useState(collapsible && defaultCollapsed);
81
205
  return /* @__PURE__ */ jsxs(ContentSplitContext.Provider, { value: { open, setOpen }, children: [
82
206
  /* @__PURE__ */ jsxs(
83
207
  "div",
@@ -129,7 +253,7 @@ function ContentSplit({
129
253
  ] });
130
254
  }
131
255
  function ContentSplitTrigger({ label, iconOnly, className }) {
132
- const ctx = React.useContext(ContentSplitContext);
256
+ const ctx = React2.useContext(ContentSplitContext);
133
257
  if (!ctx) return null;
134
258
  return /* @__PURE__ */ jsxs(
135
259
  Button,
@@ -147,6 +271,6 @@ function ContentSplitTrigger({ label, iconOnly, className }) {
147
271
  );
148
272
  }
149
273
 
150
- export { AppShellSkeleton, ContentSplit, ContentSplitTrigger, PageTrail, navigateToCrumb, usePageTrail, usePageTrailParent };
151
- //# sourceMappingURL=chunk-5NEADAIP.js.map
152
- //# sourceMappingURL=chunk-5NEADAIP.js.map
274
+ export { AppShellSkeleton, ContentSplit, ContentSplitTrigger, PageTrail, Takeover, navigateToCrumb, usePageTrail, usePageTrailParent, useTakeoverClose };
275
+ //# sourceMappingURL=chunk-7G3O54CC.js.map
276
+ //# sourceMappingURL=chunk-7G3O54CC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/layout/AppShellSkeleton.tsx","../src/layout/Takeover.tsx","../src/layout/page-trail.tsx","../src/layout/ContentSplit.tsx"],"names":["jsx","jsxs","React3"],"mappings":"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","file":"chunk-7G3O54CC.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../lib/cn'\n\n// ---------------------------------------------------------------------------\n// AppShellSkeleton — what the admin shows while it is still booting (session\n// restore, plugin runtime, first paint).\n//\n// It used to draw the SHAPE of the shell: rail, header band, tiles, table. The\n// idea was that the app would resolve into its own outline. What it did in\n// practice was promise a specific screen and then contradict it — the outline\n// is a dashboard, and half the time you were opening something else — and the\n// pulsing bars read as content that failed to load rather than content on its\n// way. Worse, it made the wait look LONGER: a page of fake rows holds the eye,\n// so every extra frame of it registers.\n//\n// One spinner on the rail's own color says exactly as much (the app is coming)\n// and nothing false. It also matches the HTML boot screen the Vite plugin\n// injects (see @fayz-ai/sdk boot-skeleton), so the whole cold load is one\n// continuous image — same background, same spinner, in the same place — from\n// first paint to mounted app, with nothing swapping underneath.\n// ---------------------------------------------------------------------------\n\nexport interface AppShellSkeletonProps {\n /** Kept for API compatibility. The boot screen no longer draws a shell shape,\n * so every layout gets the same one. */\n variant?: 'sidebar' | 'topbar' | 'minimal'\n /** Kept for API compatibility; the boot screen has no content frame. */\n contentFrame?: boolean\n /** Kept for API compatibility; the boot screen shows no logo. */\n logo?: React.ReactNode\n /** What is loading, for screen readers. */\n label: string\n className?: string\n}\n\n/** Ring spinner in the page's foreground tone. Static under reduced motion —\n * the ring alone still reads as \"busy\", a frozen spinner reads as \"stuck\". */\nexport function BootSpinner({ className }: { className?: string }) {\n return (\n <span\n aria-hidden\n className={cn(\n 'block h-7 w-7 animate-spin rounded-full border-2 border-foreground/20 border-t-foreground/70',\n 'motion-reduce:animate-none motion-reduce:border-t-foreground/20 motion-reduce:animate-pulse',\n className,\n )}\n />\n )\n}\n\nexport function AppShellSkeleton({ label, className }: AppShellSkeletonProps) {\n return (\n <div\n role=\"status\"\n aria-busy=\"true\"\n className={cn('fz-viewport-h flex items-center justify-center overflow-hidden bg-background', className)}\n >\n <span className=\"sr-only\">{label}</span>\n <BootSpinner />\n </div>\n )\n}\nAppShellSkeleton.displayName = 'AppShellSkeleton'\n","import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { X } from 'lucide-react'\nimport { cn } from '../lib/cn'\n\n/**\n * A full-viewport surface that covers the shell — rail, topbar and page — and\n * gives it back untouched on close.\n *\n * Not a route: the page underneath stays MOUNTED, so a filtered list, a scroll\n * position or a half-typed form survives a trip through the counter. That is\n * the whole reason this is not `immersive: true` on a route, which unmounts the\n * page you left and re-runs its queries on the way back.\n *\n * The back button closes it. Opening pushes a history entry with no URL change,\n * so `popstate` reads as \"leave this mode\" instead of navigating the page under\n * the takeover — which is what a browser Back would otherwise do while the\n * operator can only see the takeover.\n *\n * `Esc` does NOT close: an operator surface owns that key (it clears the\n * command field). The way out is the corner control, or Shift+Esc for the\n * keyboard.\n */\n\n/**\n * The way out, for anything rendered inside a takeover.\n *\n * A surface that offers its own exit — the counter's Balcão ⇄ Retaguarda switch\n * lives in the POS's own rail — needs the SAME close the corner X uses: the one\n * that pops the history entry the takeover pushed. A plain `setOpen(false)`\n * leaves that entry behind and the next Back press goes nowhere.\n */\nconst TakeoverCloseContext = createContext<() => void>(() => {})\nexport function useTakeoverClose(): () => void {\n return useContext(TakeoverCloseContext)\n}\n\nexport interface TakeoverProps {\n open: boolean\n onClose: () => void\n /** Accessible name for the dialog. */\n label: string\n /** Point the panel grows from — usually the rect of the row that opened it. */\n origin?: { x: number; y: number } | null\n closeLabel?: string\n /**\n * Hash path the URL wears while this is open (e.g. `/pos`), so a refresh\n * comes back to the takeover instead of to the page under it.\n *\n * `pushState` does not emit `hashchange`, which is exactly what makes this\n * safe: the URL says where you are without the hash router unmounting the\n * page underneath. Closing goes back, and THAT does emit it — the router\n * lands on the path it was already showing.\n *\n * The host is responsible for reopening on a cold load at this path.\n */\n route?: string\n /** Extra chrome beside the close button (terminal name, operator, clock). */\n corner?: React.ReactNode\n children: React.ReactNode\n}\n\ntype Phase = 'closed' | 'opening' | 'open' | 'closing'\n\nconst EXIT_MS = 220\n\nexport function Takeover({\n open, onClose, label, origin, closeLabel = 'Fechar', route, corner, children,\n}: TakeoverProps) {\n const [phase, setPhase] = useState<Phase>(open ? 'open' : 'closed')\n const panelRef = useRef<HTMLDivElement>(null)\n // The URL this replaced, and whether the entry it pushed is still there.\n // Closing puts the address back rather than counting history entries — a\n // count is wrong the moment anything else touches history in between.\n const pushed = useRef(false)\n const prevUrl = useRef('')\n\n useEffect(() => {\n if (open) {\n setPhase((p) => (p === 'closed' || p === 'closing' ? 'opening' : p))\n const id = requestAnimationFrame(() => setPhase('open'))\n return () => cancelAnimationFrame(id)\n }\n setPhase((p) => (p === 'closed' ? 'closed' : 'closing'))\n const t = setTimeout(() => setPhase('closed'), EXIT_MS)\n return () => clearTimeout(t)\n }, [open])\n\n // Body scroll lock — the takeover scrolls internally, and a shell that keeps\n // scrolling behind it moves the page you are meant to come back to.\n useEffect(() => {\n if (phase === 'closed') return\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n return () => { document.body.style.overflow = prev }\n }, [phase])\n\n useEffect(() => {\n if (!open) return\n prevUrl.current = location.href\n history.pushState({ ...history.state, fzTakeover: label }, '', route ? `#${route}` : undefined)\n pushed.current = true\n const onPop = () => { pushed.current = false; onClose() }\n window.addEventListener('popstate', onPop)\n return () => window.removeEventListener('popstate', onPop)\n }, [open, label, route, onClose])\n\n const close = useCallback(() => {\n // `replaceState`, not `back()`: the address returns to exactly what it was,\n // and the router — which never saw the push, since pushState emits no\n // `hashchange` — is already showing that page. Going back instead depends\n // on the pushed entry still being the top one, which nothing guarantees.\n if (pushed.current) {\n pushed.current = false\n if (prevUrl.current) history.replaceState(history.state, '', prevUrl.current)\n }\n onClose()\n }, [onClose])\n\n useEffect(() => {\n if (!open) return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && e.shiftKey) { e.preventDefault(); close() }\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [open, close])\n\n // Focus lands inside on arrival; without it the keyboard is still in the rail\n // and the first shortcut goes to the page nobody can see.\n useEffect(() => {\n if (phase === 'open') panelRef.current?.focus({ preventScroll: true })\n }, [phase])\n\n if (phase === 'closed') return null\n\n const active = phase === 'open'\n const originStyle = origin\n ? { transformOrigin: `${origin.x}px ${origin.y}px` }\n : undefined\n\n return createPortal(\n <TakeoverCloseContext.Provider value={close}>\n <div className=\"fixed inset-0 z-[120]\" role=\"dialog\" aria-modal=\"true\" aria-label={label}>\n <div\n aria-hidden\n className={cn(\n 'absolute inset-0 bg-black/60 backdrop-blur-[2px] transition-opacity duration-200',\n active ? 'opacity-100' : 'opacity-0',\n )}\n />\n <div\n ref={panelRef}\n tabIndex={-1}\n style={originStyle}\n className={cn(\n 'saas-takeover-panel absolute inset-0 overflow-hidden bg-background outline-none',\n active ? 'saas-takeover-in' : 'saas-takeover-out',\n )}\n >\n {children}\n </div>\n\n {/* Above the panel, not inside it: the surface under the takeover draws\n its own chrome and must not have to reserve a corner for ours. */}\n <div className=\"pointer-events-none absolute right-0 top-0 z-10 flex items-center gap-2 p-3\">\n {corner}\n <button\n type=\"button\"\n onClick={close}\n aria-label={closeLabel}\n title={`${closeLabel} · Shift+Esc`}\n className={cn(\n 'fz-tap pointer-events-auto flex h-10 w-10 items-center justify-center rounded-full',\n 'bg-black/40 text-white/80 backdrop-blur transition-colors',\n 'hover:bg-black/60 hover:text-white',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60',\n )}\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n </div>\n </TakeoverCloseContext.Provider>,\n document.body,\n )\n}\n","import * as React from 'react'\n\n// ---------------------------------------------------------------------------\n// PageTrail — quem é o PAI da tela que está desenhando agora.\n//\n// Uma migalha (\"← Entrega / Embalagens\") precisa de duas coisas que moram em\n// lugares diferentes: o nome do nível de cima, que só o container sabe, e o\n// nome do nível atual, que só a folha sabe. Sem um caminho entre os dois cada\n// container desenhava a própria seta \"para não perder o caminho de volta\" — e\n// foi assim que Configurações ficou com dois cabeçalhos empilhados: um da\n// barra da shell (\"Configurações\") e um escrito à mão dentro do plugin\n// (\"← Entrega\"), desalinhados, para uma coisa só.\n//\n// Aqui o container apenas DECLARA o nível dele. Quem desenha é sempre a folha,\n// uma vez só, pelo mesmo PageHeader que o resto do app usa — uma seta na tela,\n// nunca duas.\n// ---------------------------------------------------------------------------\n\nexport interface PageTrailCrumb {\n /** Nome do nível — a palavra antes da barra para quem vem abaixo. */\n label: string\n /** Rota (hash) deste nível. É também a IDENTIDADE dele: uma tela cuja rota é\n * igual à do nível não é filha dele, é ele — sem isso a lista de Locais,\n * que É a aba, viraria \"← Locais / Locais\". */\n href: string\n /** Como voltar. Sem isso, a própria rota. */\n onNavigate?: () => void\n}\n\nconst EMPTY: PageTrailCrumb[] = []\nconst PageTrailContext = React.createContext<PageTrailCrumb[]>(EMPTY)\n\n/** Declara um nível para tudo que renderizar abaixo. */\nexport function PageTrail({\n label,\n href,\n onNavigate,\n children,\n}: PageTrailCrumb & { children: React.ReactNode }) {\n const parent = React.useContext(PageTrailContext)\n // Identidade estável: a folha memoiza o nó do cabeçalho a partir daqui, e um\n // array novo a cada render faria a reivindicação da barra recomeçar sem fim.\n const trail = React.useMemo(\n () => [...parent, { label, href, onNavigate }],\n [parent, label, href, onNavigate],\n )\n return <PageTrailContext.Provider value={trail}>{children}</PageTrailContext.Provider>\n}\n\nexport function usePageTrail(): PageTrailCrumb[] {\n return React.useContext(PageTrailContext)\n}\n\n/**\n * O nível imediatamente acima de `href`, ou undefined quando não há trilha —\n * fora de Configurações a página segue sem migalha, como sempre foi.\n */\nexport function usePageTrailParent(href?: string): PageTrailCrumb | undefined {\n const trail = React.useContext(PageTrailContext)\n return React.useMemo(() => {\n const above = href ? trail.filter((c) => c.href !== href) : trail\n return above[above.length - 1]\n }, [trail, href])\n}\n\nexport function navigateToCrumb(crumb: PageTrailCrumb): void {\n if (crumb.onNavigate) crumb.onNavigate()\n else window.location.hash = crumb.href\n}\n","import * as React from 'react'\nimport { PanelRight, PanelRightClose, PanelRightOpen } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Button } from '../primitives/button'\nimport {\n Sheet, SheetContent, SheetHeader, SheetBody, SheetTitle, SheetDescription,\n} from '../primitives/sheet'\n\n// ---------------------------------------------------------------------------\n// ContentSplit — main content with a right-aligned companion panel, mobile\n// first. Below `lg` the aside lives in a right Sheet (opened by a trigger the\n// host places wherever fits — typically SubpageHeader actions, via\n// <ContentSplitTrigger/>). From `lg` up it docks as a sticky right column.\n//\n// Pairs with SubpageHeader/ModulePage: the page keeps its own back-button\n// header; ContentSplit only owns the columns below it. Reuse for any\n// \"document + operational panel\" page (script + shooting checklist, form +\n// help, detail + activity feed).\n// ---------------------------------------------------------------------------\n\ninterface ContentSplitContextValue {\n open: boolean\n setOpen: (open: boolean) => void\n}\n\nconst ContentSplitContext = React.createContext<ContentSplitContextValue | null>(null)\n\nexport interface ContentSplitProps {\n /** Main column (the document). */\n children: React.ReactNode\n /** Companion panel content (the checklist / help / activity). */\n aside: React.ReactNode\n /** Panel title — Sheet header on mobile, card header on desktop. */\n asideTitle: React.ReactNode\n /** Optional subtitle under the title. */\n asideDescription?: React.ReactNode\n /** Desktop column width (defaults to 20rem). */\n asideWidth?: string\n /** Controlled mobile-sheet state; uncontrolled when omitted. */\n asideOpen?: boolean\n onAsideOpenChange?: (open: boolean) => void\n /** Desktop column can collapse into a slim reopen rail. */\n collapsible?: boolean\n /** Initial desktop collapsed state (e.g. expand only on the relevant day). */\n defaultCollapsed?: boolean\n className?: string\n}\n\nexport function ContentSplit({\n children,\n aside,\n asideTitle,\n asideDescription,\n asideWidth = '20rem',\n asideOpen,\n onAsideOpenChange,\n collapsible = false,\n defaultCollapsed = false,\n className,\n}: ContentSplitProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const open = asideOpen ?? internalOpen\n const setOpen = onAsideOpenChange ?? setInternalOpen\n const [collapsed, setCollapsed] = React.useState(collapsible && defaultCollapsed)\n\n return (\n <ContentSplitContext.Provider value={{ open, setOpen }}>\n <div\n className={cn('lg:grid lg:items-start lg:gap-6', className)}\n style={{ gridTemplateColumns: `minmax(0, 1fr) ${collapsed ? 'auto' : asideWidth}` }}\n >\n <div className=\"min-w-0\">{children}</div>\n\n {/* Desktop: docked sticky column (or slim reopen rail when collapsed) */}\n <aside className=\"hidden lg:block lg:sticky lg:top-4\">\n {collapsed ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setCollapsed(false)}\n className=\"h-9 w-9 p-0\"\n aria-label={typeof asideTitle === 'string' ? asideTitle : undefined}\n title={typeof asideTitle === 'string' ? asideTitle : undefined}\n >\n <PanelRightOpen className=\"h-4 w-4\" />\n </Button>\n ) : (\n <div className=\"rounded-card border border-border bg-card\">\n <div className=\"flex items-start justify-between gap-2 border-b border-border px-4 py-3\">\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-foreground\">{asideTitle}</p>\n {asideDescription && (\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{asideDescription}</p>\n )}\n </div>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"rounded p-1 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground\"\n aria-label=\"collapse\"\n >\n <PanelRightClose className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n <div className=\"p-4\">{aside}</div>\n </div>\n )}\n </aside>\n </div>\n\n {/* Mobile: right sheet */}\n <div className=\"lg:hidden\">\n <Sheet open={open} onOpenChange={setOpen}>\n <SheetContent width=\"max-w-sm\">\n <SheetHeader>\n <SheetTitle>{asideTitle}</SheetTitle>\n {asideDescription && <SheetDescription>{asideDescription}</SheetDescription>}\n </SheetHeader>\n <SheetBody>{aside}</SheetBody>\n </SheetContent>\n </Sheet>\n </div>\n </ContentSplitContext.Provider>\n )\n}\n\nexport interface ContentSplitTriggerProps {\n /** Accessible label; also the visible text unless `iconOnly`. */\n label: React.ReactNode\n iconOnly?: boolean\n className?: string\n}\n\n/** Opens the mobile aside sheet. Renders nothing from `lg` up (the panel is\n * already docked). Place inside SubpageHeader `actions` or any toolbar. */\nexport function ContentSplitTrigger({ label, iconOnly, className }: ContentSplitTriggerProps) {\n const ctx = React.useContext(ContentSplitContext)\n if (!ctx) return null\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => ctx.setOpen(true)}\n className={cn('lg:hidden', className)}\n aria-label={typeof label === 'string' ? label : undefined}\n >\n <PanelRight className={cn('h-4 w-4', !iconOnly && 'mr-1.5')} />\n {!iconOnly && label}\n </Button>\n )\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { Zap, XCircle, X, Wrench, Workflow, Wheat, Warehouse, Wallet, UtensilsCrossed, Upload, WandSparkles, Utensils, UsersRound, Users, UserX, UserPlus, UserCog, UserCheck, User, Truck, Trophy, TrendingUp, TrendingDown, TreePalm, ToggleLeft, Timer, Target, Tags, TableProperties, Tag, Star, Sparkles, Soup, SlidersHorizontal, Sigma, ShoppingCart, ShoppingBag, ShieldCheck, Shield, Settings, Send, Search, Scale, Ruler, RotateCw, RotateCcw, Repeat, Receipt, Radio, Puzzle, PlusCircle, Plus, Plug, PieChart, Phone, Percent, Pencil, PawPrint, PartyPopper, Palette, PackageCheck, Package, Newspaper, Music, MousePointerClick, MoreHorizontal, Mic, MessageSquare, MessageCircle, Megaphone, MapPin, Map, Mail, LogIn, Lock, ListPlus, ListMusic, ListChecks, List, Link, LineChart, LeafyGreen, Leaf, LayoutTemplate, LayoutDashboard, Layers, Landmark, Instagram, Inbox, Images, Image, Home, FolderTree, Hourglass, Heart, Handshake, HandCoins, GraduationCap, Globe, Gift, Gauge, FolderOpen, Flame, Filter, FileText, FileDown, FileCheck2, Eye, ExternalLink, Egg, DoorOpen, DollarSign, Dog, Disc3, Database, CreditCard, CookingPot, Contact, Compass, Command, Clock3, Clock, ClipboardList, ClipboardCheck, Clapperboard, CircleDollarSign, CircleCheck, Circle, ChevronsUpDown, ChevronDown, ChefHat, CheckSquare, CheckCircle, Check, Cat, Camera, CalendarX, CalendarRange, CalendarPlus, CalendarDays, CalendarClock, CalendarCheck2, CalendarCheck, Calendar, Building2, Briefcase, Boxes, Box, BookOpenCheck, BookOpen, Bike, Bell, BarChart3, Banknote, Ban, BadgeDollarSign, Award, ArrowUpRight, ArrowUpCircle, ArrowLeftRight, ArrowDownRight, ArrowDownCircle, Apple, AlertTriangle, Activity } from 'lucide-react';
3
+ import { Zap, XCircle, X, Wrench, Workflow, Wheat, Warehouse, Wallet, UtensilsCrossed, Upload, WandSparkles, Utensils, UsersRound, Users, UserX, UserPlus, UserCog, UserCheck, User, Truck, Trophy, TrendingUp, TrendingDown, TreePalm, ToggleLeft, Timer, Ticket, Target, Tags, TableProperties, Tag, Store, Star, Sparkles, Soup, Smartphone, SlidersHorizontal, Sigma, ShoppingCart, ShoppingBag, ShieldCheck, Shield, Settings, Send, Search, ScanLine, Scale, Ruler, RotateCw, RotateCcw, Repeat, Receipt, Radio, Puzzle, PlusCircle, Plus, Plug, PieChart, Phone, Percent, Pencil, PawPrint, PartyPopper, Palette, PackageCheck, Package, Newspaper, Music, MousePointerClick, MoreHorizontal, Mic, MessageSquare, MessageCircle, Megaphone, MapPin, Map, Mail, LogIn, Lock, ListPlus, ListMusic, ListChecks, List, Link, LineChart, LeafyGreen, Leaf, LayoutTemplate, LayoutDashboard, Layers, Landmark, Instagram, Inbox, Images, Image, Home, FolderTree, Hourglass, Heart, Handshake, HandCoins, GraduationCap, Globe, GlassWater, Gift, Gauge, FolderOpen, Flame, Filter, FileText, FileDown, FileCheck2, Eye, ExternalLink, Egg, DoorOpen, DollarSign, Dog, Disc3, Database, CreditCard, CookingPot, Contact, Compass, Command, Clock3, Clock, ClipboardList, ClipboardCheck, Clapperboard, CircleDollarSign, CircleCheck, Circle, ChevronsUpDown, ChevronDown, ChefHat, CheckSquare, CheckCircle, Check, Cat, Camera, CalendarX, CalendarRange, CalendarPlus, CalendarDays, CalendarClock, CalendarCheck2, CalendarCheck, Calendar, Calculator, Building2, Briefcase, Boxes, Box, BookOpenCheck, BookOpen, Bike, Bell, Beer, BarChart3, Banknote, Ban, BadgeDollarSign, Award, ArrowUpRight, ArrowUpCircle, ArrowLeftRight, ArrowDownRight, ArrowDownCircle, Apple, AlertTriangle, Activity } from 'lucide-react';
4
4
 
5
5
  // src/primitives/brand-marks.tsx
6
6
  var ChefControlMark = React.forwardRef(
@@ -29,6 +29,7 @@ var registry = {
29
29
  Ban,
30
30
  Banknote,
31
31
  BarChart3,
32
+ Beer,
32
33
  Bell,
33
34
  Bike,
34
35
  BookOpen,
@@ -37,6 +38,7 @@ var registry = {
37
38
  Boxes,
38
39
  Briefcase,
39
40
  Building2,
41
+ Calculator,
40
42
  Calendar,
41
43
  CalendarCheck,
42
44
  CalendarCheck2,
@@ -82,6 +84,7 @@ var registry = {
82
84
  FolderOpen,
83
85
  Gauge,
84
86
  Gift,
87
+ GlassWater,
85
88
  Globe,
86
89
  GraduationCap,
87
90
  HandCoins,
@@ -139,6 +142,7 @@ var registry = {
139
142
  RotateCw,
140
143
  Ruler,
141
144
  Scale,
145
+ ScanLine,
142
146
  Search,
143
147
  Send,
144
148
  Settings,
@@ -148,13 +152,16 @@ var registry = {
148
152
  ShoppingCart,
149
153
  Sigma,
150
154
  SlidersHorizontal,
155
+ Smartphone,
151
156
  Soup,
152
157
  Sparkles,
153
158
  Star,
159
+ Store,
154
160
  Tag,
155
161
  TableProperties,
156
162
  Tags,
157
163
  Target,
164
+ Ticket,
158
165
  Timer,
159
166
  ToggleLeft,
160
167
  TreePalm,
@@ -195,5 +202,5 @@ function getLucideIcon(name) {
195
202
  var ICON_MAP = registry;
196
203
 
197
204
  export { BRAND_MARKS, ChefControlMark, ICON_MAP, getLucideIcon, registerIcons };
198
- //# sourceMappingURL=chunk-SB6DWHXI.js.map
199
- //# sourceMappingURL=chunk-SB6DWHXI.js.map
205
+ //# sourceMappingURL=chunk-DHNUZF2X.js.map
206
+ //# sourceMappingURL=chunk-DHNUZF2X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/primitives/brand-marks.tsx","../src/icons.ts"],"names":["ChefControlMark"],"mappings":"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","file":"chunk-DHNUZF2X.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\n\n// ---------------------------------------------------------------------------\n// The Control family's own product marks.\n//\n// Every other tile in the app switcher is a lucide glyph named by a row in\n// `app.apps`, which is fine for a product that has no mark of its own. It is\n// not fine for one that does: ChefControl's symbol has weight hierarchy — thin\n// crown, heavy base, the same contrast as the logotype beside it — and lucide's\n// `ChefHat` draws the same object at constant stroke. The launcher is where a\n// product is recognised rather than read, so the row that shows a stand-in is\n// the row that says \"this app has no brand\".\n//\n// They live in the registry rather than in each app because the switcher lists\n// SIBLINGS: StoreControl draws the Chef row too, and a mark that only the app\n// itself owns would leave the same product looking like two different products\n// depending on which window you opened the menu from.\n//\n// `fill=\"currentColor\"` and no stroke: the tile decides the ink (see AppMark),\n// the same way a surface decides the colour of the text beside it — one drawing\n// for the gold tile, the rail and the login card, with no per-surface file and\n// no `filter: invert`, which chews the anti-aliased edge.\n// ---------------------------------------------------------------------------\n\n/**\n * Typed as a lucide icon so it can sit in the same registry: the props a mark\n * actually reads are `className` and `style`, and the stroke props the callers\n * pass mean nothing to a filled path — harmless, and not worth a second\n * resolver to avoid.\n */\nexport const ChefControlMark = React.forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>(\n function ChefControlMark(props, ref) {\n return (\n // The viewBox is the symbol's ink box, not the 1080 square of the source\n // file: cropped, the hat centres in a tile instead of floating in padding.\n <svg ref={ref} viewBox=\"140.2 147.83 799.59 784.35\" fill=\"currentColor\" aria-hidden {...props}>\n <path d=\"M871.42,305.72c-8.6-6.71-17.86-12.68-27.66-17.78-25.93-13.54-55.59-21.23-87.13-21.23-8.66,0-17.18.58-25.51,1.7-33.22-70.59-106.31-120.58-191.12-120.58s-157.93,49.99-191.12,120.61h-.03c-8.33-1.15-16.85-1.73-25.51-1.73-32.62,0-63.27,8.24-89.79,22.68-9.74,5.27-18.94,11.41-27.45,18.27-40.27,32.41-65.9,81.19-65.9,135.73,0,93.23,74.89,169.64,169.82,176.21,3.88,33.85,5.91,68.69,5.91,104.24,0,45.93-3.38,90.64-9.77,133.6-2,13.45-4.3,26.71-6.87,39.79,13.5-3.43,27.27-6.6,41.25-9.42,62.07-12.68,128.53-19.54,197.6-19.54s135.5,6.86,197.57,19.54c13.98,2.82,27.75,5.96,41.25,9.42-2.57-13.08-4.87-26.33-6.87-39.79-6.39-42.96-9.77-87.67-9.77-133.6,0-35.47,2-70.21,5.89-104.01,96.69-4.84,173.58-82,173.58-176.44,0-55.64-26.67-105.28-68.37-137.66ZM771.38,570.43c-4.87.51-9.77.75-14.76.75-8.36,0-16.55-.72-24.52-2.09-1.94,12.64-3.64,25.42-5.11,38.35-4.03,35.73-6.12,72.47-6.12,110.02,0,44.3,2.93,173.01,8.48,214.69-60.25-12.28-124.5-18.91-191.2-18.91s-130.99,6.63-191.24,18.94c5.56-41.67,8.48-170.42,8.48-214.71,0-37.34-2.09-73.9-6.06-109.45-1.43-12.93-3.14-25.72-5.11-38.35-6.81,1.02-13.8,1.52-20.88,1.52-6.27,0-12.46-.39-18.52-1.19-71.03-9.08-125.94-69.78-125.94-143.29,0-42.06,17.95-79.91,46.63-106.31,8.54-7.88,18.04-14.73,28.32-20.37,20.64-11.35,44.33-17.8,69.51-17.8,4.24,0,8.42.18,12.55.54,13.2,1.13,25.87,4.03,37.82,8.48,3.2-12.7,7.83-24.79,13.68-36.17,28.47-55.29,86.12-93.11,152.61-93.11s124.11,37.82,152.58,93.11c5.85,11.38,10.49,23.48,13.68,36.17,11.92-4.45,24.61-7.35,37.82-8.48,4.12-.36,8.3-.54,12.55-.54,24.07,0,46.75,5.88,66.7,16.28,10.34,5.41,19.95,12.01,28.62,19.66,30.14,26.47,49.17,65.3,49.17,108.55,0,74.8-56.87,136.36-129.73,143.74Z\" />\n </svg>\n )\n },\n) as unknown as LucideIcon\n\n/** Registry entries, by the name `app.apps.icon` carries for these products. */\nexport const BRAND_MARKS: Record<string, LucideIcon> = {\n ChefControlMark,\n}\n","import type { LucideIcon } from 'lucide-react'\nimport { BRAND_MARKS } from './primitives/brand-marks'\nimport {\n Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,\n Award, BadgeDollarSign, Ban, Banknote, BarChart3, Beer, Bell, Bike, BookOpen,\n BookOpenCheck, Box, Boxes, Briefcase, Building2, Calculator, Calendar, CalendarCheck, CalendarCheck2,\n CalendarClock, CalendarDays, CalendarPlus, CalendarRange, CalendarX, Camera, Cat, Check, CheckCircle,\n CheckSquare, ChefHat, ChevronDown, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard,\n ClipboardCheck, ClipboardList,\n Clock, Clock3, Command, Compass, Contact, CookingPot, CreditCard, Database, Disc3, Dog,\n DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,\n FileText, Filter, Flame, FolderOpen, Gauge, Gift, GlassWater, Globe, GraduationCap, HandCoins, Handshake, Heart, Hourglass,\n FolderTree, Home, Image, Images, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,\n Leaf, LeafyGreen, LineChart, Link, List, ListChecks, ListMusic, ListPlus, Lock, LogIn,\n Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,\n MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,\n Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,\n Receipt, Repeat, RotateCcw, RotateCw, Ruler, Scale, ScanLine, Search, Send, Settings, Shield,\n ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Smartphone, Soup, Sparkles, Star, Store, Tag,\n TableProperties, Tags, Target, Ticket, Timer, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,\n User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils, WandSparkles,\n Upload, UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,\n Zap,\n} from 'lucide-react'\n\n// ---------------------------------------------------------------------------\n// Central lucide icon registry. The SDK's manifest-driven surfaces resolve\n// icons by string name; a namespace import (`import * as LucideIcons`) defeats\n// tree-shaking and drags all ~1,500 icons (~500 KB min) into every bundle, so\n// the SDK ships this curated set instead — the union of every icon name the\n// SDK, plugins, and app templates reference. Apps using names outside the set\n// call registerIcons({ Name: Component }) with their own named imports.\n// ---------------------------------------------------------------------------\n\nconst registry: Record<string, LucideIcon> = {\n Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,\n Award, BadgeDollarSign, Ban, Banknote, BarChart3, Beer, Bell, Bike, BookOpen,\n BookOpenCheck, Box, Boxes, Briefcase, Building2, Calculator, Calendar, CalendarCheck, CalendarCheck2,\n CalendarClock, CalendarDays, CalendarPlus, CalendarRange, CalendarX, Camera, Cat, Check, CheckCircle,\n CheckSquare, ChefHat, ChevronDown, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard,\n ClipboardCheck, ClipboardList,\n Clock, Clock3, Command, Compass, Contact, CookingPot, CreditCard, Database, Disc3, Dog,\n DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,\n FileText, Filter, Flame, FolderOpen, Gauge, Gift, GlassWater, Globe, GraduationCap, HandCoins, Handshake, Heart, Hourglass,\n FolderTree, Home, Image, Images, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,\n Leaf, LeafyGreen, LineChart, Link, List, ListChecks, ListMusic, ListPlus, Lock, LogIn,\n Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,\n MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,\n Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,\n Receipt, Repeat, RotateCcw, RotateCw, Ruler, Scale, ScanLine, Search, Send, Settings, Shield,\n ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Smartphone, Soup, Sparkles, Star, Store, Tag,\n TableProperties, Tags, Target, Ticket, Timer, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,\n User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils, WandSparkles,\n Upload, UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,\n Zap,\n // The family's own product marks, resolvable by the same string names the\n // app registry stores — a product that HAS a mark should never be drawn by a\n // stand-in glyph in the launcher.\n ...BRAND_MARKS,\n}\n\n/** Add or override icons resolvable by string name (e.g. from app manifests). */\nexport function registerIcons(icons: Record<string, LucideIcon>): void {\n Object.assign(registry, icons)\n}\n\n/** Resolve a lucide icon by name; undefined when not registered. */\nexport function getLucideIcon(name: string): LucideIcon | undefined {\n return registry[name]\n}\n\n/** The registered icon map (live reference — do not mutate directly). */\nexport const ICON_MAP = registry\n"]}