@schandlergarcia/sf-web-components 1.9.42 → 1.9.44

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.
@@ -0,0 +1,212 @@
1
+ # Quick Reference Card
2
+
3
+ ## Before Publishing - Checklist
4
+
5
+ ```bash
6
+ # 1. Update CHANGELOG.md
7
+ vim CHANGELOG.md
8
+
9
+ # 2. Run verification
10
+ npm run verify
11
+
12
+ # 3. Run pre-publish checks
13
+ npm run prepublish:check
14
+
15
+ # 4. Bump version
16
+ npm version patch
17
+
18
+ # 5. Publish (verification runs automatically)
19
+ npm publish
20
+ ```
21
+
22
+ ## Component Naming
23
+
24
+ | ✅ CORRECT | ❌ WRONG | Reason |
25
+ |-----------|---------|--------|
26
+ | `UIButton.tsx` | `Button.tsx` | Library uses UI prefix |
27
+ | `UIInput.tsx` | `Input.tsx` | Library uses UI prefix |
28
+ | `UIButton.tsx` | `Button.jsx` | Use TypeScript .tsx |
29
+ | Import from `UIButton` | Import from `Button` | Must match file name |
30
+
31
+ ## Source of Truth Hierarchy
32
+
33
+ ```
34
+ 1. .a4drules/skills/component-library/ ← DOCUMENTATION (source of truth)
35
+ 2. src/components/library/ ← CODE (must match docs)
36
+ 3. src/templates/ ← TEMPLATES (must match docs)
37
+ 4. CHANGELOG.md ← HISTORY (must document all changes)
38
+ ```
39
+
40
+ ## File Structure
41
+
42
+ ```
43
+ src/components/library/ui/
44
+ ✅ UIButton.tsx (Library component)
45
+ ✅ UIInput.tsx (Library component)
46
+ ❌ Button.tsx (Reserved for outer app)
47
+ ❌ Input.tsx (Reserved for outer app)
48
+
49
+ src/templates/pages/
50
+ ✅ Home.tsx.template (Imports UIButton, UIInput)
51
+ ✅ NotFound.tsx.template (Imports UIButton)
52
+
53
+ .a4drules/skills/component-library/
54
+ 📚 ui-primitives.md (Documents UIButton, UIInput)
55
+ 📚 common-mistakes.md (Lists UIButton vs Button rule)
56
+ ```
57
+
58
+ ## Import Patterns
59
+
60
+ ### ✅ Correct
61
+
62
+ ```tsx
63
+ // Template imports
64
+ import UIButton from '@/components/library/ui/UIButton';
65
+ import UIInput from '@/components/library/ui/UIInput';
66
+
67
+ // Barrel export
68
+ export { default as UIButton } from "./ui/UIButton";
69
+ export { default as UIInput } from "./ui/UIInput";
70
+
71
+ // Consuming app imports
72
+ import { UIButton, UIInput, MetricCard } from '@/components/library';
73
+ ```
74
+
75
+ ### ❌ Wrong
76
+
77
+ ```tsx
78
+ // ❌ Don't import from non-existent files
79
+ import Button from '@/components/library/ui/Button';
80
+ import Input from '@/components/library/ui/Input';
81
+
82
+ // ❌ Don't use wrong paths in barrel export
83
+ export { default as UIButton } from "./ui/Button"; // File doesn't exist
84
+
85
+ // ❌ Don't use shadcn names in library
86
+ import { Button } from '@/components/library';
87
+ ```
88
+
89
+ ## Verification Commands
90
+
91
+ | Command | Purpose | When to Run |
92
+ |---------|---------|-------------|
93
+ | `npm run verify` | Check consistency | Before committing |
94
+ | `npm run prepublish:check` | Full pre-publish checks | Before publishing |
95
+ | `npm run build` | Build dist/ | After changes |
96
+ | `bash scripts/verify-consistency.sh` | Detailed consistency check | Manual verification |
97
+
98
+ ## Common Errors and Fixes
99
+
100
+ ### Error: "Cannot resolve import '@/components/library/ui/UIButton'"
101
+
102
+ **Cause:** Component file is named `Button.tsx` but imports expect `UIButton.tsx`
103
+
104
+ **Fix:**
105
+ ```bash
106
+ # Rename to correct name
107
+ mv src/components/library/ui/Button.tsx src/components/library/ui/UIButton.tsx
108
+
109
+ # Update barrel export
110
+ # Change: from "./ui/Button"
111
+ # To: from "./ui/UIButton"
112
+ ```
113
+
114
+ ### Error: "CHANGELOG missing entry for version X.X.X"
115
+
116
+ **Cause:** Version was bumped but CHANGELOG.md not updated
117
+
118
+ **Fix:**
119
+ ```bash
120
+ vim CHANGELOG.md
121
+ # Add:
122
+ ## [X.X.X] - 2026-04-01
123
+ ### Fixed
124
+ - Description of changes
125
+ ```
126
+
127
+ ### Error: "Consistency check failed"
128
+
129
+ **Cause:** Mismatch between docs, code, or templates
130
+
131
+ **Fix:**
132
+ ```bash
133
+ # Run verification to see details
134
+ npm run verify
135
+
136
+ # Fix reported issues
137
+ # - Check .a4drules/skills/component-library/ui-primitives.md for correct names
138
+ # - Update code to match docs
139
+ # - Update templates to match docs
140
+ ```
141
+
142
+ ## Golden Reference
143
+
144
+ **Version 1.9.25-1.9.28** are the golden reference versions.
145
+
146
+ ```bash
147
+ # View golden version structure
148
+ npm view @schandlergarcia/sf-web-components@1.9.28
149
+
150
+ # Check working example
151
+ ls /Users/stephan.garcia/reactapp4/src/components/library/ui/
152
+ ```
153
+
154
+ ## Emergency Recovery
155
+
156
+ If you published a broken version:
157
+
158
+ ```bash
159
+ # 1. Don't unpublish (breaks downstream)
160
+ # 2. Fix the issue immediately
161
+ # 3. Publish patch version
162
+
163
+ # Example:
164
+ # v1.9.42 published with Button.jsx (wrong)
165
+
166
+ # Fix:
167
+ cd sf-web-components
168
+ git checkout v1.9.28 -- src/components/library/ui/UIButton.tsx
169
+ git checkout v1.9.28 -- src/components/library/ui/UIInput.tsx
170
+ rm src/components/library/ui/Button.jsx
171
+ rm src/components/library/ui/Input.jsx
172
+
173
+ # Update exports
174
+ vim src/components/library/index.jsx
175
+ # Change: from "./ui/Button" → from "./ui/UIButton"
176
+ # Change: from "./ui/Input" → from "./ui/UIInput"
177
+
178
+ # Update changelog
179
+ vim CHANGELOG.md
180
+ # Document the fix
181
+
182
+ # Publish fix
183
+ npm version patch
184
+ npm publish
185
+ ```
186
+
187
+ ## Key Documents
188
+
189
+ | Document | Purpose | Read When |
190
+ |----------|---------|-----------|
191
+ | [ARCHITECTURE.md](./ARCHITECTURE.md) | System structure | Starting new work |
192
+ | [CONTRIBUTING.md](./CONTRIBUTING.md) | Contribution guide | Before first commit |
193
+ | [CHANGELOG.md](./CHANGELOG.md) | Version history | Before each release |
194
+ | [.a4drules/RULES.md](./.a4drules/RULES.md) | Mandatory rules | Always follow |
195
+ | [.a4drules/skills/component-library/](./a4drules/skills/component-library/) | Component API docs | When using components |
196
+
197
+ ## Questions?
198
+
199
+ 1. ❓ "What should I name this component?" → Check `.a4drules/skills/component-library/ui-primitives.md`
200
+ 2. ❓ "Can I rename this component?" → NO, unless you update docs first (see CONTRIBUTING.md)
201
+ 3. ❓ "Why UIButton not Button?" → See `.a4drules/skills/component-library/common-mistakes.md`
202
+ 4. ❓ "What version works?" → 1.9.25-1.9.28 and 1.9.43+
203
+ 5. ❓ "Can I skip verification?" → NO, it will fail at publish time anyway
204
+
205
+ ## Remember
206
+
207
+ - **Documentation = Contract** - Code must match docs
208
+ - **CHANGELOG = Required** - Update with every change
209
+ - **UI Prefix = Library** - UIButton, UIInput (not Button, Input)
210
+ - **Templates = Must Match** - Imports must match file names
211
+ - **Verify = Always** - Run before committing and publishing
212
+ - **Golden = Reference** - v1.9.25-1.9.28 when in doubt
package/README.md CHANGED
@@ -20,18 +20,25 @@ This package requires:
20
20
  ### Import Components
21
21
 
22
22
  ```tsx
23
- import { Button, Card } from '@schandlergarcia/sf-web-components';
24
- import { cn } from '@schandlergarcia/sf-web-components/lib';
23
+ // Library components (for command centers/dashboards)
24
+ import { UIButton, MetricCard } from '@/components/library';
25
+ import { cn } from '@/lib/utils';
25
26
 
26
- function App() {
27
+ function Dashboard() {
27
28
  return (
28
- <Card className={cn('p-4')}>
29
- <Button>Click me</Button>
30
- </Card>
29
+ <MetricCard
30
+ title="Total Sales"
31
+ value="$1.2M"
32
+ trend={{ value: 12, direction: 'up' }}
33
+ footer={<UIButton variant="primary">View Details</UIButton>}
34
+ />
31
35
  );
32
36
  }
33
37
  ```
34
38
 
39
+ **Note:** After installation, components are copied to `src/components/library/` for Tailwind scanning.
40
+ Import from `@/components/library` (not from the package directly).
41
+
35
42
  ### Import Styles
36
43
 
37
44
  Add to your main CSS file:
@@ -105,6 +112,32 @@ npm run build
105
112
  npm run build:types
106
113
  ```
107
114
 
115
+ ## Contributing
116
+
117
+ **⚠️ IMPORTANT: Read [CONTRIBUTING.md](./CONTRIBUTING.md) before making changes.**
118
+
119
+ ### Key Rules
120
+ - Component names MUST match `.a4drules/skills/component-library/` documentation
121
+ - Library components use **UI prefix** (UIButton, UIInput) - NOT shadcn names
122
+ - Update CHANGELOG.md with EVERY change before publishing
123
+ - Run verification scripts before committing
124
+
125
+ ### Quick Checks
126
+
127
+ ```bash
128
+ # Verify consistency between code, docs, and templates
129
+ npm run verify
130
+
131
+ # Pre-publish verification (runs automatically before publish)
132
+ npm run prepublish:check
133
+ ```
134
+
135
+ ### Documentation Structure
136
+ - **[ARCHITECTURE.md](./ARCHITECTURE.md)** - Source of truth hierarchy
137
+ - **[CONTRIBUTING.md](./CONTRIBUTING.md)** - Contribution guidelines and checklists
138
+ - **[CHANGELOG.md](./CHANGELOG.md)** - Detailed version history
139
+ - **[.a4drules/RULES.md](./.a4drules/RULES.md)** - Mandatory project rules
140
+
108
141
  ## Publishing
109
142
 
110
143
  This package publishes to the **public npm registry** at https://registry.npmjs.org.
@@ -113,21 +146,50 @@ This package publishes to the **public npm registry** at https://registry.npmjs.
113
146
  - Be logged in to npm: `npm login`
114
147
  - Have publish permissions for the `@schandlergarcia` scope
115
148
 
116
- ### Publish a New Version
149
+ ### Publish Process
150
+
151
+ **The `prepublishOnly` script automatically runs verification checks.**
117
152
 
118
153
  ```bash
119
- # Bump version (patch, minor, or major)
120
- npm version patch # 1.9.29 1.9.30
121
- npm version minor # 1.9.29 → 1.10.0
122
- npm version major # 1.9.29 → 2.0.0
154
+ # 1. Update CHANGELOG.md with your changes
155
+ # Add entry under ## [X.X.X] - YYYY-MM-DD
123
156
 
124
- # Or manually edit package.json version field
157
+ # 2. Bump version
158
+ npm version patch # 1.9.43 → 1.9.44
159
+ npm version minor # 1.9.43 → 1.10.0
160
+ npm version major # 1.9.43 → 2.0.0
125
161
 
126
- # Build and publish
127
- npm run build
162
+ # 3. Publish (verification runs automatically)
128
163
  npm publish
129
164
  ```
130
165
 
166
+ **The prepublishOnly hook will:**
167
+ 1. Run consistency verification (`npm run verify`)
168
+ 2. Check CHANGELOG has entry for current version
169
+ 3. Verify UIButton.tsx and UIInput.tsx exist
170
+ 4. Build the package
171
+ 5. Block publish if any checks fail
172
+
173
+ ### Manual Verification (Optional)
174
+
175
+ ```bash
176
+ # Run all pre-publish checks manually
177
+ npm run prepublish:check
178
+
179
+ # Run only consistency checks
180
+ npm run verify
181
+ ```
182
+
183
+ ### If Publish Fails
184
+
185
+ If verification fails:
186
+ 1. Read the error output carefully
187
+ 2. Fix the reported issues
188
+ 3. See [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed guidance
189
+ 4. See [.a4drules/RULES.md](./.a4drules/RULES.md) for rules
190
+ 5. Run `npm run verify` to check fixes
191
+ 6. Try publishing again
192
+
131
193
  The package is published as **public** and can be installed by anyone:
132
194
  ```bash
133
195
  npm install @schandlergarcia/sf-web-components
@@ -1,6 +1,6 @@
1
1
  import { jsxs as i, jsx as r } from "react/jsx-runtime";
2
2
  import "react";
3
- import m from "../ui/Button.js";
3
+ import m from "../ui/UIButton.js";
4
4
  function x({
5
5
  actions: s = [],
6
6
  title: t,
@@ -1 +1 @@
1
- {"version":3,"file":"ActionList.js","sources":["../../../../src/components/library/cards/ActionList.jsx"],"sourcesContent":["import React from \"react\";\nimport UIButton from \"../ui/Button\";\n\n/**\n * Row of action buttons — typically used at the bottom of a dashboard section.\n *\n * @param {{ label: string, [key]: any }[] | string[]} actions\n * @param {string} title\n * @param {Function} onAction Called with the action object/string when clicked\n */\nexport default function ActionList({\n actions = [],\n title,\n onAction,\n className = \"\",\n}) {\n return (\n <div className={`rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900 ${className}`}>\n {title && (\n <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">\n {title}\n </div>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n}\n"],"names":["ActionList","actions","title","onAction","className","jsxs","jsx","action","i","UIButton"],"mappings":";;;AAUA,SAAwBA,EAAW;AAAA,EACjC,SAAAC,IAAU,CAAA;AAAA,EACV,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC,IAAY;AACd,GAAG;AACD,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAW,4FAA4FD,CAAS,IAClH,UAAA;AAAA,IAAAF,KACC,gBAAAI,EAAC,OAAA,EAAI,WAAU,8DACZ,UAAAJ,GACH;AAAA,IAEF,gBAAAI,EAAC,SAAI,WAAU,wBACZ,YAAQ,IAAI,CAACC,GAAQC,MACpB,gBAAAF;AAAA,MAACG;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,SAASD,MAAM,IAAI,YAAY;AAAA,QAC/B,SAAS,MAAML,IAAWI,CAAM;AAAA,QAE/B,UAAA,OAAOA,KAAW,WAAWA,IAASA,EAAO;AAAA,MAAA;AAAA,MALzCC;AAAA,IAAA,CAOR,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
1
+ {"version":3,"file":"ActionList.js","sources":["../../../../src/components/library/cards/ActionList.jsx"],"sourcesContent":["import React from \"react\";\nimport UIButton from \"../ui/UIButton\";\n\n/**\n * Row of action buttons — typically used at the bottom of a dashboard section.\n *\n * @param {{ label: string, [key]: any }[] | string[]} actions\n * @param {string} title\n * @param {Function} onAction Called with the action object/string when clicked\n */\nexport default function ActionList({\n actions = [],\n title,\n onAction,\n className = \"\",\n}) {\n return (\n <div className={`rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900 ${className}`}>\n {title && (\n <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">\n {title}\n </div>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n}\n"],"names":["ActionList","actions","title","onAction","className","jsxs","jsx","action","i","UIButton"],"mappings":";;;AAUA,SAAwBA,EAAW;AAAA,EACjC,SAAAC,IAAU,CAAA;AAAA,EACV,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC,IAAY;AACd,GAAG;AACD,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAW,4FAA4FD,CAAS,IAClH,UAAA;AAAA,IAAAF,KACC,gBAAAI,EAAC,OAAA,EAAI,WAAU,8DACZ,UAAAJ,GACH;AAAA,IAEF,gBAAAI,EAAC,SAAI,WAAU,wBACZ,YAAQ,IAAI,CAACC,GAAQC,MACpB,gBAAAF;AAAA,MAACG;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,SAASD,MAAM,IAAI,YAAY;AAAA,QAC/B,SAAS,MAAML,IAAWI,CAAM;AAAA,QAE/B,UAAA,OAAOA,KAAW,WAAWA,IAASA,EAAO;AAAA,MAAA;AAAA,MALzCC;AAAA,IAAA,CAOR,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
@@ -1,8 +1,8 @@
1
1
  import { jsx as t, jsxs as d } from "react/jsx-runtime";
2
2
  import i from "react";
3
3
  import I from "./BaseCard.js";
4
- import te from "../ui/Input.js";
5
- import K from "../ui/Button.js";
4
+ import te from "../ui/UIInput.js";
5
+ import K from "../ui/UIButton.js";
6
6
  import Q from "../ui/Text.js";
7
7
  function re(o, s) {
8
8
  if (s == null) return "";
@@ -1 +1 @@
1
- {"version":3,"file":"TableCard.js","sources":["../../../../src/components/library/cards/TableCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\nimport UIInput from \"../ui/Input\";\nimport UIButton from \"../ui/Button\";\nimport UIText from \"../ui/Text\";\n\nfunction defaultTypeFormat(type, value) {\n if (value == null) return \"\";\n if (!type) return String(value);\n\n if (type === \"currency\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n.toLocaleString(undefined, { style: \"currency\", currency: \"USD\" });\n }\n if (type === \"percentage\") {\n const n = Number(value);\n if (Number.isFinite(n)) return `${n}%`;\n }\n if (type === \"number\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n.toLocaleString();\n }\n return String(value);\n}\n\nfunction stableSort(data, compare) {\n return data\n .map((item, idx) => ({ item, idx }))\n .sort((a, b) => {\n const c = compare(a.item, b.item);\n return c !== 0 ? c : a.idx - b.idx;\n })\n .map((x) => x.item);\n}\n\nexport default function TableCard({\n data = [],\n columns = [],\n title,\n subtitle,\n searchable = false,\n sortable = false,\n paginated = false,\n selectable = false,\n pageSize = 10,\n actions,\n rowActions,\n onRowSelect,\n onSort,\n onSearch,\n loading = false,\n error,\n emptyMessage = \"No results.\",\n simulateInitialLoad = false,\n minInitialDelayMs = 350,\n maxInitialDelayMs = 900,\n ...cardProps\n}) {\n const [query, setQuery] = React.useState(\"\");\n const [sortKey, setSortKey] = React.useState(null);\n const [sortDir, setSortDir] = React.useState(\"asc\");\n const [page, setPage] = React.useState(1);\n const [selectedId, setSelectedId] = React.useState(null);\n const [simLoading, setSimLoading] = React.useState(simulateInitialLoad);\n\n React.useEffect(() => {\n if (!simulateInitialLoad) return;\n const delay =\n Math.floor(Math.random() * (maxInitialDelayMs - minInitialDelayMs + 1)) + minInitialDelayMs;\n const t = setTimeout(() => setSimLoading(false), delay);\n return () => clearTimeout(t);\n }, [simulateInitialLoad, minInitialDelayMs, maxInitialDelayMs]);\n\n const effectiveLoading = loading || simLoading;\n\n const filtered = React.useMemo(() => {\n if (!searchable || !query.trim()) return data;\n const q = query.trim().toLowerCase();\n return data.filter((row) =>\n columns.some((col) => {\n const raw = row?.[col.key];\n if (raw == null) return false;\n return String(raw).toLowerCase().includes(q);\n })\n );\n }, [data, columns, query, searchable]);\n\n const sorted = React.useMemo(() => {\n if (!sortable || !sortKey) return filtered;\n const col = columns.find((c) => c.key === sortKey);\n if (!col) return filtered;\n const dir = sortDir === \"desc\" ? -1 : 1;\n return stableSort(filtered, (a, b) => {\n const av = a?.[sortKey];\n const bv = b?.[sortKey];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (typeof av === \"number\" && typeof bv === \"number\") return (av - bv) * dir;\n return String(av).localeCompare(String(bv)) * dir;\n });\n }, [filtered, sortable, sortKey, sortDir, columns]);\n\n const total = sorted.length;\n const totalPages = paginated ? Math.max(1, Math.ceil(total / pageSize)) : 1;\n const clampedPage = Math.min(page, totalPages);\n\n const pageData = React.useMemo(() => {\n if (!paginated) return sorted;\n const start = (clampedPage - 1) * pageSize;\n return sorted.slice(start, start + pageSize);\n }, [sorted, paginated, clampedPage, pageSize]);\n\n React.useEffect(() => {\n if (page !== clampedPage) setPage(clampedPage);\n }, [page, clampedPage]);\n\n const header = (\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"min-w-0\">\n {title ? (\n <UIText as=\"div\" size=\"sm\" weight=\"medium\">\n {title}\n </UIText>\n ) : null}\n {subtitle ? (\n <UIText as=\"div\" size=\"xs\" muted className=\"mt-1\">\n {subtitle}\n </UIText>\n ) : null}\n </div>\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-end\">\n {searchable ? (\n <div className=\"w-full sm:w-64\">\n <UIInput\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setPage(1);\n onSearch?.(e.target.value);\n }}\n placeholder=\"Search…\"\n aria-label=\"Search table\"\n />\n </div>\n ) : null}\n {actions ? <div className=\"flex items-center gap-2\">{actions}</div> : null}\n </div>\n </div>\n );\n\n if (error) {\n return (\n <BaseCard\n header={header}\n body={\n <div className=\"mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100\">\n {String(error)}\n </div>\n }\n {...cardProps}\n />\n );\n }\n\n const canSort = (col) => sortable && (col.sortable ?? true);\n\n return (\n <BaseCard\n variant=\"table\"\n header={header}\n body={\n <div className=\"mt-4 overflow-hidden rounded-xl border border-slate-200 dark:border-slate-800\">\n <div className=\"w-full overflow-x-auto\">\n <table className=\"min-w-full border-separate border-spacing-0\">\n <thead className=\"bg-slate-50 dark:bg-slate-950/30\">\n <tr>\n {columns.map((col) => {\n const active = sortKey === col.key;\n return (\n <th\n key={col.key}\n scope=\"col\"\n className={[\n \"whitespace-nowrap border-b border-slate-200 px-4 py-3 text-left text-xs font-semibold text-slate-600 dark:border-slate-800 dark:text-slate-300\",\n col.className ?? \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {canSort(col) ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-2 hover:text-slate-900 dark:hover:text-slate-50\"\n onClick={() => {\n const nextDir = active && sortDir === \"asc\" ? \"desc\" : \"asc\";\n setSortKey(col.key);\n setSortDir(nextDir);\n onSort?.({ key: col.key, direction: nextDir });\n }}\n >\n <span>{col.label}</span>\n <span className=\"text-[10px] opacity-70\">\n {active ? (sortDir === \"asc\" ? \"▲\" : \"▼\") : \"↕\"}\n </span>\n </button>\n ) : (\n col.label\n )}\n </th>\n );\n })}\n {rowActions ? (\n <th className=\"border-b border-slate-200 px-4 py-3 text-right text-xs font-semibold text-slate-600 dark:border-slate-800 dark:text-slate-300\">\n Actions\n </th>\n ) : null}\n </tr>\n </thead>\n\n <tbody className=\"bg-white dark:bg-slate-900\">\n {effectiveLoading ? (\n Array.from({ length: Math.min(pageSize, 6) }).map((_, idx) => (\n <tr key={idx}>\n {columns.map((col) => (\n <td\n key={col.key}\n className=\"border-b border-slate-200 px-4 py-3 dark:border-slate-800\"\n >\n <div className=\"h-4 w-3/4 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n </td>\n ))}\n {rowActions ? (\n <td className=\"border-b border-slate-200 px-4 py-3 dark:border-slate-800\">\n <div className=\"h-4 w-10 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n </td>\n ) : null}\n </tr>\n ))\n ) : pageData.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + (rowActions ? 1 : 0)}\n className=\"px-4 py-10 text-center text-sm text-slate-600 dark:text-slate-300\"\n >\n {emptyMessage}\n </td>\n </tr>\n ) : (\n pageData.map((row, idx) => {\n const rowId = row?.id ?? idx;\n const selected = selectable && selectedId === rowId;\n return (\n <tr\n key={rowId}\n className={[\n \"group\",\n selectable ? \"cursor-pointer\" : \"\",\n selected ? \"bg-brand-50 dark:bg-brand-950/30\" : \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n onClick={() => {\n if (!selectable) return;\n setSelectedId(rowId);\n onRowSelect?.(row);\n }}\n >\n {columns.map((col) => {\n const raw = row?.[col.key];\n const content = col.render ? col.render(raw, row) : defaultTypeFormat(col.type, raw);\n return (\n <td\n key={col.key}\n className={[\n \"border-b border-slate-200 px-4 py-3 text-sm text-slate-700 dark:border-slate-800 dark:text-slate-200\",\n col.mono ? \"font-mono text-[13px]\" : \"\",\n col.className ?? \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {content}\n </td>\n );\n })}\n {rowActions ? (\n <td className=\"border-b border-slate-200 px-4 py-3 text-right text-sm dark:border-slate-800\">\n <div className=\"inline-flex items-center justify-end gap-2 opacity-100 sm:opacity-0 sm:group-hover:opacity-100\">\n {rowActions(row)}\n </div>\n </td>\n ) : null}\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n\n {paginated && !effectiveLoading ? (\n <div className=\"flex flex-col gap-2 border-t border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/30 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"text-xs text-slate-600 dark:text-slate-300\">\n {total === 0 ? \"0 results\" : `Showing ${(clampedPage - 1) * pageSize + 1}-${Math.min(clampedPage * pageSize, total)} of ${total}`}\n </div>\n <div className=\"flex items-center gap-2\">\n <UIButton\n variant=\"outline\"\n size=\"sm\"\n disabled={clampedPage <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n >\n Prev\n </UIButton>\n <div className=\"text-xs text-slate-600 dark:text-slate-300\">\n Page {clampedPage} / {totalPages}\n </div>\n <UIButton\n variant=\"outline\"\n size=\"sm\"\n disabled={clampedPage >= totalPages}\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n >\n Next\n </UIButton>\n </div>\n </div>\n ) : null}\n </div>\n }\n {...cardProps}\n />\n );\n}\n\n\n"],"names":["defaultTypeFormat","type","value","n","stableSort","data","compare","item","idx","a","b","c","x","TableCard","columns","title","subtitle","searchable","sortable","paginated","selectable","pageSize","actions","rowActions","onRowSelect","onSort","onSearch","loading","error","emptyMessage","simulateInitialLoad","minInitialDelayMs","maxInitialDelayMs","cardProps","query","setQuery","React","sortKey","setSortKey","sortDir","setSortDir","page","setPage","selectedId","setSelectedId","simLoading","setSimLoading","delay","t","effectiveLoading","filtered","q","row","col","raw","sorted","dir","av","bv","total","totalPages","clampedPage","pageData","start","header","jsxs","jsx","UIText","UIInput","BaseCard","canSort","active","nextDir","_","rowId","content","UIButton","p"],"mappings":"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"}
1
+ {"version":3,"file":"TableCard.js","sources":["../../../../src/components/library/cards/TableCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\nimport UIInput from \"../ui/UIInput\";\nimport UIButton from \"../ui/UIButton\";\nimport UIText from \"../ui/Text\";\n\nfunction defaultTypeFormat(type, value) {\n if (value == null) return \"\";\n if (!type) return String(value);\n\n if (type === \"currency\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n.toLocaleString(undefined, { style: \"currency\", currency: \"USD\" });\n }\n if (type === \"percentage\") {\n const n = Number(value);\n if (Number.isFinite(n)) return `${n}%`;\n }\n if (type === \"number\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n.toLocaleString();\n }\n return String(value);\n}\n\nfunction stableSort(data, compare) {\n return data\n .map((item, idx) => ({ item, idx }))\n .sort((a, b) => {\n const c = compare(a.item, b.item);\n return c !== 0 ? c : a.idx - b.idx;\n })\n .map((x) => x.item);\n}\n\nexport default function TableCard({\n data = [],\n columns = [],\n title,\n subtitle,\n searchable = false,\n sortable = false,\n paginated = false,\n selectable = false,\n pageSize = 10,\n actions,\n rowActions,\n onRowSelect,\n onSort,\n onSearch,\n loading = false,\n error,\n emptyMessage = \"No results.\",\n simulateInitialLoad = false,\n minInitialDelayMs = 350,\n maxInitialDelayMs = 900,\n ...cardProps\n}) {\n const [query, setQuery] = React.useState(\"\");\n const [sortKey, setSortKey] = React.useState(null);\n const [sortDir, setSortDir] = React.useState(\"asc\");\n const [page, setPage] = React.useState(1);\n const [selectedId, setSelectedId] = React.useState(null);\n const [simLoading, setSimLoading] = React.useState(simulateInitialLoad);\n\n React.useEffect(() => {\n if (!simulateInitialLoad) return;\n const delay =\n Math.floor(Math.random() * (maxInitialDelayMs - minInitialDelayMs + 1)) + minInitialDelayMs;\n const t = setTimeout(() => setSimLoading(false), delay);\n return () => clearTimeout(t);\n }, [simulateInitialLoad, minInitialDelayMs, maxInitialDelayMs]);\n\n const effectiveLoading = loading || simLoading;\n\n const filtered = React.useMemo(() => {\n if (!searchable || !query.trim()) return data;\n const q = query.trim().toLowerCase();\n return data.filter((row) =>\n columns.some((col) => {\n const raw = row?.[col.key];\n if (raw == null) return false;\n return String(raw).toLowerCase().includes(q);\n })\n );\n }, [data, columns, query, searchable]);\n\n const sorted = React.useMemo(() => {\n if (!sortable || !sortKey) return filtered;\n const col = columns.find((c) => c.key === sortKey);\n if (!col) return filtered;\n const dir = sortDir === \"desc\" ? -1 : 1;\n return stableSort(filtered, (a, b) => {\n const av = a?.[sortKey];\n const bv = b?.[sortKey];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (typeof av === \"number\" && typeof bv === \"number\") return (av - bv) * dir;\n return String(av).localeCompare(String(bv)) * dir;\n });\n }, [filtered, sortable, sortKey, sortDir, columns]);\n\n const total = sorted.length;\n const totalPages = paginated ? Math.max(1, Math.ceil(total / pageSize)) : 1;\n const clampedPage = Math.min(page, totalPages);\n\n const pageData = React.useMemo(() => {\n if (!paginated) return sorted;\n const start = (clampedPage - 1) * pageSize;\n return sorted.slice(start, start + pageSize);\n }, [sorted, paginated, clampedPage, pageSize]);\n\n React.useEffect(() => {\n if (page !== clampedPage) setPage(clampedPage);\n }, [page, clampedPage]);\n\n const header = (\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"min-w-0\">\n {title ? (\n <UIText as=\"div\" size=\"sm\" weight=\"medium\">\n {title}\n </UIText>\n ) : null}\n {subtitle ? (\n <UIText as=\"div\" size=\"xs\" muted className=\"mt-1\">\n {subtitle}\n </UIText>\n ) : null}\n </div>\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-end\">\n {searchable ? (\n <div className=\"w-full sm:w-64\">\n <UIInput\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setPage(1);\n onSearch?.(e.target.value);\n }}\n placeholder=\"Search…\"\n aria-label=\"Search table\"\n />\n </div>\n ) : null}\n {actions ? <div className=\"flex items-center gap-2\">{actions}</div> : null}\n </div>\n </div>\n );\n\n if (error) {\n return (\n <BaseCard\n header={header}\n body={\n <div className=\"mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100\">\n {String(error)}\n </div>\n }\n {...cardProps}\n />\n );\n }\n\n const canSort = (col) => sortable && (col.sortable ?? true);\n\n return (\n <BaseCard\n variant=\"table\"\n header={header}\n body={\n <div className=\"mt-4 overflow-hidden rounded-xl border border-slate-200 dark:border-slate-800\">\n <div className=\"w-full overflow-x-auto\">\n <table className=\"min-w-full border-separate border-spacing-0\">\n <thead className=\"bg-slate-50 dark:bg-slate-950/30\">\n <tr>\n {columns.map((col) => {\n const active = sortKey === col.key;\n return (\n <th\n key={col.key}\n scope=\"col\"\n className={[\n \"whitespace-nowrap border-b border-slate-200 px-4 py-3 text-left text-xs font-semibold text-slate-600 dark:border-slate-800 dark:text-slate-300\",\n col.className ?? \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {canSort(col) ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-2 hover:text-slate-900 dark:hover:text-slate-50\"\n onClick={() => {\n const nextDir = active && sortDir === \"asc\" ? \"desc\" : \"asc\";\n setSortKey(col.key);\n setSortDir(nextDir);\n onSort?.({ key: col.key, direction: nextDir });\n }}\n >\n <span>{col.label}</span>\n <span className=\"text-[10px] opacity-70\">\n {active ? (sortDir === \"asc\" ? \"▲\" : \"▼\") : \"↕\"}\n </span>\n </button>\n ) : (\n col.label\n )}\n </th>\n );\n })}\n {rowActions ? (\n <th className=\"border-b border-slate-200 px-4 py-3 text-right text-xs font-semibold text-slate-600 dark:border-slate-800 dark:text-slate-300\">\n Actions\n </th>\n ) : null}\n </tr>\n </thead>\n\n <tbody className=\"bg-white dark:bg-slate-900\">\n {effectiveLoading ? (\n Array.from({ length: Math.min(pageSize, 6) }).map((_, idx) => (\n <tr key={idx}>\n {columns.map((col) => (\n <td\n key={col.key}\n className=\"border-b border-slate-200 px-4 py-3 dark:border-slate-800\"\n >\n <div className=\"h-4 w-3/4 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n </td>\n ))}\n {rowActions ? (\n <td className=\"border-b border-slate-200 px-4 py-3 dark:border-slate-800\">\n <div className=\"h-4 w-10 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n </td>\n ) : null}\n </tr>\n ))\n ) : pageData.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length + (rowActions ? 1 : 0)}\n className=\"px-4 py-10 text-center text-sm text-slate-600 dark:text-slate-300\"\n >\n {emptyMessage}\n </td>\n </tr>\n ) : (\n pageData.map((row, idx) => {\n const rowId = row?.id ?? idx;\n const selected = selectable && selectedId === rowId;\n return (\n <tr\n key={rowId}\n className={[\n \"group\",\n selectable ? \"cursor-pointer\" : \"\",\n selected ? \"bg-brand-50 dark:bg-brand-950/30\" : \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n onClick={() => {\n if (!selectable) return;\n setSelectedId(rowId);\n onRowSelect?.(row);\n }}\n >\n {columns.map((col) => {\n const raw = row?.[col.key];\n const content = col.render ? col.render(raw, row) : defaultTypeFormat(col.type, raw);\n return (\n <td\n key={col.key}\n className={[\n \"border-b border-slate-200 px-4 py-3 text-sm text-slate-700 dark:border-slate-800 dark:text-slate-200\",\n col.mono ? \"font-mono text-[13px]\" : \"\",\n col.className ?? \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {content}\n </td>\n );\n })}\n {rowActions ? (\n <td className=\"border-b border-slate-200 px-4 py-3 text-right text-sm dark:border-slate-800\">\n <div className=\"inline-flex items-center justify-end gap-2 opacity-100 sm:opacity-0 sm:group-hover:opacity-100\">\n {rowActions(row)}\n </div>\n </td>\n ) : null}\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n\n {paginated && !effectiveLoading ? (\n <div className=\"flex flex-col gap-2 border-t border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/30 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"text-xs text-slate-600 dark:text-slate-300\">\n {total === 0 ? \"0 results\" : `Showing ${(clampedPage - 1) * pageSize + 1}-${Math.min(clampedPage * pageSize, total)} of ${total}`}\n </div>\n <div className=\"flex items-center gap-2\">\n <UIButton\n variant=\"outline\"\n size=\"sm\"\n disabled={clampedPage <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n >\n Prev\n </UIButton>\n <div className=\"text-xs text-slate-600 dark:text-slate-300\">\n Page {clampedPage} / {totalPages}\n </div>\n <UIButton\n variant=\"outline\"\n size=\"sm\"\n disabled={clampedPage >= totalPages}\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n >\n Next\n </UIButton>\n </div>\n </div>\n ) : null}\n </div>\n }\n {...cardProps}\n />\n );\n}\n\n\n"],"names":["defaultTypeFormat","type","value","n","stableSort","data","compare","item","idx","a","b","c","x","TableCard","columns","title","subtitle","searchable","sortable","paginated","selectable","pageSize","actions","rowActions","onRowSelect","onSort","onSearch","loading","error","emptyMessage","simulateInitialLoad","minInitialDelayMs","maxInitialDelayMs","cardProps","query","setQuery","React","sortKey","setSortKey","sortDir","setSortDir","page","setPage","selectedId","setSelectedId","simLoading","setSimLoading","delay","t","effectiveLoading","filtered","q","row","col","raw","sorted","dir","av","bv","total","totalPages","clampedPage","pageData","start","header","jsxs","jsx","UIText","UIInput","BaseCard","canSort","active","nextDir","_","rowId","content","UIButton","p"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/library/index.jsx"],"sourcesContent":["export { default as AppThemeProvider, useThemeMode } from \"./theme/AppThemeProvider\";\n\n// UI primitives\nexport { default as UIButton } from \"./ui/Button\";\nexport { default as UIInput } from \"./ui/Input\";\nexport { default as UIToggle } from \"./ui/Toggle\";\nexport { default as UIText } from \"./ui/Text\";\nexport { default as UICard, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from \"./ui/Card\";\nexport { default as UIContainer } from \"./ui/Container\";\nexport { default as UIChip } from \"./ui/Chip\";\nexport { default as Avatar } from \"./ui/Avatar\";\nexport { default as Spinner } from \"./ui/Spinner\";\nexport { default as EmptyState } from \"./ui/EmptyState\";\nexport { default as Label } from \"./ui/Label\";\nexport { default as Checkbox } from \"./ui/Checkbox\";\nexport { default as FieldGroup } from \"./ui/FieldGroup\";\n\n// Cards\nexport { default as BaseCard } from \"./cards/BaseCard\";\nexport { default as ChartCard } from \"./cards/ChartCard\";\nexport { default as ListCard } from \"./cards/ListCard\";\nexport { default as MetricCard } from \"./cards/MetricCard\";\nexport { default as SectionCard } from \"./cards/SectionCard\";\nexport { default as StatusCard } from \"./cards/StatusCard\";\nexport { default as TableCard } from \"./cards/TableCard\";\nexport { default as WidgetCard } from \"./cards/WidgetCard\";\nexport { default as FeedPanel } from \"./cards/FeedPanel\";\nexport { default as ActivityCard } from \"./cards/ActivityCard\";\nexport { default as MetricsStrip } from \"./cards/MetricsStrip\";\nexport { default as CalloutCard } from \"./cards/CalloutCard\";\nexport { default as ActionList } from \"./cards/ActionList\";\n\n// Charts\nexport { default as D3Chart } from \"./charts/D3Chart\";\nexport { D3ChartTemplates } from \"./charts/D3ChartTemplates\";\nexport { default as GeoMap } from \"./charts/GeoMap\";\n\n// Layout\nexport { default as PageContainer } from \"./layout/PageContainer\";\n\n// Skeletons\nexport { default as CardSkeleton } from \"./skeletons/CardSkeleton\";\n\n// Forms\nexport { FormModal, FormRenderer, FormSection, FormField, useFormState } from \"./forms\";\n\n// Filters\nexport { FilterBar, SearchFilter, SelectFilter, ToggleFilter } from \"./filters\";\n\n// Data mode\nexport { default as DataModeProvider, useDataMode } from \"./data/DataModeProvider\";\nexport { default as DataModeToggle } from \"./data/DataModeToggle\";\nexport { default as useDataSource } from \"./data/useDataSource\";\n\n// Data utilities\nexport { default as usePageFilters } from \"./data/usePageFilters\";\nexport {\n filterBySearch,\n filterByValue,\n filterByToggle,\n filterByDateRange,\n sortByKey,\n applyFilters,\n} from \"./data/filterUtils\";\n\n// Chat / AI agent\nexport {\n ChatPanel,\n ChatBar,\n ChatMessageList,\n ChatMessage,\n ChatInput,\n ChatTypingIndicator,\n ChatSuggestions,\n ChatToolCall,\n ChatWelcome,\n useChatState,\n} from \"./chat\";\n\n// HeroUI wrappers — existing\nexport { default as HeroUIButton, Button } from \"./heroui/Button\";\nexport { default as HeroUIInput } from \"./heroui/Input\";\nexport { default as HeroUICard } from \"./heroui/Card\";\nexport { default as HeroUIToggle } from \"./heroui/Toggle\";\n\n// HeroUI wrappers — navigation & layout\nexport { default as HeroUITabs, Tabs } from \"./heroui/Tabs\";\nexport { default as HeroUIAccordion, Accordion } from \"./heroui/Accordion\";\nexport { default as HeroUIBreadcrumbs, Breadcrumbs } from \"./heroui/Breadcrumbs\";\nexport { default as HeroUISeparator, Separator } from \"./heroui/Separator\";\nexport { default as HeroUIPagination, Pagination } from \"./heroui/Pagination\";\n\n// Breadcrumb subcomponents for shadcn compatibility\nexport const Breadcrumb = ({ children, ...props }) => <nav aria-label=\"breadcrumb\" {...props}>{children}</nav>;\nexport const BreadcrumbList = ({ children, ...props }) => <ol className=\"flex flex-wrap items-center gap-1.5 break-words text-sm text-slate-500 dark:text-slate-400\" {...props}>{children}</ol>;\nexport const BreadcrumbItem = ({ children, ...props }) => <li className=\"inline-flex items-center gap-1.5\" {...props}>{children}</li>;\nexport const BreadcrumbLink = ({ href, children, asChild, ...props }) => asChild ? <span {...props}>{children}</span> : <a href={href} className=\"transition-colors hover:text-slate-900 dark:hover:text-slate-50\" {...props}>{children}</a>;\nexport const BreadcrumbPage = ({ children, ...props }) => <span role=\"link\" aria-disabled=\"true\" aria-current=\"page\" className=\"font-normal text-slate-900 dark:text-slate-50\" {...props}>{children}</span>;\nexport const BreadcrumbSeparator = ({ children, ...props }) => <li role=\"presentation\" aria-hidden=\"true\" {...props}>{children ?? \"/\"}</li>;\nexport const BreadcrumbEllipsis = (props) => <span role=\"presentation\" aria-hidden=\"true\" {...props}>...</span>;\n\n// Pagination subcomponents for shadcn compatibility\nexport const PaginationContent = ({ children, ...props }) => <ul className=\"flex flex-row items-center gap-1\" {...props}>{children}</ul>;\nexport const PaginationItem = ({ children, ...props }) => <li {...props}>{children}</li>;\nexport const PaginationLink = ({ href, isActive, children, ...props }) => <a href={href} aria-current={isActive ? \"page\" : undefined} className={`inline-flex items-center justify-center rounded-md text-sm font-medium h-9 min-w-9 px-4 py-2 ${isActive ? \"bg-slate-900 text-white dark:bg-slate-50 dark:text-slate-900\" : \"hover:bg-slate-100 dark:hover:bg-slate-800\"}`} {...props}>{children}</a>;\nexport const PaginationPrevious = ({ href, ...props }) => <PaginationLink href={href} {...props}>Previous</PaginationLink>;\nexport const PaginationNext = ({ href, ...props }) => <PaginationLink href={href} {...props}>Next</PaginationLink>;\nexport const PaginationEllipsis = (props) => <span aria-hidden {...props}>...</span>;\n\n// HeroUI wrappers — overlays\nexport { default as HeroUIDrawer, Drawer } from \"./heroui/Drawer\";\nexport { default as HeroUIModal, Modal } from \"./heroui/Modal\";\nexport { default as HeroUIDropdown, Dropdown } from \"./heroui/Dropdown\";\nexport { default as HeroUITooltip, Tooltip } from \"./heroui/Tooltip\";\nexport { default as HeroUIToast, Toast, toast } from \"./heroui/Toast\";\n\n// HeroUI wrappers — feedback\nexport { default as HeroUIAlert } from \"./heroui/Alert\";\nexport { default as HeroUIBadge, Badge } from \"./heroui/Badge\";\nexport { default as HeroUIProgressBar, ProgressBar } from \"./heroui/ProgressBar\";\nexport { default as HeroUIProgressCircle, ProgressCircle } from \"./heroui/ProgressCircle\";\nexport { default as HeroUIMeter, Meter } from \"./heroui/Meter\";\nexport { default as HeroUISkeleton, Skeleton } from \"./heroui/Skeleton\";\n\n// shadcn-compatible components from ui/\nexport { default as Alert, AlertTitle, AlertDescription, AlertAction } from \"./ui/Alert\";\n\n// shadcn-compatible components from heroui/ (HeroUI-based)\nexport { default as HeroUIDialog, Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from \"./heroui/Dialog\";\nexport { default as HeroUIField, Field, FieldLabel, FieldDescription, FieldError } from \"./heroui/Field\";\nexport { default as HeroUICollapsible, Collapsible, CollapsibleTrigger, CollapsibleContent } from \"./heroui/Collapsible\";\nexport { default as HeroUIPopover, Popover, PopoverTrigger, PopoverContent } from \"./heroui/Popover\";\nexport { default as HeroUIDatePicker, DatePicker, DatePickerTrigger, DatePickerContent, DatePickerCalendar, DatePickerRangeTrigger } from \"./heroui/DatePicker\";\n\n// HeroUI wrappers — pickers & forms\nexport { default as HeroUISelect, Select } from \"./heroui/Select\";\n\n// Re-export Select subcomponents for shadcn compatibility\nexport const SelectTrigger = ({ children, size, ...props }) => <button {...props}>{children}</button>;\nexport const SelectValue = ({ placeholder, ...props }) => <span {...props}>{placeholder}</span>;\nexport const SelectContent = ({ children, ...props }) => <div {...props}>{children}</div>;\nexport const SelectItem = ({ children, ...props }) => <div {...props}>{children}</div>;\n\n// HeroUI wrappers — utilities\nexport { default as HeroUIKbd, Kbd } from \"./heroui/Kbd\";\nexport { default as HeroUIScrollShadow, ScrollShadow } from \"./heroui/ScrollShadow\";\n"],"names":["Breadcrumb","children","props","jsx","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","href","asChild","BreadcrumbPage","BreadcrumbSeparator","BreadcrumbEllipsis","PaginationContent","PaginationItem","PaginationLink","isActive","PaginationPrevious","PaginationNext","PaginationEllipsis","SelectTrigger","size","SelectValue","placeholder","SelectContent","SelectItem"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/library/index.jsx"],"sourcesContent":["export { default as AppThemeProvider, useThemeMode } from \"./theme/AppThemeProvider\";\n\n// UI primitives\nexport { default as UIButton } from \"./ui/UIButton\";\nexport { default as UIInput } from \"./ui/UIInput\";\nexport { default as UIToggle } from \"./ui/Toggle\";\nexport { default as UIText } from \"./ui/Text\";\nexport { default as UICard, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from \"./ui/Card\";\nexport { default as UIContainer } from \"./ui/Container\";\nexport { default as UIChip } from \"./ui/Chip\";\nexport { default as Avatar } from \"./ui/Avatar\";\nexport { default as Spinner } from \"./ui/Spinner\";\nexport { default as EmptyState } from \"./ui/EmptyState\";\nexport { default as Label } from \"./ui/Label\";\nexport { default as Checkbox } from \"./ui/Checkbox\";\nexport { default as FieldGroup } from \"./ui/FieldGroup\";\n\n// Cards\nexport { default as BaseCard } from \"./cards/BaseCard\";\nexport { default as ChartCard } from \"./cards/ChartCard\";\nexport { default as ListCard } from \"./cards/ListCard\";\nexport { default as MetricCard } from \"./cards/MetricCard\";\nexport { default as SectionCard } from \"./cards/SectionCard\";\nexport { default as StatusCard } from \"./cards/StatusCard\";\nexport { default as TableCard } from \"./cards/TableCard\";\nexport { default as WidgetCard } from \"./cards/WidgetCard\";\nexport { default as FeedPanel } from \"./cards/FeedPanel\";\nexport { default as ActivityCard } from \"./cards/ActivityCard\";\nexport { default as MetricsStrip } from \"./cards/MetricsStrip\";\nexport { default as CalloutCard } from \"./cards/CalloutCard\";\nexport { default as ActionList } from \"./cards/ActionList\";\n\n// Charts\nexport { default as D3Chart } from \"./charts/D3Chart\";\nexport { D3ChartTemplates } from \"./charts/D3ChartTemplates\";\nexport { default as GeoMap } from \"./charts/GeoMap\";\n\n// Layout\nexport { default as PageContainer } from \"./layout/PageContainer\";\n\n// Skeletons\nexport { default as CardSkeleton } from \"./skeletons/CardSkeleton\";\n\n// Forms\nexport { FormModal, FormRenderer, FormSection, FormField, useFormState } from \"./forms\";\n\n// Filters\nexport { FilterBar, SearchFilter, SelectFilter, ToggleFilter } from \"./filters\";\n\n// Data mode\nexport { default as DataModeProvider, useDataMode } from \"./data/DataModeProvider\";\nexport { default as DataModeToggle } from \"./data/DataModeToggle\";\nexport { default as useDataSource } from \"./data/useDataSource\";\n\n// Data utilities\nexport { default as usePageFilters } from \"./data/usePageFilters\";\nexport {\n filterBySearch,\n filterByValue,\n filterByToggle,\n filterByDateRange,\n sortByKey,\n applyFilters,\n} from \"./data/filterUtils\";\n\n// Chat / AI agent\nexport {\n ChatPanel,\n ChatBar,\n ChatMessageList,\n ChatMessage,\n ChatInput,\n ChatTypingIndicator,\n ChatSuggestions,\n ChatToolCall,\n ChatWelcome,\n useChatState,\n} from \"./chat\";\n\n// HeroUI wrappers — existing\nexport { default as HeroUIButton, Button } from \"./heroui/Button\";\nexport { default as HeroUIInput } from \"./heroui/Input\";\nexport { default as HeroUICard } from \"./heroui/Card\";\nexport { default as HeroUIToggle } from \"./heroui/Toggle\";\n\n// HeroUI wrappers — navigation & layout\nexport { default as HeroUITabs, Tabs } from \"./heroui/Tabs\";\nexport { default as HeroUIAccordion, Accordion } from \"./heroui/Accordion\";\nexport { default as HeroUIBreadcrumbs, Breadcrumbs } from \"./heroui/Breadcrumbs\";\nexport { default as HeroUISeparator, Separator } from \"./heroui/Separator\";\nexport { default as HeroUIPagination, Pagination } from \"./heroui/Pagination\";\n\n// Breadcrumb subcomponents for shadcn compatibility\nexport const Breadcrumb = ({ children, ...props }) => <nav aria-label=\"breadcrumb\" {...props}>{children}</nav>;\nexport const BreadcrumbList = ({ children, ...props }) => <ol className=\"flex flex-wrap items-center gap-1.5 break-words text-sm text-slate-500 dark:text-slate-400\" {...props}>{children}</ol>;\nexport const BreadcrumbItem = ({ children, ...props }) => <li className=\"inline-flex items-center gap-1.5\" {...props}>{children}</li>;\nexport const BreadcrumbLink = ({ href, children, asChild, ...props }) => asChild ? <span {...props}>{children}</span> : <a href={href} className=\"transition-colors hover:text-slate-900 dark:hover:text-slate-50\" {...props}>{children}</a>;\nexport const BreadcrumbPage = ({ children, ...props }) => <span role=\"link\" aria-disabled=\"true\" aria-current=\"page\" className=\"font-normal text-slate-900 dark:text-slate-50\" {...props}>{children}</span>;\nexport const BreadcrumbSeparator = ({ children, ...props }) => <li role=\"presentation\" aria-hidden=\"true\" {...props}>{children ?? \"/\"}</li>;\nexport const BreadcrumbEllipsis = (props) => <span role=\"presentation\" aria-hidden=\"true\" {...props}>...</span>;\n\n// Pagination subcomponents for shadcn compatibility\nexport const PaginationContent = ({ children, ...props }) => <ul className=\"flex flex-row items-center gap-1\" {...props}>{children}</ul>;\nexport const PaginationItem = ({ children, ...props }) => <li {...props}>{children}</li>;\nexport const PaginationLink = ({ href, isActive, children, ...props }) => <a href={href} aria-current={isActive ? \"page\" : undefined} className={`inline-flex items-center justify-center rounded-md text-sm font-medium h-9 min-w-9 px-4 py-2 ${isActive ? \"bg-slate-900 text-white dark:bg-slate-50 dark:text-slate-900\" : \"hover:bg-slate-100 dark:hover:bg-slate-800\"}`} {...props}>{children}</a>;\nexport const PaginationPrevious = ({ href, ...props }) => <PaginationLink href={href} {...props}>Previous</PaginationLink>;\nexport const PaginationNext = ({ href, ...props }) => <PaginationLink href={href} {...props}>Next</PaginationLink>;\nexport const PaginationEllipsis = (props) => <span aria-hidden {...props}>...</span>;\n\n// HeroUI wrappers — overlays\nexport { default as HeroUIDrawer, Drawer } from \"./heroui/Drawer\";\nexport { default as HeroUIModal, Modal } from \"./heroui/Modal\";\nexport { default as HeroUIDropdown, Dropdown } from \"./heroui/Dropdown\";\nexport { default as HeroUITooltip, Tooltip } from \"./heroui/Tooltip\";\nexport { default as HeroUIToast, Toast, toast } from \"./heroui/Toast\";\n\n// HeroUI wrappers — feedback\nexport { default as HeroUIAlert } from \"./heroui/Alert\";\nexport { default as HeroUIBadge, Badge } from \"./heroui/Badge\";\nexport { default as HeroUIProgressBar, ProgressBar } from \"./heroui/ProgressBar\";\nexport { default as HeroUIProgressCircle, ProgressCircle } from \"./heroui/ProgressCircle\";\nexport { default as HeroUIMeter, Meter } from \"./heroui/Meter\";\nexport { default as HeroUISkeleton, Skeleton } from \"./heroui/Skeleton\";\n\n// shadcn-compatible components from ui/\nexport { default as Alert, AlertTitle, AlertDescription, AlertAction } from \"./ui/Alert\";\n\n// shadcn-compatible components from heroui/ (HeroUI-based)\nexport { default as HeroUIDialog, Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from \"./heroui/Dialog\";\nexport { default as HeroUIField, Field, FieldLabel, FieldDescription, FieldError } from \"./heroui/Field\";\nexport { default as HeroUICollapsible, Collapsible, CollapsibleTrigger, CollapsibleContent } from \"./heroui/Collapsible\";\nexport { default as HeroUIPopover, Popover, PopoverTrigger, PopoverContent } from \"./heroui/Popover\";\nexport { default as HeroUIDatePicker, DatePicker, DatePickerTrigger, DatePickerContent, DatePickerCalendar, DatePickerRangeTrigger } from \"./heroui/DatePicker\";\n\n// HeroUI wrappers — pickers & forms\nexport { default as HeroUISelect, Select } from \"./heroui/Select\";\n\n// Re-export Select subcomponents for shadcn compatibility\nexport const SelectTrigger = ({ children, size, ...props }) => <button {...props}>{children}</button>;\nexport const SelectValue = ({ placeholder, ...props }) => <span {...props}>{placeholder}</span>;\nexport const SelectContent = ({ children, ...props }) => <div {...props}>{children}</div>;\nexport const SelectItem = ({ children, ...props }) => <div {...props}>{children}</div>;\n\n// HeroUI wrappers — utilities\nexport { default as HeroUIKbd, Kbd } from \"./heroui/Kbd\";\nexport { default as HeroUIScrollShadow, ScrollShadow } from \"./heroui/ScrollShadow\";\n"],"names":["Breadcrumb","children","props","jsx","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","href","asChild","BreadcrumbPage","BreadcrumbSeparator","BreadcrumbEllipsis","PaginationContent","PaginationItem","PaginationLink","isActive","PaginationPrevious","PaginationNext","PaginationEllipsis","SelectTrigger","size","SelectValue","placeholder","SelectContent","SelectItem"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { jsx as d } from "react/jsx-runtime";
2
+ const i = {
3
+ primary: "bg-blue-600 text-white hover:bg-blue-500 dark:bg-blue-500 dark:hover:bg-blue-400 border-transparent",
4
+ secondary: "bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-100 dark:text-slate-900 dark:hover:bg-slate-200 border-transparent",
5
+ destructive: "bg-red-600 text-white hover:bg-red-500 dark:bg-red-500 dark:hover:bg-red-400 border-transparent",
6
+ outline: "bg-transparent text-slate-900 hover:bg-slate-50 dark:text-slate-50 dark:hover:bg-slate-900 border-slate-200 dark:border-slate-800",
7
+ ghost: "bg-transparent text-slate-900 hover:bg-slate-100 dark:text-slate-50 dark:hover:bg-slate-900 border-transparent",
8
+ link: "text-blue-600 underline-offset-4 hover:underline dark:text-blue-400 border-transparent"
9
+ }, u = {
10
+ sm: "h-8 px-3 text-sm",
11
+ md: "h-10 px-4 text-sm",
12
+ lg: "h-12 px-5 text-base",
13
+ icon: "h-10 w-10 p-0"
14
+ };
15
+ function f({
16
+ variant: e = "primary",
17
+ size: t = "md",
18
+ fullWidth: r = !1,
19
+ disabled: a = !1,
20
+ className: s = "",
21
+ children: o,
22
+ ...n
23
+ }) {
24
+ const l = i[e], b = u[t];
25
+ return /* @__PURE__ */ d(
26
+ "button",
27
+ {
28
+ type: "button",
29
+ disabled: a,
30
+ className: [
31
+ "inline-flex items-center justify-center gap-2 rounded-lg border font-medium shadow-sm transition",
32
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-slate-950",
33
+ "disabled:cursor-not-allowed disabled:opacity-60",
34
+ l,
35
+ b,
36
+ r ? "w-full" : "",
37
+ s
38
+ ].filter(Boolean).join(" "),
39
+ ...n,
40
+ children: o
41
+ }
42
+ );
43
+ }
44
+ export {
45
+ f as default
46
+ };
47
+ //# sourceMappingURL=UIButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UIButton.js","sources":["../../../../src/components/library/ui/UIButton.tsx"],"sourcesContent":["import * as React from \"react\";\n\nconst VARIANT_CLASSES = {\n primary:\n \"bg-blue-600 text-white hover:bg-blue-500 dark:bg-blue-500 dark:hover:bg-blue-400 border-transparent\",\n secondary:\n \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-100 dark:text-slate-900 dark:hover:bg-slate-200 border-transparent\",\n destructive:\n \"bg-red-600 text-white hover:bg-red-500 dark:bg-red-500 dark:hover:bg-red-400 border-transparent\",\n outline:\n \"bg-transparent text-slate-900 hover:bg-slate-50 dark:text-slate-50 dark:hover:bg-slate-900 border-slate-200 dark:border-slate-800\",\n ghost:\n \"bg-transparent text-slate-900 hover:bg-slate-100 dark:text-slate-50 dark:hover:bg-slate-900 border-transparent\",\n link: \"text-blue-600 underline-offset-4 hover:underline dark:text-blue-400 border-transparent\"\n} as const;\n\nconst SIZE_CLASSES = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-5 text-base\",\n icon: \"h-10 w-10 p-0\"\n} as const;\n\nexport interface UIButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: keyof typeof VARIANT_CLASSES;\n size?: keyof typeof SIZE_CLASSES;\n fullWidth?: boolean;\n}\n\nexport default function UIButton({\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n disabled = false,\n className = \"\",\n children,\n ...rest\n}: UIButtonProps) {\n const variantClass = VARIANT_CLASSES[variant];\n const sizeClass = SIZE_CLASSES[size];\n\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={[\n \"inline-flex items-center justify-center gap-2 rounded-lg border font-medium shadow-sm transition\",\n \"focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-slate-950\",\n \"disabled:cursor-not-allowed disabled:opacity-60\",\n variantClass,\n sizeClass,\n fullWidth ? \"w-full\" : \"\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n {...rest}\n >\n {children}\n </button>\n );\n}\n"],"names":["VARIANT_CLASSES","SIZE_CLASSES","UIButton","variant","size","fullWidth","disabled","className","children","rest","variantClass","sizeClass","jsx"],"mappings":";AAEA,MAAMA,IAAkB;AAAA,EACtB,SACE;AAAA,EACF,WACE;AAAA,EACF,aACE;AAAA,EACF,SACE;AAAA,EACF,OACE;AAAA,EACF,MAAM;AACR,GAEMC,IAAe;AAAA,EACnB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AACR;AAQA,SAAwBC,EAAS;AAAA,EAC/B,SAAAC,IAAU;AAAA,EACV,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,UAAAC;AAAA,EACA,GAAGC;AACL,GAAkB;AAChB,QAAMC,IAAeV,EAAgBG,CAAO,GACtCQ,IAAYV,EAAaG,CAAI;AAEnC,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAAN;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACAI;AAAA,QACAC;AAAA,QACAN,IAAY,WAAW;AAAA,QACvBE;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACV,GAAGE;AAAA,MAEH,UAAAD;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -0,0 +1,21 @@
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ function a({ className: e = "", ...t }) {
3
+ return /* @__PURE__ */ o(
4
+ "input",
5
+ {
6
+ className: [
7
+ "h-10 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 shadow-sm",
8
+ "placeholder:text-slate-400",
9
+ "focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 dark:focus:ring-offset-slate-950",
10
+ "dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50 dark:placeholder:text-slate-500",
11
+ "disabled:cursor-not-allowed disabled:opacity-50",
12
+ e
13
+ ].filter(Boolean).join(" "),
14
+ ...t
15
+ }
16
+ );
17
+ }
18
+ export {
19
+ a as default
20
+ };
21
+ //# sourceMappingURL=UIInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UIInput.js","sources":["../../../../src/components/library/ui/UIInput.tsx"],"sourcesContent":["import * as React from \"react\";\n\nexport interface UIInputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nexport default function UIInput({ className = \"\", ...rest }: UIInputProps) {\n return (\n <input\n className={[\n \"h-10 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 shadow-sm\",\n \"placeholder:text-slate-400\",\n \"focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 dark:focus:ring-offset-slate-950\",\n \"dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50 dark:placeholder:text-slate-500\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n {...rest}\n />\n );\n}\n"],"names":["UIInput","className","rest","jsx"],"mappings":";AAIA,SAAwBA,EAAQ,EAAE,WAAAC,IAAY,IAAI,GAAGC,KAAsB;AACzE,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACAF;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACV,GAAGC;AAAA,IAAA;AAAA,EAAA;AAGV;"}
@@ -1,7 +1,7 @@
1
1
  import { jsxs as i, jsx as e } from "react/jsx-runtime";
2
2
  import b from "react";
3
3
  import "../library/theme/AppThemeProvider.js";
4
- import u from "../library/ui/Button.js";
4
+ import u from "../library/ui/UIButton.js";
5
5
  import p from "../library/ui/Chip.js";
6
6
  import h from "../library/cards/ChartCard.js";
7
7
  import g from "../library/cards/MetricCard.js";