@pattern-stack/frontend-patterns 0.2.0-alpha.6 → 0.2.0-alpha.8

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.
@@ -2,5 +2,4 @@ export * from "./utils";
2
2
  export * from "./animations";
3
3
  export * from "./field-detection";
4
4
  export * from "./ui-mapping";
5
- export * from "./entity-card-mapping";
6
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atoms/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atoms/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
package/dist/index.es.js CHANGED
@@ -9,7 +9,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
9
9
  import * as React from "react";
10
10
  import React__default, { useRef, useState, useEffect, useMemo, forwardRef, useCallback, useContext, createContext, useId, Component } from "react";
11
11
  import * as SheetPrimitive from "@radix-ui/react-dialog";
12
- import { Map as Map$1, Calculator, Brain, User, Handshake, Truck, Building, HelpCircle, Info, AlertCircle, Check, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, ChevronUp, ChevronLeft, ChevronDown, ChevronRight, Music, Video, Image, Folder, File, Flag, Tag, Bookmark, Heart, Star, MapPin, Clock, Calendar, Phone, Mail, Unlock, Lock, Share, Upload, Download, Eye, Trash2, Edit, Plus, Search, Bell, Settings, Home, Layout, TrendingUp, Database, BarChart3, Users, Shield, X, Menu, Palette, Circle, Building2, Package, FileText, Loader2, EyeOff, InfoIcon, ChevronsUpDown, AreaChart, LineChart, TrendingDown, Minus, AlertTriangle, Activity, WifiOff, CloudOff, Cloud, CheckCircle, FileX, Sun, Moon, LogOut, Square, Waves, Zap, TreePine, Sparkles, Sunset, DollarSign, ShoppingCart, Target, ExternalLink, MoreHorizontal, Filter, Edit2, Undo2, RefreshCw, History, Save, Copy, Grid3X3, Layers, XCircle, Briefcase } from "lucide-react";
12
+ import { Map as Map$1, Calculator, Brain, User, Handshake, Truck, Building, HelpCircle, Info, AlertCircle, Check, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, ChevronUp, ChevronLeft, ChevronDown, ChevronRight, Music, Video, Image, Folder, File, Flag, Tag, Bookmark, Heart, Star, MapPin, Clock, Calendar, Phone, Mail, Unlock, Lock, Share, Upload, Download, Eye, Trash2, Edit, Plus, Search, Bell, Settings, Home, Layout, TrendingUp, Database, BarChart3, Users, Shield, X, Menu, Palette, Loader2, EyeOff, InfoIcon, Circle, ChevronsUpDown, AreaChart, LineChart, TrendingDown, Minus, AlertTriangle, Activity, WifiOff, CloudOff, Cloud, CheckCircle, FileX, Sun, Moon, LogOut, Square, Waves, Zap, TreePine, Sparkles, Sunset, Building2, DollarSign, ShoppingCart, Target, ExternalLink, MoreHorizontal, Filter, Edit2, Undo2, RefreshCw, FileText, History, Save, Copy, Grid3X3, Layers, XCircle, Briefcase } from "lucide-react";
13
13
  import * as LabelPrimitive from "@radix-ui/react-label";
14
14
  import { cva } from "class-variance-authority";
15
15
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
@@ -2009,362 +2009,6 @@ function renderField(value, fieldName, fieldType, breakpoint, item, customRender
2009
2009
  function cn(...inputs) {
2010
2010
  return twMerge(clsx(inputs));
2011
2011
  }
2012
- const STATUS_COLOR_MAP = {
2013
- // Success states
2014
- active: "success",
2015
- completed: "success",
2016
- approved: "success",
2017
- paid: "success",
2018
- delivered: "success",
2019
- resolved: "success",
2020
- closed: "success",
2021
- // Warning states
2022
- pending: "warning",
2023
- processing: "warning",
2024
- review: "warning",
2025
- draft: "warning",
2026
- waiting: "warning",
2027
- // Error states
2028
- failed: "error",
2029
- rejected: "error",
2030
- cancelled: "error",
2031
- overdue: "error",
2032
- blocked: "error",
2033
- // Info states
2034
- new: "info",
2035
- open: "info",
2036
- in_progress: "info",
2037
- scheduled: "info",
2038
- // Neutral (default)
2039
- inactive: "neutral",
2040
- archived: "neutral",
2041
- unknown: "neutral"
2042
- };
2043
- function getStatusColor(value) {
2044
- if (typeof value !== "string") return "neutral";
2045
- const normalized = value.toLowerCase().replace(/[_-]/g, "_");
2046
- return STATUS_COLOR_MAP[normalized] ?? "neutral";
2047
- }
2048
- const CATEGORY_MAP = {
2049
- account: 1,
2050
- customer: 1,
2051
- client: 1,
2052
- user: 2,
2053
- contact: 2,
2054
- person: 2,
2055
- order: 3,
2056
- sale: 3,
2057
- transaction: 3,
2058
- product: 4,
2059
- item: 4,
2060
- inventory: 4,
2061
- task: 5,
2062
- activity: 5,
2063
- event: 5,
2064
- file: 6,
2065
- document: 6,
2066
- report: 6,
2067
- tag: 7,
2068
- category: 7,
2069
- label: 7,
2070
- default: 8
2071
- };
2072
- function getCategoryForEntity(entityType) {
2073
- if (!entityType) return 8;
2074
- const normalized = entityType.toLowerCase();
2075
- for (const [key, value] of Object.entries(CATEGORY_MAP)) {
2076
- if (normalized.includes(key)) return value;
2077
- }
2078
- return 8;
2079
- }
2080
- function getIconForEntity(entityType) {
2081
- if (!entityType) return /* @__PURE__ */ jsx(Circle, { className: "w-4 h-4" });
2082
- const normalized = entityType.toLowerCase();
2083
- if (normalized.includes("account") || normalized.includes("customer") || normalized.includes("client")) {
2084
- return /* @__PURE__ */ jsx(Building2, { className: "w-4 h-4" });
2085
- }
2086
- if (normalized.includes("user") || normalized.includes("contact") || normalized.includes("person")) {
2087
- return /* @__PURE__ */ jsx(User, { className: "w-4 h-4" });
2088
- }
2089
- if (normalized.includes("product") || normalized.includes("item")) {
2090
- return /* @__PURE__ */ jsx(Package, { className: "w-4 h-4" });
2091
- }
2092
- if (normalized.includes("file") || normalized.includes("document")) {
2093
- return /* @__PURE__ */ jsx(FileText, { className: "w-4 h-4" });
2094
- }
2095
- if (normalized.includes("tag") || normalized.includes("category")) {
2096
- return /* @__PURE__ */ jsx(Tag, { className: "w-4 h-4" });
2097
- }
2098
- return /* @__PURE__ */ jsx(Circle, { className: "w-4 h-4" });
2099
- }
2100
- function normalizeImportance(importance) {
2101
- switch (importance) {
2102
- case "critical":
2103
- case "high":
2104
- case "primary":
2105
- return "primary";
2106
- case "medium":
2107
- case "secondary":
2108
- return "secondary";
2109
- default:
2110
- return "tertiary";
2111
- }
2112
- }
2113
- function isPrimaryImportance(importance) {
2114
- return normalizeImportance(importance) === "primary";
2115
- }
2116
- function formatValueForCard(value, type, format) {
2117
- if (value === null || value === void 0) return "—";
2118
- switch (type) {
2119
- case "money": {
2120
- const num = Number(value);
2121
- const currency = (format == null ? void 0 : format.currency) ?? "USD";
2122
- if (num >= 1e6) {
2123
- return new Intl.NumberFormat("en-US", {
2124
- style: "currency",
2125
- currency,
2126
- notation: "compact",
2127
- maximumFractionDigits: 1
2128
- }).format(num);
2129
- }
2130
- if (num >= 1e3) {
2131
- return new Intl.NumberFormat("en-US", {
2132
- style: "currency",
2133
- currency,
2134
- notation: "compact",
2135
- maximumFractionDigits: 1
2136
- }).format(num);
2137
- }
2138
- return new Intl.NumberFormat("en-US", {
2139
- style: "currency",
2140
- currency,
2141
- maximumFractionDigits: 0
2142
- }).format(num);
2143
- }
2144
- case "percent": {
2145
- const num = Number(value);
2146
- return `${num.toFixed(0)}%`;
2147
- }
2148
- case "number": {
2149
- const num = Number(value);
2150
- if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
2151
- if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
2152
- return String(num);
2153
- }
2154
- case "date":
2155
- case "datetime": {
2156
- const date = new Date(String(value));
2157
- if (isNaN(date.getTime())) return String(value);
2158
- return date.toLocaleDateString("en-US", {
2159
- month: "short",
2160
- day: "numeric"
2161
- });
2162
- }
2163
- case "boolean":
2164
- return value ? "Yes" : "No";
2165
- default:
2166
- return String(value);
2167
- }
2168
- }
2169
- function autoDetectMapping(columns) {
2170
- var _a, _b, _c, _d, _e, _f;
2171
- const primaryCols = columns.filter((c) => isPrimaryImportance(c.importance));
2172
- const titleField = ((_a = primaryCols.find((c) => ["text", "entity", "user"].includes(c.type))) == null ? void 0 : _a.field) ?? ((_b = primaryCols[0]) == null ? void 0 : _b.field) ?? ((_c = columns[0]) == null ? void 0 : _c.field);
2173
- const valueField = (_d = primaryCols.find((c) => c.type === "money")) == null ? void 0 : _d.field;
2174
- const statusField = (_e = primaryCols.find(
2175
- (c) => c.type === "status" || c.type === "badge"
2176
- )) == null ? void 0 : _e.field;
2177
- const usedForMain = new Set([titleField, valueField, statusField].filter(Boolean));
2178
- const remainingPrimary = primaryCols.filter((c) => !usedForMain.has(c.field));
2179
- const subtitleField = (_f = remainingPrimary[0]) == null ? void 0 : _f.field;
2180
- const usedFields = new Set(
2181
- [titleField, valueField, statusField, subtitleField].filter(Boolean)
2182
- );
2183
- const metadataFields = primaryCols.filter((c) => !usedFields.has(c.field)).slice(0, 3).map((c) => c.field);
2184
- return {
2185
- titleField: titleField ?? "id",
2186
- subtitleField,
2187
- valueField,
2188
- statusField,
2189
- metadataFields,
2190
- iconConfig: void 0
2191
- };
2192
- }
2193
- function entityToListCardProps(item, columns, mapping, entityType) {
2194
- const autoMapping = autoDetectMapping(columns);
2195
- const effectiveMapping = { ...autoMapping, ...mapping };
2196
- const {
2197
- titleField,
2198
- subtitleField,
2199
- valueField,
2200
- statusField,
2201
- metadataFields,
2202
- iconConfig
2203
- } = effectiveMapping;
2204
- const getColumn = (field) => field ? columns.find((c) => c.field === field) : void 0;
2205
- const title = item[titleField] != null ? String(item[titleField]) : "—";
2206
- const subtitle = subtitleField && item[subtitleField] != null ? String(item[subtitleField]) : void 0;
2207
- let value;
2208
- if (valueField && item[valueField] != null) {
2209
- const valueCol = getColumn(valueField);
2210
- const formatted = formatValueForCard(
2211
- item[valueField],
2212
- (valueCol == null ? void 0 : valueCol.type) ?? "text",
2213
- valueCol == null ? void 0 : valueCol.format
2214
- );
2215
- value = {
2216
- text: formatted,
2217
- variant: "success"
2218
- // Money typically green
2219
- };
2220
- }
2221
- let badge;
2222
- if (statusField && item[statusField] != null) {
2223
- const statusValue = String(item[statusField]);
2224
- badge = {
2225
- text: statusValue,
2226
- variant: "status",
2227
- status: getStatusColor(statusValue),
2228
- size: "sm"
2229
- };
2230
- }
2231
- const metadata = metadataFields == null ? void 0 : metadataFields.map((field) => {
2232
- const col = getColumn(field);
2233
- if (!col || item[field] == null) return null;
2234
- return formatValueForCard(item[field], col.type, col.format);
2235
- }).filter((v) => v !== null);
2236
- let icon;
2237
- if (iconConfig) {
2238
- const iconValue = iconConfig.field ? item[iconConfig.field] : void 0;
2239
- if (iconConfig.variant === "status" && iconValue) {
2240
- icon = {
2241
- icon: iconConfig.icon ?? getIconForEntity(entityType),
2242
- variant: "status",
2243
- status: getStatusColor(iconValue),
2244
- size: "sm"
2245
- };
2246
- } else {
2247
- icon = {
2248
- icon: iconConfig.icon ?? getIconForEntity(entityType),
2249
- variant: "category",
2250
- category: getCategoryForEntity(entityType),
2251
- size: "sm"
2252
- };
2253
- }
2254
- } else {
2255
- icon = {
2256
- icon: getIconForEntity(entityType),
2257
- variant: "category",
2258
- category: getCategoryForEntity(entityType),
2259
- size: "sm"
2260
- };
2261
- }
2262
- return {
2263
- icon,
2264
- title,
2265
- subtitle,
2266
- metadata,
2267
- value,
2268
- badge
2269
- };
2270
- }
2271
- const HEADER_ABBREVIATIONS = {
2272
- customer: "Cust",
2273
- account: "Acct",
2274
- amount: "Amt",
2275
- quantity: "Qty",
2276
- priority: "Pri",
2277
- status: "Status",
2278
- created: "Created",
2279
- updated: "Updated",
2280
- description: "Desc",
2281
- total: "Total",
2282
- items: "Items",
2283
- number: "#",
2284
- date: "Date",
2285
- time: "Time"
2286
- };
2287
- function abbreviateHeader(label) {
2288
- const lower = label.toLowerCase();
2289
- for (const [key, abbrev] of Object.entries(HEADER_ABBREVIATIONS)) {
2290
- if (lower.includes(key)) return abbrev;
2291
- }
2292
- if (label.length > 8) return label.slice(0, 6) + "…";
2293
- return label;
2294
- }
2295
- function generateCompactColumns(columns, options = {}) {
2296
- const {
2297
- maxColumns = 5,
2298
- abbreviateHeaders = true,
2299
- requiredFields = [],
2300
- excludeFields = []
2301
- } = options;
2302
- const excludeSet = new Set(excludeFields);
2303
- const requiredSet = new Set(requiredFields);
2304
- const filteredColumns = columns.filter((col) => {
2305
- if (excludeSet.has(col.field)) return false;
2306
- return true;
2307
- });
2308
- const required = filteredColumns.filter((c) => requiredSet.has(c.field));
2309
- const primary = filteredColumns.filter(
2310
- (c) => !requiredSet.has(c.field) && normalizeImportance(c.importance) === "primary"
2311
- );
2312
- const secondary = filteredColumns.filter(
2313
- (c) => !requiredSet.has(c.field) && normalizeImportance(c.importance) === "secondary"
2314
- );
2315
- const selectedColumns = [...required, ...primary, ...secondary].slice(
2316
- 0,
2317
- maxColumns
2318
- );
2319
- return selectedColumns.map((col) => ({
2320
- key: col.field,
2321
- header: abbreviateHeaders ? abbreviateHeader(col.label) : col.label,
2322
- sortable: col.sortable,
2323
- type: col.type,
2324
- format: col.format,
2325
- // Compact widths
2326
- width: getCompactWidth(col.type)
2327
- }));
2328
- }
2329
- function getCompactWidth(type) {
2330
- switch (type) {
2331
- case "money":
2332
- return "70px";
2333
- case "number":
2334
- case "percent":
2335
- return "50px";
2336
- case "status":
2337
- case "badge":
2338
- return "80px";
2339
- case "date":
2340
- return "70px";
2341
- case "datetime":
2342
- return "90px";
2343
- case "boolean":
2344
- return "50px";
2345
- default:
2346
- return "120px";
2347
- }
2348
- }
2349
- function createMobileCardRenderer(columns, mapping, entityType) {
2350
- const { ListCard: ListCard2 } = require("../components/data/ListCard");
2351
- return ({ data, onItemClick }) => /* @__PURE__ */ jsx("div", { className: "space-y-2", children: data.map((item, index) => {
2352
- const cardProps = entityToListCardProps(
2353
- item,
2354
- columns,
2355
- mapping,
2356
- entityType
2357
- );
2358
- return /* @__PURE__ */ jsx(
2359
- ListCard2,
2360
- {
2361
- ...cardProps,
2362
- onClick: onItemClick ? () => onItemClick(item) : void 0
2363
- },
2364
- item.id ?? index
2365
- );
2366
- }) });
2367
- }
2368
2012
  let globalAuthService = null;
2369
2013
  function setGlobalAuthService(authService) {
2370
2014
  globalAuthService = authService;
@@ -17724,17 +17368,14 @@ export {
17724
17368
  cn,
17725
17369
  createAPIDataTemplate,
17726
17370
  createApiClient,
17727
- createMobileCardRenderer,
17728
17371
  createReactApp,
17729
17372
  createSimpleApp,
17730
17373
  defaultFieldRenderers,
17731
17374
  detectBulkOperationType,
17732
17375
  detectUIConfig,
17733
- entityToListCardProps,
17734
17376
  env,
17735
17377
  formatNumberWithTooltip,
17736
17378
  generateBulkOperationName,
17737
- generateCompactColumns,
17738
17379
  getAnimationClasses,
17739
17380
  getChartHeight,
17740
17381
  getContainerHeightClass,