@open-mercato/ui 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c
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.
- package/.turbo/turbo-build.log +1 -1
- package/build.mjs +2 -54
- package/dist/backend/NextStepCallout.js +4 -4
- package/dist/backend/NextStepCallout.js.map +1 -1
- package/dist/backend/confirm-dialog/ConfirmDialog.js +12 -0
- package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
- package/dist/backend/detail/AddressTiles.js +4 -5
- package/dist/backend/detail/AddressTiles.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.generated.js +1 -25
- package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.js +3 -3
- package/dist/backend/icons/lucideRegistry.js.map +2 -2
- package/dist/backend/icons/lucideRegistryRuntime.js +28 -0
- package/dist/backend/icons/lucideRegistryRuntime.js.map +7 -0
- package/dist/backend/schedule/ScheduleToolbar.js +87 -70
- package/dist/backend/schedule/ScheduleToolbar.js.map +2 -2
- package/jest.config.cjs +2 -1
- package/package.json +17 -16
- package/scripts/lucideRegistrySource.cjs +133 -0
- package/src/backend/NextStepCallout.tsx +4 -4
- package/src/backend/confirm-dialog/ConfirmDialog.tsx +15 -0
- package/src/backend/confirm-dialog/__tests__/ConfirmDialog.test.tsx +33 -1
- package/src/backend/detail/AddressTiles.tsx +3 -6
- package/src/backend/icons/__tests__/lucideRegistryGenerator.test.ts +177 -0
- package/src/backend/icons/lucideRegistry.generated.tsx +3 -37
- package/src/backend/icons/lucideRegistry.ts +2 -2
- package/src/backend/icons/lucideRegistryRuntime.tsx +36 -0
- package/src/backend/schedule/ScheduleToolbar.tsx +89 -68
package/.turbo/turbo-build.log
CHANGED
package/build.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { readFileSync, writeFileSync } from 'node:fs'
|
|
|
3
3
|
import { dirname, join } from 'node:path'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
import { buildPackage } from '../../scripts/build-package.mjs'
|
|
6
|
+
import { buildLucideRegistrySource } from './scripts/lucideRegistrySource.cjs'
|
|
6
7
|
|
|
7
8
|
const packageDir = dirname(fileURLToPath(import.meta.url))
|
|
8
9
|
|
|
@@ -88,61 +89,8 @@ async function generateLucideRegistry() {
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
resolved.sort((a, b) => a.kebab.localeCompare(b.kebab))
|
|
92
|
-
const uniqueExports = [...new Set(resolved.map((r) => r.exportName))].sort((a, b) => a.localeCompare(b))
|
|
93
|
-
|
|
94
|
-
const importSection = uniqueExports.length
|
|
95
|
-
? `import {\n${uniqueExports.map((n) => ` ${n},`).join('\n')}\n} from 'lucide-react'\n`
|
|
96
|
-
: ``
|
|
97
|
-
|
|
98
|
-
const registryEntries = resolved.map((r) => ` '${r.kebab}': ${r.exportName},`).join('\n')
|
|
99
|
-
|
|
100
92
|
const outPath = join(packageDir, 'src/backend/icons/lucideRegistry.generated.tsx')
|
|
101
|
-
|
|
102
|
-
// AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.
|
|
103
|
-
// Generated from discovered icon string usages across the repo.
|
|
104
|
-
|
|
105
|
-
import type * as React from 'react'
|
|
106
|
-
import type { LucideIcon } from 'lucide-react'
|
|
107
|
-
${importSection}
|
|
108
|
-
export const LUCIDE_ICON_REGISTRY: Record<string, LucideIcon> = {
|
|
109
|
-
${registryEntries ? `${registryEntries}\n` : ''}}
|
|
110
|
-
|
|
111
|
-
function normalizeKebabIconName(input: string): string {
|
|
112
|
-
const trimmed = input.trim()
|
|
113
|
-
if (!trimmed) return ''
|
|
114
|
-
const withoutPrefix = trimmed.startsWith('lucide:') ? trimmed.slice('lucide:'.length) : trimmed
|
|
115
|
-
if (!withoutPrefix) return ''
|
|
116
|
-
if (!withoutPrefix.includes('-') && !withoutPrefix.includes('_') && !withoutPrefix.includes(' ') && /[A-Z]/.test(withoutPrefix)) {
|
|
117
|
-
return withoutPrefix
|
|
118
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
119
|
-
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
120
|
-
.toLowerCase()
|
|
121
|
-
}
|
|
122
|
-
return withoutPrefix
|
|
123
|
-
.replace(/[_\\s]+/g, '-')
|
|
124
|
-
.replace(/-+/g, '-')
|
|
125
|
-
.toLowerCase()
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function resolveRegisteredLucideIcon(name: string | undefined): LucideIcon | null {
|
|
129
|
-
if (!name) return null
|
|
130
|
-
const normalized = normalizeKebabIconName(name)
|
|
131
|
-
if (!normalized) return null
|
|
132
|
-
return (LUCIDE_ICON_REGISTRY as Record<string, LucideIcon | undefined>)[normalized] ?? null
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function resolveRegisteredLucideIconNode(
|
|
136
|
-
name: string | undefined,
|
|
137
|
-
className: string
|
|
138
|
-
): React.ReactNode | null {
|
|
139
|
-
const Icon = resolveRegisteredLucideIcon(name)
|
|
140
|
-
if (!Icon) return null
|
|
141
|
-
return <Icon className={className} />
|
|
142
|
-
}
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
writeFileSync(outPath, file)
|
|
93
|
+
writeFileSync(outPath, buildLucideRegistrySource(resolved))
|
|
146
94
|
console.log(`Generated lucide registry with ${resolved.length} icons -> ${outPath}`)
|
|
147
95
|
}
|
|
148
96
|
|
|
@@ -7,15 +7,15 @@ import { Progress } from "@open-mercato/ui/primitives/progress";
|
|
|
7
7
|
const STEP_STYLES = {
|
|
8
8
|
pending: "",
|
|
9
9
|
active: "border-primary/40 bg-primary/10 text-primary",
|
|
10
|
-
completed: "border-
|
|
10
|
+
completed: "border-status-success-border bg-status-success-bg text-status-success-text"
|
|
11
11
|
};
|
|
12
12
|
const STATUS_STYLES = {
|
|
13
13
|
default: "border-border bg-background/80 text-foreground",
|
|
14
14
|
info: "border-primary/20 bg-primary/5 text-primary",
|
|
15
|
-
success: "border-
|
|
16
|
-
warning: "border-
|
|
15
|
+
success: "border-status-success-border bg-status-success-bg text-status-success-text",
|
|
16
|
+
warning: "border-status-warning-border bg-status-warning-bg text-status-warning-text",
|
|
17
17
|
danger: "border-destructive/20 bg-destructive/5 text-destructive",
|
|
18
|
-
muted: "border-
|
|
18
|
+
muted: "border-status-neutral-border bg-status-neutral-bg text-status-neutral-text"
|
|
19
19
|
};
|
|
20
20
|
function NextStepCallout({
|
|
21
21
|
icon,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/backend/NextStepCallout.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\n\ntype NextStepCalloutStep = {\n id: string\n label: React.ReactNode\n state?: 'pending' | 'active' | 'completed'\n}\n\ntype NextStepCalloutStatusTone = 'default' | 'info' | 'success' | 'warning' | 'danger' | 'muted'\n\ntype NextStepCalloutStatus = {\n tone?: NextStepCalloutStatusTone\n icon?: React.ReactNode\n label: React.ReactNode\n badge?: React.ReactNode\n progressValue?: number | null\n progressDescription?: React.ReactNode\n errorMessage?: React.ReactNode\n}\n\ntype NextStepCalloutProps = {\n icon?: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n steps?: NextStepCalloutStep[]\n actionLabel: React.ReactNode\n actionIcon?: React.ReactNode\n onAction?: () => void\n disabled?: boolean\n disabledMessage?: React.ReactNode\n busy?: boolean\n status?: NextStepCalloutStatus | null\n className?: string\n}\n\nconst STEP_STYLES: Record<NonNullable<NextStepCalloutStep['state']>, string> = {\n pending: '',\n active: 'border-primary/40 bg-primary/10 text-primary',\n completed: 'border-
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\n\ntype NextStepCalloutStep = {\n id: string\n label: React.ReactNode\n state?: 'pending' | 'active' | 'completed'\n}\n\ntype NextStepCalloutStatusTone = 'default' | 'info' | 'success' | 'warning' | 'danger' | 'muted'\n\ntype NextStepCalloutStatus = {\n tone?: NextStepCalloutStatusTone\n icon?: React.ReactNode\n label: React.ReactNode\n badge?: React.ReactNode\n progressValue?: number | null\n progressDescription?: React.ReactNode\n errorMessage?: React.ReactNode\n}\n\ntype NextStepCalloutProps = {\n icon?: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n steps?: NextStepCalloutStep[]\n actionLabel: React.ReactNode\n actionIcon?: React.ReactNode\n onAction?: () => void\n disabled?: boolean\n disabledMessage?: React.ReactNode\n busy?: boolean\n status?: NextStepCalloutStatus | null\n className?: string\n}\n\nconst STEP_STYLES: Record<NonNullable<NextStepCalloutStep['state']>, string> = {\n pending: '',\n active: 'border-primary/40 bg-primary/10 text-primary',\n completed: 'border-status-success-border bg-status-success-bg text-status-success-text',\n}\n\nconst STATUS_STYLES: Record<NextStepCalloutStatusTone, string> = {\n default: 'border-border bg-background/80 text-foreground',\n info: 'border-primary/20 bg-primary/5 text-primary',\n success: 'border-status-success-border bg-status-success-bg text-status-success-text',\n warning: 'border-status-warning-border bg-status-warning-bg text-status-warning-text',\n danger: 'border-destructive/20 bg-destructive/5 text-destructive',\n muted: 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text',\n}\n\nexport function NextStepCallout({\n icon,\n title,\n description,\n steps,\n actionLabel,\n actionIcon,\n onAction,\n disabled = false,\n disabledMessage,\n busy = false,\n status,\n className,\n}: NextStepCalloutProps) {\n return (\n <div className={cn('rounded-xl border border-dashed border-primary/30 bg-primary/5 px-6 py-8', className)}>\n <div className=\"mx-auto flex max-w-2xl flex-col items-center text-center\">\n {icon ? (\n <div className=\"mb-4 flex h-14 w-14 items-center justify-center rounded-full border border-primary/30 bg-background text-primary\">\n {icon}\n </div>\n ) : null}\n <h4 className=\"text-lg font-semibold\">{title}</h4>\n {description ? (\n <p className=\"mt-2 text-sm text-muted-foreground\">{description}</p>\n ) : null}\n {steps && steps.length > 0 ? (\n <div className=\"mt-4 flex flex-wrap items-center justify-center gap-2\">\n {steps.map((step) => (\n <Badge\n key={step.id}\n variant=\"outline\"\n className={cn(step.state ? STEP_STYLES[step.state] : STEP_STYLES.pending)}\n >\n {step.label}\n </Badge>\n ))}\n </div>\n ) : null}\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"mt-6 min-w-72\"\n onClick={onAction}\n disabled={disabled || busy}\n >\n {actionIcon}\n {actionLabel}\n </Button>\n {disabledMessage ? (\n <p className=\"mt-3 text-xs text-muted-foreground\">{disabledMessage}</p>\n ) : null}\n {status ? (\n <div className={cn('mt-4 w-full rounded-lg border px-4 py-3 text-left', STATUS_STYLES[status.tone ?? 'default'])}>\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n {status.icon ? <span className=\"shrink-0\">{status.icon}</span> : null}\n <span>{status.label}</span>\n </div>\n {status.badge ? status.badge : null}\n </div>\n {typeof status.progressValue === 'number' ? (\n <Progress value={status.progressValue} className=\"mt-3 h-2\" />\n ) : busy ? (\n <div className=\"mt-3 h-2 rounded-full bg-secondary\" />\n ) : null}\n {status.progressDescription ? (\n <p className=\"mt-2 text-xs text-muted-foreground\">{status.progressDescription}</p>\n ) : null}\n {status.errorMessage ? (\n <p className=\"mt-2 text-xs text-destructive\">{status.errorMessage}</p>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": ";AA0EU,cAqBF,YArBE;AAvEV,SAAS,UAAU;AACnB,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,gBAAgB;AAmCzB,MAAM,cAAyE;AAAA,EAC7E,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,WAAW;AACb;AAEA,MAAM,gBAA2D;AAAA,EAC/D,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AACT;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AACF,GAAyB;AACvB,SACE,oBAAC,SAAI,WAAW,GAAG,4EAA4E,SAAS,GACtG,+BAAC,SAAI,WAAU,4DACZ;AAAA,WACC,oBAAC,SAAI,WAAU,oHACZ,gBACH,IACE;AAAA,IACJ,oBAAC,QAAG,WAAU,yBAAyB,iBAAM;AAAA,IAC5C,cACC,oBAAC,OAAE,WAAU,sCAAsC,uBAAY,IAC7D;AAAA,IACH,SAAS,MAAM,SAAS,IACvB,oBAAC,SAAI,WAAU,yDACZ,gBAAM,IAAI,CAAC,SACV;AAAA,MAAC;AAAA;AAAA,QAEC,SAAQ;AAAA,QACR,WAAW,GAAG,KAAK,QAAQ,YAAY,KAAK,KAAK,IAAI,YAAY,OAAO;AAAA,QAEvE,eAAK;AAAA;AAAA,MAJD,KAAK;AAAA,IAKZ,CACD,GACH,IACE;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU,YAAY;AAAA,QAErB;AAAA;AAAA,UACA;AAAA;AAAA;AAAA,IACH;AAAA,IACC,kBACC,oBAAC,OAAE,WAAU,sCAAsC,2BAAgB,IACjE;AAAA,IACH,SACC,qBAAC,SAAI,WAAW,GAAG,qDAAqD,cAAc,OAAO,QAAQ,SAAS,CAAC,GAC7G;AAAA,2BAAC,SAAI,WAAU,qDACb;AAAA,6BAAC,SAAI,WAAU,+CACZ;AAAA,iBAAO,OAAO,oBAAC,UAAK,WAAU,YAAY,iBAAO,MAAK,IAAU;AAAA,UACjE,oBAAC,UAAM,iBAAO,OAAM;AAAA,WACtB;AAAA,QACC,OAAO,QAAQ,OAAO,QAAQ;AAAA,SACjC;AAAA,MACC,OAAO,OAAO,kBAAkB,WAC/B,oBAAC,YAAS,OAAO,OAAO,eAAe,WAAU,YAAW,IAC1D,OACF,oBAAC,SAAI,WAAU,sCAAqC,IAClD;AAAA,MACH,OAAO,sBACN,oBAAC,OAAE,WAAU,sCAAsC,iBAAO,qBAAoB,IAC5E;AAAA,MACH,OAAO,eACN,oBAAC,OAAE,WAAU,iCAAiC,iBAAO,cAAa,IAChE;AAAA,OACN,IACE;AAAA,KACN,GACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -82,6 +82,18 @@ function ConfirmDialog({
|
|
|
82
82
|
dialog.addEventListener("cancel", handleCancel2);
|
|
83
83
|
return () => dialog.removeEventListener("cancel", handleCancel2);
|
|
84
84
|
}, [loading, requestClose]);
|
|
85
|
+
React.useEffect(() => {
|
|
86
|
+
if (!open) return;
|
|
87
|
+
const handleEscape = (event) => {
|
|
88
|
+
if (event.key !== "Escape") return;
|
|
89
|
+
if (!(event.target instanceof Node) || !dialogRef.current?.contains(event.target)) return;
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
if (!loading) requestClose();
|
|
93
|
+
};
|
|
94
|
+
window.addEventListener("keydown", handleEscape, true);
|
|
95
|
+
return () => window.removeEventListener("keydown", handleEscape, true);
|
|
96
|
+
}, [loading, open, requestClose]);
|
|
85
97
|
const handleBackdropClick = (e) => {
|
|
86
98
|
if (e.target === dialogRef.current && !loading) {
|
|
87
99
|
requestClose();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/confirm-dialog/ConfirmDialog.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { IconButton } from \"../../primitives/icon-button\";\nimport { cn } from \"@open-mercato/shared/lib/utils\";\nimport { Loader2, X } from \"lucide-react\";\n\nexport type ConfirmDialogProps = {\n /** Whether the dialog is open (controlled mode \u2014 used by useConfirmDialog) */\n open?: boolean;\n /** Callback when open state changes (controlled mode) */\n onOpenChange?: (open: boolean) => void;\n /** Callback when user confirms */\n onConfirm: () => void | Promise<void>;\n /** Callback when user cancels (optional, defaults to closing) */\n onCancel?: () => void;\n /** Dialog title. Defaults to i18n key \"ui.dialogs.confirm.defaultTitle\" (\"Are you sure?\") */\n title?: string;\n /** Dialog body text / description */\n text?: string;\n /** Confirm button label. Defaults to i18n \"ui.dialogs.confirm.confirmText\" (\"Confirm\").\n * Pass `false` to hide the confirm button entirely. */\n confirmText?: string | false;\n /** Cancel button label. Defaults to i18n \"ui.dialogs.confirm.cancelText\" (\"Cancel\").\n * Pass `false` to hide the cancel button entirely. */\n cancelText?: string | false;\n /** Visual variant \u2014 \"destructive\" renders the confirm button in red */\n variant?: \"default\" | \"destructive\";\n /** Whether the confirm button shows a loading spinner.\n * Useful for async onConfirm handlers (e.g., waiting for API response before closing). */\n loading?: boolean;\n /** Trigger element \u2014 when provided, component manages its own open state (declarative mode).\n * Clicking the trigger opens the dialog. */\n trigger?: React.ReactNode;\n};\n\nexport function ConfirmDialog({\n open: controlledOpen,\n onOpenChange,\n onConfirm,\n onCancel,\n title,\n text,\n confirmText,\n cancelText,\n variant = \"default\",\n loading = false,\n trigger,\n}: ConfirmDialogProps) {\n const t = useT();\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n const [internalOpen, setInternalOpen] = React.useState(false);\n const cancelButtonRef = React.useRef<HTMLButtonElement>(null);\n const confirmButtonRef = React.useRef<HTMLButtonElement>(null);\n const [portalTarget, setPortalTarget] = React.useState<HTMLElement | null>(null);\n // Unique IDs so multiple ConfirmDialog instances on the same page don't\n // collide and make `aria-labelledby` resolve to the wrong dialog's title.\n const reactId = React.useId();\n const titleId = `confirm-dialog-title-${reactId}`;\n const descriptionId = `confirm-dialog-description-${reactId}`;\n\n // Determine if we're in controlled mode (open prop provided) or declarative mode (trigger provided)\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = isControlled\n ? onOpenChange || (() => {})\n : setInternalOpen;\n const handleCancelCallback = React.useCallback(() => {\n if (!isControlled) {\n onCancel?.();\n }\n }, [isControlled, onCancel]);\n\n // Default text values from i18n\n const resolvedTitle =\n title ?? t(\"ui.dialogs.confirm.defaultTitle\", \"Are you sure?\");\n const resolvedConfirmText =\n confirmText === false\n ? false\n : confirmText ?? t(\"ui.dialogs.confirm.confirmText\", \"Confirm\");\n const resolvedCancelText =\n cancelText === false\n ? false\n : cancelText ?? t(\"ui.dialogs.confirm.cancelText\", \"Cancel\");\n const closeAriaLabel = t(\"ui.dialog.close.ariaLabel\", \"Close\");\n const requestClose = React.useCallback(() => {\n setOpen(false);\n handleCancelCallback();\n }, [setOpen, handleCancelCallback]);\n\n React.useLayoutEffect(() => {\n setPortalTarget(document.body);\n }, []);\n\n // Handle dialog open/close with native showModal/close\n React.useLayoutEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open) {\n if (!dialog.open) {\n dialog.showModal();\n // Focus cancel button (safe default) or confirm if no cancel\n setTimeout(() => {\n if (resolvedCancelText !== false && cancelButtonRef.current) {\n cancelButtonRef.current.focus();\n } else if (confirmButtonRef.current) {\n confirmButtonRef.current.focus();\n }\n }, 0);\n }\n } else {\n if (dialog.open) {\n dialog.close();\n }\n }\n }, [open, resolvedCancelText, portalTarget]);\n\n // Handle native cancel event (Escape key)\n React.useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleCancel = (e: Event) => {\n // Prevent close if loading\n if (loading) {\n e.preventDefault();\n return;\n }\n requestClose();\n };\n\n dialog.addEventListener(\"cancel\", handleCancel);\n return () => dialog.removeEventListener(\"cancel\", handleCancel);\n }, [loading, requestClose]);\n\n // Handle backdrop click\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n // Only close if clicking directly on the dialog (backdrop), not its children\n if (e.target === dialogRef.current && !loading) {\n requestClose();\n }\n };\n\n // Handle keyboard shortcuts\n React.useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Cmd/Ctrl+Enter confirms\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\" && !loading) {\n e.preventDefault();\n handleConfirm();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, loading]);\n\n const handleConfirm = async () => {\n await onConfirm();\n // Don't auto-close if loading \u2014 let the parent control when to close\n if (!loading) {\n setOpen(false);\n }\n };\n\n const handleCancel = () => {\n requestClose();\n };\n\n const handleTriggerClick = () => {\n if (trigger) {\n setOpen(true);\n }\n };\n\n const dialogElement = (\n <dialog\n ref={dialogRef}\n role=\"alertdialog\"\n aria-labelledby={titleId}\n aria-describedby={text ? descriptionId : undefined}\n onClick={handleBackdropClick}\n className={cn(\n // Reset dialog defaults\n \"m-0 p-0 max-w-none bg-transparent border-none pointer-events-auto\",\n // Backdrop styling\n \"backdrop:bg-black/50 backdrop:backdrop-blur-sm backdrop:transition-opacity\",\n // Mobile: bottom sheet\n \"fixed inset-x-0 bottom-0 top-auto w-full\",\n // Desktop: centered\n \"sm:inset-auto sm:mx-auto sm:my-auto sm:max-w-md sm:top-1/2 sm:left-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2\",\n // Animation with reduced motion support\n \"motion-safe:open:animate-in motion-safe:open:fade-in-0 motion-safe:open:slide-in-from-bottom-4\",\n \"sm:motion-safe:open:slide-in-from-bottom-0 sm:motion-safe:open:zoom-in-95\",\n // Duration\n \"motion-safe:open:duration-300\"\n )}\n >\n <div\n role=\"document\"\n className={cn(\n // Panel container\n \"flex flex-col gap-4 rounded-t-2xl border-t bg-card p-6 text-foreground shadow-lg\",\n \"sm:rounded-xl sm:border\",\n // Relative positioning for close button\n \"relative\"\n )}\n >\n {/* Close button */}\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={loading}\n aria-label={closeAriaLabel}\n className=\"absolute right-4 top-4 opacity-70 hover:opacity-100\"\n >\n <X className=\"h-4 w-4\" />\n </IconButton>\n\n {/* Title */}\n <h2\n id={titleId}\n className={cn(\n \"text-sm font-medium leading-snug tracking-tight pr-6\",\n // Mobile: centered, Desktop: left-aligned\n \"text-center sm:text-left\"\n )}\n >\n {resolvedTitle}\n </h2>\n\n {/* Description (optional) */}\n {text && (\n <p\n id={descriptionId}\n className=\"text-sm font-medium leading-snug text-muted-foreground\"\n >\n {text}\n </p>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n {resolvedCancelText !== false && (\n <Button\n ref={cancelButtonRef}\n variant=\"outline\"\n onClick={handleCancel}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {resolvedCancelText}\n </Button>\n )}\n {resolvedConfirmText !== false && (\n <Button\n ref={confirmButtonRef}\n variant={variant === \"destructive\" ? \"destructive\" : \"default\"}\n onClick={handleConfirm}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {loading && <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />}\n {resolvedConfirmText}\n </Button>\n )}\n </div>\n </div>\n </dialog>\n );\n\n return (\n <>\n {trigger && (\n <div onClick={handleTriggerClick} className=\"inline-block\" role=\"presentation\">\n {trigger}\n </div>\n )}\n\n {portalTarget ? createPortal(dialogElement, portalTarget) : null}\n </>\n );\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { IconButton } from \"../../primitives/icon-button\";\nimport { cn } from \"@open-mercato/shared/lib/utils\";\nimport { Loader2, X } from \"lucide-react\";\n\nexport type ConfirmDialogProps = {\n /** Whether the dialog is open (controlled mode \u2014 used by useConfirmDialog) */\n open?: boolean;\n /** Callback when open state changes (controlled mode) */\n onOpenChange?: (open: boolean) => void;\n /** Callback when user confirms */\n onConfirm: () => void | Promise<void>;\n /** Callback when user cancels (optional, defaults to closing) */\n onCancel?: () => void;\n /** Dialog title. Defaults to i18n key \"ui.dialogs.confirm.defaultTitle\" (\"Are you sure?\") */\n title?: string;\n /** Dialog body text / description */\n text?: string;\n /** Confirm button label. Defaults to i18n \"ui.dialogs.confirm.confirmText\" (\"Confirm\").\n * Pass `false` to hide the confirm button entirely. */\n confirmText?: string | false;\n /** Cancel button label. Defaults to i18n \"ui.dialogs.confirm.cancelText\" (\"Cancel\").\n * Pass `false` to hide the cancel button entirely. */\n cancelText?: string | false;\n /** Visual variant \u2014 \"destructive\" renders the confirm button in red */\n variant?: \"default\" | \"destructive\";\n /** Whether the confirm button shows a loading spinner.\n * Useful for async onConfirm handlers (e.g., waiting for API response before closing). */\n loading?: boolean;\n /** Trigger element \u2014 when provided, component manages its own open state (declarative mode).\n * Clicking the trigger opens the dialog. */\n trigger?: React.ReactNode;\n};\n\nexport function ConfirmDialog({\n open: controlledOpen,\n onOpenChange,\n onConfirm,\n onCancel,\n title,\n text,\n confirmText,\n cancelText,\n variant = \"default\",\n loading = false,\n trigger,\n}: ConfirmDialogProps) {\n const t = useT();\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n const [internalOpen, setInternalOpen] = React.useState(false);\n const cancelButtonRef = React.useRef<HTMLButtonElement>(null);\n const confirmButtonRef = React.useRef<HTMLButtonElement>(null);\n const [portalTarget, setPortalTarget] = React.useState<HTMLElement | null>(null);\n // Unique IDs so multiple ConfirmDialog instances on the same page don't\n // collide and make `aria-labelledby` resolve to the wrong dialog's title.\n const reactId = React.useId();\n const titleId = `confirm-dialog-title-${reactId}`;\n const descriptionId = `confirm-dialog-description-${reactId}`;\n\n // Determine if we're in controlled mode (open prop provided) or declarative mode (trigger provided)\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = isControlled\n ? onOpenChange || (() => {})\n : setInternalOpen;\n const handleCancelCallback = React.useCallback(() => {\n if (!isControlled) {\n onCancel?.();\n }\n }, [isControlled, onCancel]);\n\n // Default text values from i18n\n const resolvedTitle =\n title ?? t(\"ui.dialogs.confirm.defaultTitle\", \"Are you sure?\");\n const resolvedConfirmText =\n confirmText === false\n ? false\n : confirmText ?? t(\"ui.dialogs.confirm.confirmText\", \"Confirm\");\n const resolvedCancelText =\n cancelText === false\n ? false\n : cancelText ?? t(\"ui.dialogs.confirm.cancelText\", \"Cancel\");\n const closeAriaLabel = t(\"ui.dialog.close.ariaLabel\", \"Close\");\n const requestClose = React.useCallback(() => {\n setOpen(false);\n handleCancelCallback();\n }, [setOpen, handleCancelCallback]);\n\n React.useLayoutEffect(() => {\n setPortalTarget(document.body);\n }, []);\n\n // Handle dialog open/close with native showModal/close\n React.useLayoutEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open) {\n if (!dialog.open) {\n dialog.showModal();\n // Focus cancel button (safe default) or confirm if no cancel\n setTimeout(() => {\n if (resolvedCancelText !== false && cancelButtonRef.current) {\n cancelButtonRef.current.focus();\n } else if (confirmButtonRef.current) {\n confirmButtonRef.current.focus();\n }\n }, 0);\n }\n } else {\n if (dialog.open) {\n dialog.close();\n }\n }\n }, [open, resolvedCancelText, portalTarget]);\n\n // Handle native cancel event (Escape key)\n React.useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleCancel = (e: Event) => {\n // Prevent close if loading\n if (loading) {\n e.preventDefault();\n return;\n }\n requestClose();\n };\n\n dialog.addEventListener(\"cancel\", handleCancel);\n return () => dialog.removeEventListener(\"cancel\", handleCancel);\n }, [loading, requestClose]);\n\n React.useEffect(() => {\n if (!open) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n if (!(event.target instanceof Node) || !dialogRef.current?.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n if (!loading) requestClose();\n };\n\n window.addEventListener(\"keydown\", handleEscape, true);\n return () => window.removeEventListener(\"keydown\", handleEscape, true);\n }, [loading, open, requestClose]);\n\n // Handle backdrop click\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n // Only close if clicking directly on the dialog (backdrop), not its children\n if (e.target === dialogRef.current && !loading) {\n requestClose();\n }\n };\n\n // Handle keyboard shortcuts\n React.useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Cmd/Ctrl+Enter confirms\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\" && !loading) {\n e.preventDefault();\n handleConfirm();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, loading]);\n\n const handleConfirm = async () => {\n await onConfirm();\n // Don't auto-close if loading \u2014 let the parent control when to close\n if (!loading) {\n setOpen(false);\n }\n };\n\n const handleCancel = () => {\n requestClose();\n };\n\n const handleTriggerClick = () => {\n if (trigger) {\n setOpen(true);\n }\n };\n\n const dialogElement = (\n <dialog\n ref={dialogRef}\n role=\"alertdialog\"\n aria-labelledby={titleId}\n aria-describedby={text ? descriptionId : undefined}\n onClick={handleBackdropClick}\n className={cn(\n // Reset dialog defaults\n \"m-0 p-0 max-w-none bg-transparent border-none pointer-events-auto\",\n // Backdrop styling\n \"backdrop:bg-black/50 backdrop:backdrop-blur-sm backdrop:transition-opacity\",\n // Mobile: bottom sheet\n \"fixed inset-x-0 bottom-0 top-auto w-full\",\n // Desktop: centered\n \"sm:inset-auto sm:mx-auto sm:my-auto sm:max-w-md sm:top-1/2 sm:left-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2\",\n // Animation with reduced motion support\n \"motion-safe:open:animate-in motion-safe:open:fade-in-0 motion-safe:open:slide-in-from-bottom-4\",\n \"sm:motion-safe:open:slide-in-from-bottom-0 sm:motion-safe:open:zoom-in-95\",\n // Duration\n \"motion-safe:open:duration-300\"\n )}\n >\n <div\n role=\"document\"\n className={cn(\n // Panel container\n \"flex flex-col gap-4 rounded-t-2xl border-t bg-card p-6 text-foreground shadow-lg\",\n \"sm:rounded-xl sm:border\",\n // Relative positioning for close button\n \"relative\"\n )}\n >\n {/* Close button */}\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={loading}\n aria-label={closeAriaLabel}\n className=\"absolute right-4 top-4 opacity-70 hover:opacity-100\"\n >\n <X className=\"h-4 w-4\" />\n </IconButton>\n\n {/* Title */}\n <h2\n id={titleId}\n className={cn(\n \"text-sm font-medium leading-snug tracking-tight pr-6\",\n // Mobile: centered, Desktop: left-aligned\n \"text-center sm:text-left\"\n )}\n >\n {resolvedTitle}\n </h2>\n\n {/* Description (optional) */}\n {text && (\n <p\n id={descriptionId}\n className=\"text-sm font-medium leading-snug text-muted-foreground\"\n >\n {text}\n </p>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n {resolvedCancelText !== false && (\n <Button\n ref={cancelButtonRef}\n variant=\"outline\"\n onClick={handleCancel}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {resolvedCancelText}\n </Button>\n )}\n {resolvedConfirmText !== false && (\n <Button\n ref={confirmButtonRef}\n variant={variant === \"destructive\" ? \"destructive\" : \"default\"}\n onClick={handleConfirm}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {loading && <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />}\n {resolvedConfirmText}\n </Button>\n )}\n </div>\n </div>\n </dialog>\n );\n\n return (\n <>\n {trigger && (\n <div onClick={handleTriggerClick} className=\"inline-block\" role=\"presentation\">\n {trigger}\n </div>\n )}\n\n {portalTarget ? createPortal(dialogElement, portalTarget) : null}\n </>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["handleCancel"]
|
|
7
7
|
}
|
|
@@ -7,7 +7,7 @@ import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
|
7
7
|
import { TabEmptyState } from "@open-mercato/ui/backend/detail";
|
|
8
8
|
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
|
|
9
9
|
import { normalizeCoordinateInput, validateCoordinateInput } from "@open-mercato/shared/lib/location/coordinates";
|
|
10
|
-
import { AddressView
|
|
10
|
+
import { AddressView } from "./addressFormat.js";
|
|
11
11
|
import AddressEditor from "./AddressEditor.js";
|
|
12
12
|
const defaultDraft = {
|
|
13
13
|
name: "",
|
|
@@ -78,7 +78,7 @@ function AddressTiles({
|
|
|
78
78
|
t,
|
|
79
79
|
emptyLabel,
|
|
80
80
|
isSubmitting = false,
|
|
81
|
-
gridClassName = "grid grid-cols-
|
|
81
|
+
gridClassName = "grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] gap-2 sm:gap-4",
|
|
82
82
|
hideAddButton = false,
|
|
83
83
|
onAddActionChange,
|
|
84
84
|
emptyStateTitle,
|
|
@@ -348,7 +348,7 @@ function AddressTiles({
|
|
|
348
348
|
addressTypesContext
|
|
349
349
|
}
|
|
350
350
|
),
|
|
351
|
-
generalError ? /* @__PURE__ */ jsx("p", { className: "text-xs text-
|
|
351
|
+
generalError ? /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error-text", children: generalError }) : null,
|
|
352
352
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2", children: [
|
|
353
353
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: handleCancel, disabled: disableActions, children: label("cancel", "Cancel") }),
|
|
354
354
|
/* @__PURE__ */ jsx(Button, { type: "button", onClick: handleSave, disabled: disableActions, children: saving ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -412,8 +412,7 @@ function AddressTiles({
|
|
|
412
412
|
address.isPrimary ? /* @__PURE__ */ jsx("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-overline font-semibold uppercase", children: label("primaryBadge", "Primary") }) : null
|
|
413
413
|
] }),
|
|
414
414
|
address.purpose ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: address.purpose }) : null,
|
|
415
|
-
/* @__PURE__ */ jsx(AddressView, { address, format, className: "text-sm text-foreground" })
|
|
416
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: formatAddressString(address, format) })
|
|
415
|
+
/* @__PURE__ */ jsx(AddressView, { address, format, className: "text-sm text-foreground" })
|
|
417
416
|
] }),
|
|
418
417
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 opacity-100 md:opacity-0 transition-opacity md:group-hover:opacity-100 focus-within:opacity-100", children: [
|
|
419
418
|
/* @__PURE__ */ jsx(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/detail/AddressTiles.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, Plus, Trash2, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { normalizeCoordinateInput, validateCoordinateInput } from '@open-mercato/shared/lib/location/coordinates'\nimport { AddressView, formatAddressString, type AddressFormatStrategy } from './addressFormat'\nimport AddressEditor, { type AddressTypesAdapter } from './AddressEditor'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\n\nexport type Translator = (\n key: string,\n fallback?: string,\n params?: Record<string, string | number>,\n) => string\n\nexport type AddressInput = {\n name?: string\n purpose?: string\n companyName?: string\n addressLine1: string\n addressLine2?: string\n buildingNumber?: string\n flatNumber?: string\n city?: string\n region?: string\n postalCode?: string\n country?: string\n latitude?: number | null\n longitude?: number | null\n isPrimary?: boolean\n}\n\nexport type AddressValue = AddressInput & {\n id: string\n purpose?: string | null\n companyName?: string | null\n latitude?: number | null\n longitude?: number | null\n}\n\ntype AddressTilesProps<C = unknown> = {\n addresses: AddressValue[]\n onCreate: (payload: AddressInput) => Promise<void> | void\n onUpdate?: (id: string, payload: AddressInput) => Promise<void> | void\n onDelete?: (id: string) => Promise<void> | void\n t: Translator\n emptyLabel: string\n isSubmitting?: boolean\n gridClassName?: string\n hideAddButton?: boolean\n onAddActionChange?: (action: { openCreateForm: () => void; addDisabled: boolean } | null) => void\n emptyStateTitle?: string\n emptyStateActionLabel?: string\n labelPrefix?: string\n showCoordinateFields?: boolean\n addressTypesAdapter?: AddressTypesAdapter<C>\n addressTypesContext?: C\n loadFormat?: (context?: C) => Promise<AddressFormatStrategy>\n formatContext?: C\n}\n\ntype DraftAddressState = {\n name: string\n purpose: string\n companyName: string\n addressLine1: string\n addressLine2: string\n buildingNumber: string\n flatNumber: string\n city: string\n region: string\n postalCode: string\n country: string\n latitude: string\n longitude: string\n isPrimary: boolean\n}\n\ntype DraftFieldKey = keyof DraftAddressState\n\ntype AddressValidationDetail = {\n path?: Array<string | number>\n code?: string\n message?: string\n minimum?: number\n maximum?: number\n type?: string\n}\n\nconst defaultDraft: DraftAddressState = {\n name: '',\n purpose: '',\n companyName: '',\n addressLine1: '',\n addressLine2: '',\n buildingNumber: '',\n flatNumber: '',\n city: '',\n region: '',\n postalCode: '',\n country: '',\n latitude: '',\n longitude: '',\n isPrimary: false,\n}\n\nconst serverFieldMap: Record<string, DraftFieldKey> = {\n name: 'name',\n purpose: 'purpose',\n companyName: 'companyName',\n addressLine1: 'addressLine1',\n addressLine2: 'addressLine2',\n buildingNumber: 'buildingNumber',\n flatNumber: 'flatNumber',\n city: 'city',\n region: 'region',\n postalCode: 'postalCode',\n country: 'country',\n latitude: 'latitude',\n longitude: 'longitude',\n isPrimary: 'isPrimary',\n}\n\nfunction normalizeOptional(value: string): string | undefined {\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nfunction extractValidationDetails(error: unknown): AddressValidationDetail[] {\n if (!error || typeof error !== 'object') return []\n const candidate = (error as { details?: unknown }).details\n if (!Array.isArray(candidate)) return []\n return candidate\n .map((entry) => (entry && typeof entry === 'object' ? (entry as AddressValidationDetail) : null))\n .filter((entry): entry is AddressValidationDetail => entry !== null)\n}\n\nfunction resolveFieldMessage(detail: AddressValidationDetail, fieldLabel: string, t: Translator, prefix: string): string {\n const label = (suffix: string, fallback: string) => t(`${prefix}.${suffix}`, fallback)\n switch (detail.code) {\n case 'invalid_type':\n return label('validation.invalid', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n case 'too_small':\n if (detail.minimum === 1 && detail.type === 'string') {\n return label('validation.required', '{{field}} is required').replace('{{field}}', fieldLabel)\n }\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n case 'too_big':\n if (typeof detail.maximum === 'number') {\n return label('validation.tooLong', '{{field}} is too long').replace('{{field}}', fieldLabel)\n .replace('{{max}}', `${detail.maximum}`)\n }\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n default:\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n }\n}\n\nexport function AddressTiles<C = unknown>({\n addresses,\n onCreate,\n onUpdate,\n onDelete,\n t,\n emptyLabel,\n isSubmitting = false,\n gridClassName = 'grid grid-cols-1 gap-2 sm:gap-4 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4',\n hideAddButton = false,\n onAddActionChange,\n emptyStateTitle,\n emptyStateActionLabel,\n labelPrefix = 'customers.people.detail.addresses',\n showCoordinateFields = false,\n addressTypesAdapter,\n addressTypesContext,\n loadFormat,\n formatContext,\n}: AddressTilesProps<C>) {\n const scopeVersion = useOrganizationScopeVersion()\n const [isFormOpen, setIsFormOpen] = React.useState(false)\n const [editingId, setEditingId] = React.useState<string | null>(null)\n const [draft, setDraft] = React.useState<DraftAddressState>(defaultDraft)\n const [saving, setSaving] = React.useState(false)\n const [deletingId, setDeletingId] = React.useState<string | null>(null)\n const [generalError, setGeneralError] = React.useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = React.useState<Partial<Record<DraftFieldKey, string>>>({})\n const [format, setFormat] = React.useState<AddressFormatStrategy>('line_first')\n const [formatLoading, setFormatLoading] = React.useState(false)\n\n const label = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback, params),\n [labelPrefix, t],\n )\n\n const fieldLabels = React.useMemo(\n () => ({\n name: label('fields.label', 'Label'),\n purpose: label('fields.type', 'Address type'),\n companyName: label('fields.companyName', 'Company name'),\n addressLine1: label('fields.line1', 'Address line 1'),\n addressLine2: label('fields.line2', 'Address line 2'),\n street: label('fields.street', 'Street'),\n buildingNumber: label('fields.buildingNumber', 'Building number'),\n flatNumber: label('fields.flatNumber', 'Flat number'),\n city: label('fields.city', 'City'),\n region: label('fields.region', 'Region'),\n postalCode: label('fields.postalCode', 'Postal code'),\n country: label('fields.country', 'Country'),\n latitude: label('fields.latitude', 'Latitude'),\n longitude: label('fields.longitude', 'Longitude'),\n isPrimary: label('fields.primary', 'Primary address'),\n }),\n [label],\n )\n const line1FieldLabel = React.useMemo(\n () => (format === 'street_first' ? fieldLabels.street : fieldLabels.addressLine1),\n [fieldLabels.addressLine1, fieldLabels.street, format],\n )\n\n const resetForm = React.useCallback(() => {\n setDraft(defaultDraft)\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(null)\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFormatValue() {\n if (!loadFormat) {\n setFormat('line_first')\n setFormatLoading(false)\n return\n }\n setFormatLoading(true)\n try {\n const value = await loadFormat(formatContext)\n if (!cancelled && (value === 'street_first' || value === 'line_first')) {\n setFormat(value)\n }\n } catch (err) {\n if (!cancelled) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setFormatLoading(false)\n }\n }\n void loadFormatValue()\n return () => {\n cancelled = true\n }\n }, [formatContext, label, loadFormat, scopeVersion])\n\n const openCreateForm = React.useCallback(() => {\n resetForm()\n setIsFormOpen(true)\n }, [resetForm])\n\n const handleCancel = React.useCallback(() => {\n resetForm()\n setIsFormOpen(false)\n }, [resetForm])\n\n const handleEdit = React.useCallback((value: AddressValue) => {\n setDraft({\n name: value.name ?? '',\n purpose: value.purpose ?? '',\n companyName: value.companyName ?? '',\n addressLine1: value.addressLine1 ?? '',\n addressLine2: value.addressLine2 ?? '',\n buildingNumber: value.buildingNumber ?? '',\n flatNumber: value.flatNumber ?? '',\n city: value.city ?? '',\n region: value.region ?? '',\n postalCode: value.postalCode ?? '',\n country: value.country ?? '',\n latitude: value.latitude != null ? String(value.latitude) : '',\n longitude: value.longitude != null ? String(value.longitude) : '',\n isPrimary: value.isPrimary ?? false,\n })\n setEditingId(value.id)\n setIsFormOpen(true)\n setFieldErrors({})\n setGeneralError(null)\n }, [])\n\n const validate = React.useCallback((): boolean => {\n const errors: Partial<Record<DraftFieldKey, string>> = {}\n if (!draft.addressLine1.trim()) {\n errors.addressLine1 = label('validation.required', '{{field}} is required').replace('{{field}}', line1FieldLabel)\n }\n for (const key of ['latitude', 'longitude'] as const) {\n const result = validateCoordinateInput(key, draft[key])\n if (result.status === 'invalid') {\n errors[key] = label('validation.invalid', 'Invalid value for {{field}}').replace('{{field}}', fieldLabels[key])\n } else if (result.status === 'outOfRange') {\n errors[key] = label('validation.coordinateRange', '{{field}} must be between {{min}} and {{max}}')\n .replace('{{field}}', fieldLabels[key])\n .replace('{{min}}', `${result.min}`)\n .replace('{{max}}', `${result.max}`)\n }\n }\n if (Object.keys(errors).length > 0) {\n setFieldErrors(errors)\n return false\n }\n return true\n }, [draft.addressLine1, draft.latitude, draft.longitude, fieldLabels, label, line1FieldLabel])\n\n const handleSave = React.useCallback(async () => {\n if (!validate()) return\n setSaving(true)\n setGeneralError(null)\n try {\n const payload: AddressInput = {\n name: normalizeOptional(draft.name),\n purpose: normalizeOptional(draft.purpose),\n companyName: normalizeOptional(draft.companyName),\n addressLine1: draft.addressLine1.trim(),\n addressLine2: normalizeOptional(draft.addressLine2),\n buildingNumber: normalizeOptional(draft.buildingNumber),\n flatNumber: normalizeOptional(draft.flatNumber),\n city: normalizeOptional(draft.city),\n region: normalizeOptional(draft.region),\n postalCode: normalizeOptional(draft.postalCode),\n country: normalizeOptional(draft.country)?.toUpperCase(),\n // On edit, an emptied coordinate must be sent as `null` to clear the stored value; omitting\n // it (undefined) makes the partial-update handler keep the old coordinate. On create there is\n // nothing to clear, so leave it undefined (omitted).\n latitude: normalizeCoordinateInput(draft.latitude) ?? (editingId ? null : undefined),\n longitude: normalizeCoordinateInput(draft.longitude) ?? (editingId ? null : undefined),\n isPrimary: draft.isPrimary,\n }\n if (editingId && onUpdate) {\n await onUpdate(editingId, payload)\n } else {\n await onCreate(payload)\n }\n resetForm()\n setIsFormOpen(false)\n } catch (err) {\n const details = extractValidationDetails(err)\n if (details.length) {\n const nextErrors: Partial<Record<DraftFieldKey, string>> = {}\n details.forEach((detail) => {\n const path = Array.isArray(detail.path) ? detail.path : []\n const key = typeof path[0] === 'string' ? path[0] : undefined\n if (!key) return\n const fieldKey = serverFieldMap[key]\n if (!fieldKey) return\n const fieldLabel = fieldKey === 'addressLine1' ? line1FieldLabel : (fieldLabels[fieldKey] ?? key)\n nextErrors[fieldKey] = resolveFieldMessage(detail, fieldLabel, t, labelPrefix)\n })\n setFieldErrors(nextErrors)\n setGeneralError(label('validation.summary', 'Please fix the highlighted fields.'))\n return\n }\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('error', 'Failed to save address')\n setGeneralError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, editingId, fieldLabels, label, labelPrefix, onCreate, onUpdate, resetForm, t, validate])\n\n const handleDelete = React.useCallback(\n async (id: string) => {\n if (!onDelete) return\n setDeletingId(id)\n try {\n await onDelete(id)\n if (editingId === id) {\n resetForm()\n setIsFormOpen(false)\n }\n } catch (err) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('error', 'Failed to delete address')\n flash(message, 'error')\n } finally {\n setDeletingId(null)\n }\n },\n [editingId, label, onDelete, resetForm]\n )\n\n const disableActions = saving || isSubmitting || deletingId !== null\n const isEditing = editingId !== null\n const addDisabled = disableActions || isEditing\n const hasAddresses = addresses.length > 0\n const emptyTitle = emptyStateTitle ?? emptyLabel\n const emptyActionLabel = emptyStateActionLabel ?? label('add', 'Add address')\n\n React.useEffect(() => {\n if (!onAddActionChange) return\n onAddActionChange({ openCreateForm, addDisabled })\n }, [onAddActionChange, openCreateForm, addDisabled])\n\n React.useEffect(\n () => () => {\n if (onAddActionChange) onAddActionChange(null)\n },\n [onAddActionChange]\n )\n\n const renderFormTile = React.useCallback(\n (key: string) => (\n <div\n key={key}\n className=\"rounded-lg border-2 border-dashed border-muted-foreground/50 bg-muted/30 p-4 text-sm\"\n onKeyDown={(event) => {\n if (!(event.metaKey || event.ctrlKey)) return\n if (event.key !== 'Enter') return\n event.preventDefault()\n if (disableActions) return\n void handleSave()\n }}\n >\n <div className=\"flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n <span>\n {editingId\n ? label('editTitle', 'Edit address')\n : label('addTitle', 'Add address')}\n </span>\n <Button type=\"button\" variant=\"ghost\" size=\"icon\" onClick={handleCancel} disabled={disableActions}>\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"mt-3 space-y-3\">\n {formatLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {label('formatLoading', 'Loading address preferences\u2026')}\n </p>\n ) : null}\n <AddressEditor\n value={draft}\n onChange={(next) => {\n setDraft({ ...next, latitude: next.latitude ?? '', longitude: next.longitude ?? '' })\n if (Object.keys(fieldErrors).length) {\n const nextErrors = { ...fieldErrors }\n ;(Object.keys(nextErrors) as DraftFieldKey[]).forEach((key) => {\n const candidate = (next as Record<string, unknown>)[key]\n if (candidate !== undefined && candidate !== null && `${candidate}`.length) {\n delete nextErrors[key]\n }\n })\n setFieldErrors(nextErrors)\n }\n }}\n format={format}\n t={t}\n disabled={disableActions}\n errors={fieldErrors}\n showFormatHint={!formatLoading}\n showCoordinateFields={showCoordinateFields}\n labelPrefix={labelPrefix}\n addressTypesAdapter={addressTypesAdapter}\n addressTypesContext={addressTypesContext}\n />\n {generalError ? <p className=\"text-xs text-red-600\">{generalError}</p> : null}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={handleCancel} disabled={disableActions}>\n {label('cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" onClick={handleSave} disabled={disableActions}>\n {saving ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {editingId\n ? label('updating', 'Updating\u2026')\n : label('saving', 'Saving\u2026')}\n </>\n ) : editingId ? (\n label('update', 'Update address')\n ) : (\n label('save', 'Save address')\n )}\n </Button>\n </div>\n </div>\n </div>\n ),\n [\n addressTypesAdapter,\n addressTypesContext,\n disableActions,\n draft,\n editingId,\n fieldErrors,\n format,\n formatLoading,\n handleCancel,\n handleSave,\n generalError,\n label,\n labelPrefix,\n saving,\n showCoordinateFields,\n t,\n ]\n )\n\n return (\n <div className=\"space-y-4\">\n {!hideAddButton && hasAddresses ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openCreateForm}\n disabled={addDisabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {label('add', 'Add address')}\n </Button>\n </div>\n ) : null}\n {hasAddresses ? (\n <div className={gridClassName}>\n {addresses.map((address) => {\n if (isFormOpen && editingId === address.id) {\n return renderFormTile(`form-${address.id}`)\n }\n const isDeleting = deletingId === address.id\n return (\n <div\n key={address.id}\n className=\"group rounded-lg border border-border/70 bg-card p-4 text-sm transition hover:border-border\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-sm font-semibold text-foreground\">\n {address.name ?? label('labelFallback', 'Address')}\n </p>\n {address.isPrimary ? (\n <span className=\"rounded-full border border-border bg-muted px-2 py-0.5 text-overline font-semibold uppercase\">\n {label('primaryBadge', 'Primary')}\n </span>\n ) : null}\n </div>\n {address.purpose ? (\n <p className=\"text-xs text-muted-foreground\">\n {address.purpose}\n </p>\n ) : null}\n <AddressView address={address} format={format} className=\"text-sm text-foreground\" />\n <p className=\"text-xs text-muted-foreground\">\n {formatAddressString(address, format)}\n </p>\n </div>\n <div className=\"flex items-center gap-1 opacity-100 md:opacity-0 transition-opacity md:group-hover:opacity-100 focus-within:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleEdit(address)}\n disabled={disableActions}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleDelete(address.id)}\n disabled={disableActions}\n >\n {isDeleting ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n </div>\n )\n })}\n {isFormOpen && !editingId ? renderFormTile('create') : null}\n </div>\n ) : isFormOpen ? (\n <div className={gridClassName}>\n {renderFormTile('create')}\n </div>\n ) : (\n <TabEmptyState\n title={emptyTitle}\n action={{\n label: emptyActionLabel,\n onClick: openCreateForm,\n disabled: addDisabled,\n }}\n />\n )}\n </div>\n )\n}\n\nexport default AddressTiles\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, Plus, Trash2, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { TabEmptyState } from '@open-mercato/ui/backend/detail'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { normalizeCoordinateInput, validateCoordinateInput } from '@open-mercato/shared/lib/location/coordinates'\nimport { AddressView, type AddressFormatStrategy } from './addressFormat'\nimport AddressEditor, { type AddressTypesAdapter } from './AddressEditor'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@open-mercato/ui/primitives/dialog'\n\nexport type Translator = (\n key: string,\n fallback?: string,\n params?: Record<string, string | number>,\n) => string\n\nexport type AddressInput = {\n name?: string\n purpose?: string\n companyName?: string\n addressLine1: string\n addressLine2?: string\n buildingNumber?: string\n flatNumber?: string\n city?: string\n region?: string\n postalCode?: string\n country?: string\n latitude?: number | null\n longitude?: number | null\n isPrimary?: boolean\n}\n\nexport type AddressValue = AddressInput & {\n id: string\n purpose?: string | null\n companyName?: string | null\n latitude?: number | null\n longitude?: number | null\n}\n\ntype AddressTilesProps<C = unknown> = {\n addresses: AddressValue[]\n onCreate: (payload: AddressInput) => Promise<void> | void\n onUpdate?: (id: string, payload: AddressInput) => Promise<void> | void\n onDelete?: (id: string) => Promise<void> | void\n t: Translator\n emptyLabel: string\n isSubmitting?: boolean\n gridClassName?: string\n hideAddButton?: boolean\n onAddActionChange?: (action: { openCreateForm: () => void; addDisabled: boolean } | null) => void\n emptyStateTitle?: string\n emptyStateActionLabel?: string\n labelPrefix?: string\n showCoordinateFields?: boolean\n addressTypesAdapter?: AddressTypesAdapter<C>\n addressTypesContext?: C\n loadFormat?: (context?: C) => Promise<AddressFormatStrategy>\n formatContext?: C\n}\n\ntype DraftAddressState = {\n name: string\n purpose: string\n companyName: string\n addressLine1: string\n addressLine2: string\n buildingNumber: string\n flatNumber: string\n city: string\n region: string\n postalCode: string\n country: string\n latitude: string\n longitude: string\n isPrimary: boolean\n}\n\ntype DraftFieldKey = keyof DraftAddressState\n\ntype AddressValidationDetail = {\n path?: Array<string | number>\n code?: string\n message?: string\n minimum?: number\n maximum?: number\n type?: string\n}\n\nconst defaultDraft: DraftAddressState = {\n name: '',\n purpose: '',\n companyName: '',\n addressLine1: '',\n addressLine2: '',\n buildingNumber: '',\n flatNumber: '',\n city: '',\n region: '',\n postalCode: '',\n country: '',\n latitude: '',\n longitude: '',\n isPrimary: false,\n}\n\nconst serverFieldMap: Record<string, DraftFieldKey> = {\n name: 'name',\n purpose: 'purpose',\n companyName: 'companyName',\n addressLine1: 'addressLine1',\n addressLine2: 'addressLine2',\n buildingNumber: 'buildingNumber',\n flatNumber: 'flatNumber',\n city: 'city',\n region: 'region',\n postalCode: 'postalCode',\n country: 'country',\n latitude: 'latitude',\n longitude: 'longitude',\n isPrimary: 'isPrimary',\n}\n\nfunction normalizeOptional(value: string): string | undefined {\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nfunction extractValidationDetails(error: unknown): AddressValidationDetail[] {\n if (!error || typeof error !== 'object') return []\n const candidate = (error as { details?: unknown }).details\n if (!Array.isArray(candidate)) return []\n return candidate\n .map((entry) => (entry && typeof entry === 'object' ? (entry as AddressValidationDetail) : null))\n .filter((entry): entry is AddressValidationDetail => entry !== null)\n}\n\nfunction resolveFieldMessage(detail: AddressValidationDetail, fieldLabel: string, t: Translator, prefix: string): string {\n const label = (suffix: string, fallback: string) => t(`${prefix}.${suffix}`, fallback)\n switch (detail.code) {\n case 'invalid_type':\n return label('validation.invalid', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n case 'too_small':\n if (detail.minimum === 1 && detail.type === 'string') {\n return label('validation.required', '{{field}} is required').replace('{{field}}', fieldLabel)\n }\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n case 'too_big':\n if (typeof detail.maximum === 'number') {\n return label('validation.tooLong', '{{field}} is too long').replace('{{field}}', fieldLabel)\n .replace('{{max}}', `${detail.maximum}`)\n }\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n default:\n return label('validation.generic', 'Invalid value for {{field}}').replace('{{field}}', fieldLabel)\n }\n}\n\nexport function AddressTiles<C = unknown>({\n addresses,\n onCreate,\n onUpdate,\n onDelete,\n t,\n emptyLabel,\n isSubmitting = false,\n gridClassName = 'grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] gap-2 sm:gap-4',\n hideAddButton = false,\n onAddActionChange,\n emptyStateTitle,\n emptyStateActionLabel,\n labelPrefix = 'customers.people.detail.addresses',\n showCoordinateFields = false,\n addressTypesAdapter,\n addressTypesContext,\n loadFormat,\n formatContext,\n}: AddressTilesProps<C>) {\n const scopeVersion = useOrganizationScopeVersion()\n const [isFormOpen, setIsFormOpen] = React.useState(false)\n const [editingId, setEditingId] = React.useState<string | null>(null)\n const [draft, setDraft] = React.useState<DraftAddressState>(defaultDraft)\n const [saving, setSaving] = React.useState(false)\n const [deletingId, setDeletingId] = React.useState<string | null>(null)\n const [generalError, setGeneralError] = React.useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = React.useState<Partial<Record<DraftFieldKey, string>>>({})\n const [format, setFormat] = React.useState<AddressFormatStrategy>('line_first')\n const [formatLoading, setFormatLoading] = React.useState(false)\n\n const label = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback, params),\n [labelPrefix, t],\n )\n\n const fieldLabels = React.useMemo(\n () => ({\n name: label('fields.label', 'Label'),\n purpose: label('fields.type', 'Address type'),\n companyName: label('fields.companyName', 'Company name'),\n addressLine1: label('fields.line1', 'Address line 1'),\n addressLine2: label('fields.line2', 'Address line 2'),\n street: label('fields.street', 'Street'),\n buildingNumber: label('fields.buildingNumber', 'Building number'),\n flatNumber: label('fields.flatNumber', 'Flat number'),\n city: label('fields.city', 'City'),\n region: label('fields.region', 'Region'),\n postalCode: label('fields.postalCode', 'Postal code'),\n country: label('fields.country', 'Country'),\n latitude: label('fields.latitude', 'Latitude'),\n longitude: label('fields.longitude', 'Longitude'),\n isPrimary: label('fields.primary', 'Primary address'),\n }),\n [label],\n )\n const line1FieldLabel = React.useMemo(\n () => (format === 'street_first' ? fieldLabels.street : fieldLabels.addressLine1),\n [fieldLabels.addressLine1, fieldLabels.street, format],\n )\n\n const resetForm = React.useCallback(() => {\n setDraft(defaultDraft)\n setFieldErrors({})\n setGeneralError(null)\n setEditingId(null)\n }, [])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFormatValue() {\n if (!loadFormat) {\n setFormat('line_first')\n setFormatLoading(false)\n return\n }\n setFormatLoading(true)\n try {\n const value = await loadFormat(formatContext)\n if (!cancelled && (value === 'street_first' || value === 'line_first')) {\n setFormat(value)\n }\n } catch (err) {\n if (!cancelled) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('formatLoadError', 'Failed to load address configuration')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setFormatLoading(false)\n }\n }\n void loadFormatValue()\n return () => {\n cancelled = true\n }\n }, [formatContext, label, loadFormat, scopeVersion])\n\n const openCreateForm = React.useCallback(() => {\n resetForm()\n setIsFormOpen(true)\n }, [resetForm])\n\n const handleCancel = React.useCallback(() => {\n resetForm()\n setIsFormOpen(false)\n }, [resetForm])\n\n const handleEdit = React.useCallback((value: AddressValue) => {\n setDraft({\n name: value.name ?? '',\n purpose: value.purpose ?? '',\n companyName: value.companyName ?? '',\n addressLine1: value.addressLine1 ?? '',\n addressLine2: value.addressLine2 ?? '',\n buildingNumber: value.buildingNumber ?? '',\n flatNumber: value.flatNumber ?? '',\n city: value.city ?? '',\n region: value.region ?? '',\n postalCode: value.postalCode ?? '',\n country: value.country ?? '',\n latitude: value.latitude != null ? String(value.latitude) : '',\n longitude: value.longitude != null ? String(value.longitude) : '',\n isPrimary: value.isPrimary ?? false,\n })\n setEditingId(value.id)\n setIsFormOpen(true)\n setFieldErrors({})\n setGeneralError(null)\n }, [])\n\n const validate = React.useCallback((): boolean => {\n const errors: Partial<Record<DraftFieldKey, string>> = {}\n if (!draft.addressLine1.trim()) {\n errors.addressLine1 = label('validation.required', '{{field}} is required').replace('{{field}}', line1FieldLabel)\n }\n for (const key of ['latitude', 'longitude'] as const) {\n const result = validateCoordinateInput(key, draft[key])\n if (result.status === 'invalid') {\n errors[key] = label('validation.invalid', 'Invalid value for {{field}}').replace('{{field}}', fieldLabels[key])\n } else if (result.status === 'outOfRange') {\n errors[key] = label('validation.coordinateRange', '{{field}} must be between {{min}} and {{max}}')\n .replace('{{field}}', fieldLabels[key])\n .replace('{{min}}', `${result.min}`)\n .replace('{{max}}', `${result.max}`)\n }\n }\n if (Object.keys(errors).length > 0) {\n setFieldErrors(errors)\n return false\n }\n return true\n }, [draft.addressLine1, draft.latitude, draft.longitude, fieldLabels, label, line1FieldLabel])\n\n const handleSave = React.useCallback(async () => {\n if (!validate()) return\n setSaving(true)\n setGeneralError(null)\n try {\n const payload: AddressInput = {\n name: normalizeOptional(draft.name),\n purpose: normalizeOptional(draft.purpose),\n companyName: normalizeOptional(draft.companyName),\n addressLine1: draft.addressLine1.trim(),\n addressLine2: normalizeOptional(draft.addressLine2),\n buildingNumber: normalizeOptional(draft.buildingNumber),\n flatNumber: normalizeOptional(draft.flatNumber),\n city: normalizeOptional(draft.city),\n region: normalizeOptional(draft.region),\n postalCode: normalizeOptional(draft.postalCode),\n country: normalizeOptional(draft.country)?.toUpperCase(),\n // On edit, an emptied coordinate must be sent as `null` to clear the stored value; omitting\n // it (undefined) makes the partial-update handler keep the old coordinate. On create there is\n // nothing to clear, so leave it undefined (omitted).\n latitude: normalizeCoordinateInput(draft.latitude) ?? (editingId ? null : undefined),\n longitude: normalizeCoordinateInput(draft.longitude) ?? (editingId ? null : undefined),\n isPrimary: draft.isPrimary,\n }\n if (editingId && onUpdate) {\n await onUpdate(editingId, payload)\n } else {\n await onCreate(payload)\n }\n resetForm()\n setIsFormOpen(false)\n } catch (err) {\n const details = extractValidationDetails(err)\n if (details.length) {\n const nextErrors: Partial<Record<DraftFieldKey, string>> = {}\n details.forEach((detail) => {\n const path = Array.isArray(detail.path) ? detail.path : []\n const key = typeof path[0] === 'string' ? path[0] : undefined\n if (!key) return\n const fieldKey = serverFieldMap[key]\n if (!fieldKey) return\n const fieldLabel = fieldKey === 'addressLine1' ? line1FieldLabel : (fieldLabels[fieldKey] ?? key)\n nextErrors[fieldKey] = resolveFieldMessage(detail, fieldLabel, t, labelPrefix)\n })\n setFieldErrors(nextErrors)\n setGeneralError(label('validation.summary', 'Please fix the highlighted fields.'))\n return\n }\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('error', 'Failed to save address')\n setGeneralError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, editingId, fieldLabels, label, labelPrefix, onCreate, onUpdate, resetForm, t, validate])\n\n const handleDelete = React.useCallback(\n async (id: string) => {\n if (!onDelete) return\n setDeletingId(id)\n try {\n await onDelete(id)\n if (editingId === id) {\n resetForm()\n setIsFormOpen(false)\n }\n } catch (err) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : label('error', 'Failed to delete address')\n flash(message, 'error')\n } finally {\n setDeletingId(null)\n }\n },\n [editingId, label, onDelete, resetForm]\n )\n\n const disableActions = saving || isSubmitting || deletingId !== null\n const isEditing = editingId !== null\n const addDisabled = disableActions || isEditing\n const hasAddresses = addresses.length > 0\n const emptyTitle = emptyStateTitle ?? emptyLabel\n const emptyActionLabel = emptyStateActionLabel ?? label('add', 'Add address')\n\n React.useEffect(() => {\n if (!onAddActionChange) return\n onAddActionChange({ openCreateForm, addDisabled })\n }, [onAddActionChange, openCreateForm, addDisabled])\n\n React.useEffect(\n () => () => {\n if (onAddActionChange) onAddActionChange(null)\n },\n [onAddActionChange]\n )\n\n const renderFormTile = React.useCallback(\n (key: string) => (\n <div\n key={key}\n className=\"rounded-lg border-2 border-dashed border-muted-foreground/50 bg-muted/30 p-4 text-sm\"\n onKeyDown={(event) => {\n if (!(event.metaKey || event.ctrlKey)) return\n if (event.key !== 'Enter') return\n event.preventDefault()\n if (disableActions) return\n void handleSave()\n }}\n >\n <div className=\"flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n <span>\n {editingId\n ? label('editTitle', 'Edit address')\n : label('addTitle', 'Add address')}\n </span>\n <Button type=\"button\" variant=\"ghost\" size=\"icon\" onClick={handleCancel} disabled={disableActions}>\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"mt-3 space-y-3\">\n {formatLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {label('formatLoading', 'Loading address preferences\u2026')}\n </p>\n ) : null}\n <AddressEditor\n value={draft}\n onChange={(next) => {\n setDraft({ ...next, latitude: next.latitude ?? '', longitude: next.longitude ?? '' })\n if (Object.keys(fieldErrors).length) {\n const nextErrors = { ...fieldErrors }\n ;(Object.keys(nextErrors) as DraftFieldKey[]).forEach((key) => {\n const candidate = (next as Record<string, unknown>)[key]\n if (candidate !== undefined && candidate !== null && `${candidate}`.length) {\n delete nextErrors[key]\n }\n })\n setFieldErrors(nextErrors)\n }\n }}\n format={format}\n t={t}\n disabled={disableActions}\n errors={fieldErrors}\n showFormatHint={!formatLoading}\n showCoordinateFields={showCoordinateFields}\n labelPrefix={labelPrefix}\n addressTypesAdapter={addressTypesAdapter}\n addressTypesContext={addressTypesContext}\n />\n {generalError ? <p className=\"text-xs text-status-error-text\">{generalError}</p> : null}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={handleCancel} disabled={disableActions}>\n {label('cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" onClick={handleSave} disabled={disableActions}>\n {saving ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {editingId\n ? label('updating', 'Updating\u2026')\n : label('saving', 'Saving\u2026')}\n </>\n ) : editingId ? (\n label('update', 'Update address')\n ) : (\n label('save', 'Save address')\n )}\n </Button>\n </div>\n </div>\n </div>\n ),\n [\n addressTypesAdapter,\n addressTypesContext,\n disableActions,\n draft,\n editingId,\n fieldErrors,\n format,\n formatLoading,\n handleCancel,\n handleSave,\n generalError,\n label,\n labelPrefix,\n saving,\n showCoordinateFields,\n t,\n ]\n )\n\n return (\n <div className=\"space-y-4\">\n {!hideAddButton && hasAddresses ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={openCreateForm}\n disabled={addDisabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {label('add', 'Add address')}\n </Button>\n </div>\n ) : null}\n {hasAddresses ? (\n <div className={gridClassName}>\n {addresses.map((address) => {\n if (isFormOpen && editingId === address.id) {\n return renderFormTile(`form-${address.id}`)\n }\n const isDeleting = deletingId === address.id\n return (\n <div\n key={address.id}\n className=\"group rounded-lg border border-border/70 bg-card p-4 text-sm transition hover:border-border\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-sm font-semibold text-foreground\">\n {address.name ?? label('labelFallback', 'Address')}\n </p>\n {address.isPrimary ? (\n <span className=\"rounded-full border border-border bg-muted px-2 py-0.5 text-overline font-semibold uppercase\">\n {label('primaryBadge', 'Primary')}\n </span>\n ) : null}\n </div>\n {address.purpose ? (\n <p className=\"text-xs text-muted-foreground\">\n {address.purpose}\n </p>\n ) : null}\n <AddressView address={address} format={format} className=\"text-sm text-foreground\" />\n </div>\n <div className=\"flex items-center gap-1 opacity-100 md:opacity-0 transition-opacity md:group-hover:opacity-100 focus-within:opacity-100\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleEdit(address)}\n disabled={disableActions}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleDelete(address.id)}\n disabled={disableActions}\n >\n {isDeleting ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n </div>\n )\n })}\n {isFormOpen && !editingId ? renderFormTile('create') : null}\n </div>\n ) : isFormOpen ? (\n <div className={gridClassName}>\n {renderFormTile('create')}\n </div>\n ) : (\n <TabEmptyState\n title={emptyTitle}\n action={{\n label: emptyActionLabel,\n onClick: openCreateForm,\n disabled: addDisabled,\n }}\n />\n )}\n </div>\n )\n}\n\nexport default AddressTiles\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["key"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
1
|
import {
|
|
3
2
|
Activity,
|
|
4
3
|
AlertCircle,
|
|
@@ -293,30 +292,7 @@ const LUCIDE_ICON_REGISTRY = {
|
|
|
293
292
|
"x": X,
|
|
294
293
|
"x-circle": XCircle
|
|
295
294
|
};
|
|
296
|
-
function normalizeKebabIconName(input) {
|
|
297
|
-
const trimmed = input.trim();
|
|
298
|
-
if (!trimmed) return "";
|
|
299
|
-
const withoutPrefix = trimmed.startsWith("lucide:") ? trimmed.slice("lucide:".length) : trimmed;
|
|
300
|
-
if (!withoutPrefix) return "";
|
|
301
|
-
if (!withoutPrefix.includes("-") && !withoutPrefix.includes("_") && !withoutPrefix.includes(" ") && /[A-Z]/.test(withoutPrefix)) {
|
|
302
|
-
return withoutPrefix.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
303
|
-
}
|
|
304
|
-
return withoutPrefix.replace(/[_\s]+/g, "-").replace(/-+/g, "-").toLowerCase();
|
|
305
|
-
}
|
|
306
|
-
function resolveRegisteredLucideIcon(name) {
|
|
307
|
-
if (!name) return null;
|
|
308
|
-
const normalized = normalizeKebabIconName(name);
|
|
309
|
-
if (!normalized) return null;
|
|
310
|
-
return LUCIDE_ICON_REGISTRY[normalized] ?? null;
|
|
311
|
-
}
|
|
312
|
-
function resolveRegisteredLucideIconNode(name, className) {
|
|
313
|
-
const Icon = resolveRegisteredLucideIcon(name);
|
|
314
|
-
if (!Icon) return null;
|
|
315
|
-
return /* @__PURE__ */ jsx(Icon, { className });
|
|
316
|
-
}
|
|
317
295
|
export {
|
|
318
|
-
LUCIDE_ICON_REGISTRY
|
|
319
|
-
resolveRegisteredLucideIcon,
|
|
320
|
-
resolveRegisteredLucideIconNode
|
|
296
|
+
LUCIDE_ICON_REGISTRY
|
|
321
297
|
};
|
|
322
298
|
//# sourceMappingURL=lucideRegistry.generated.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/icons/lucideRegistry.generated.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n// AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.\n// Generated from discovered icon string usages across the repo.\n\nimport type
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n// AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.\n// Generated from discovered icon string usages across the repo.\n\nimport type { LucideIcon } from 'lucide-react';\nimport {\n Activity,\n AlertCircle,\n AlertOctagon,\n AlertTriangle,\n Archive,\n Award,\n BadgeCheck,\n Ban,\n Banknote,\n BarChart2,\n BarChart3,\n Bell,\n Bolt,\n Book,\n Bookmark,\n Box,\n Boxes,\n Briefcase,\n BriefcaseBusiness,\n Building,\n Building2,\n Calendar,\n CalendarCheck,\n CalendarClock,\n CalendarCog,\n CalendarMinus,\n CalendarOff,\n CalendarX,\n Check,\n CheckCircle,\n CheckCircle2,\n CheckSquare,\n Circle,\n ClipboardCheck,\n ClipboardList,\n Clock,\n Clock3,\n Coins,\n Copy,\n CreditCard,\n Crown,\n Database,\n DollarSign,\n Download,\n ExternalLink,\n Eye,\n FileMinus,\n FilePenLine,\n FileSpreadsheet,\n FileText,\n FilterX,\n Flag,\n Flame,\n FolderTree,\n Gauge,\n GitBranch,\n GitCompareArrows,\n GitPullRequestArrow,\n Globe,\n GraduationCap,\n Hand,\n Handshake,\n Headphones,\n Heart,\n HelpCircle,\n Hourglass,\n Inbox,\n Key,\n KeyRound,\n Layers,\n Lightbulb,\n LineChart,\n Link,\n List,\n Loader,\n Loader2,\n Lock,\n Mail,\n MailOpen,\n MapPin,\n MapPinned,\n MessageCircle,\n MinusCircle,\n Notebook,\n Package,\n PackageCheck,\n PackagePlus,\n PackageSearch,\n PackageX,\n PauseCircle,\n Percent,\n Phone,\n PhoneCall,\n PieChart,\n PlusSquare,\n Receipt,\n ReceiptText,\n RefreshCcw,\n RefreshCw,\n Reply,\n RotateCcw,\n Ruler,\n Send,\n Settings,\n Shapes,\n Share2,\n Shield,\n ShieldAlert,\n ShieldCheck,\n ShoppingBag,\n ShoppingCart,\n Shuffle,\n Sliders,\n Smartphone,\n Snowflake,\n Sparkles,\n Star,\n StickyNote,\n Store,\n Tag,\n Target,\n ThumbsUp,\n Ticket,\n Timer,\n Trash2,\n TrendingUp,\n TriangleAlert,\n Trophy,\n Truck,\n Undo2,\n Unlock,\n User,\n UserCheck,\n UserMinus,\n UserPlus,\n UserRound,\n Users,\n UserX,\n Wallet,\n Warehouse,\n Webhook,\n Workflow,\n Wrench,\n X,\n XCircle,\n} from 'lucide-react';\n\nexport const LUCIDE_ICON_REGISTRY: Record<string, LucideIcon> = {\n 'activity': Activity,\n 'alert-circle': AlertCircle,\n 'alert-octagon': AlertOctagon,\n 'alert-triangle': AlertTriangle,\n 'archive': Archive,\n 'award': Award,\n 'badge-check': BadgeCheck,\n 'ban': Ban,\n 'banknote': Banknote,\n 'bar-chart-2': BarChart2,\n 'bar-chart-3': BarChart3,\n 'bell': Bell,\n 'bolt': Bolt,\n 'book': Book,\n 'bookmark': Bookmark,\n 'box': Box,\n 'boxes': Boxes,\n 'briefcase': Briefcase,\n 'briefcase-business': BriefcaseBusiness,\n 'building': Building,\n 'building2': Building2,\n 'calendar': Calendar,\n 'calendar-check': CalendarCheck,\n 'calendar-clock': CalendarClock,\n 'calendar-cog': CalendarCog,\n 'calendar-minus': CalendarMinus,\n 'calendar-off': CalendarOff,\n 'calendar-x': CalendarX,\n 'check': Check,\n 'check-circle': CheckCircle,\n 'check-circle-2': CheckCircle2,\n 'check-square': CheckSquare,\n 'circle': Circle,\n 'clipboard-check': ClipboardCheck,\n 'clipboard-list': ClipboardList,\n 'clock': Clock,\n 'clock-3': Clock3,\n 'coins': Coins,\n 'copy': Copy,\n 'credit-card': CreditCard,\n 'crown': Crown,\n 'database': Database,\n 'dollar-sign': DollarSign,\n 'download': Download,\n 'external-link': ExternalLink,\n 'eye': Eye,\n 'file-minus': FileMinus,\n 'file-pen-line': FilePenLine,\n 'file-spreadsheet': FileSpreadsheet,\n 'file-text': FileText,\n 'filter-x': FilterX,\n 'flag': Flag,\n 'flame': Flame,\n 'folder-tree': FolderTree,\n 'gauge': Gauge,\n 'git-branch': GitBranch,\n 'git-compare-arrows': GitCompareArrows,\n 'git-pull-request-arrow': GitPullRequestArrow,\n 'globe': Globe,\n 'graduation-cap': GraduationCap,\n 'hand': Hand,\n 'handshake': Handshake,\n 'headphones': Headphones,\n 'heart': Heart,\n 'help-circle': HelpCircle,\n 'hourglass': Hourglass,\n 'inbox': Inbox,\n 'key': Key,\n 'key-round': KeyRound,\n 'layers': Layers,\n 'lightbulb': Lightbulb,\n 'line-chart': LineChart,\n 'link': Link,\n 'list': List,\n 'loader': Loader,\n 'loader-2': Loader2,\n 'lock': Lock,\n 'mail': Mail,\n 'mail-open': MailOpen,\n 'map-pin': MapPin,\n 'map-pinned': MapPinned,\n 'message-circle': MessageCircle,\n 'minus-circle': MinusCircle,\n 'notebook': Notebook,\n 'package': Package,\n 'package-check': PackageCheck,\n 'package-plus': PackagePlus,\n 'package-search': PackageSearch,\n 'package-x': PackageX,\n 'pause-circle': PauseCircle,\n 'percent': Percent,\n 'phone': Phone,\n 'phone-call': PhoneCall,\n 'pie-chart': PieChart,\n 'plus-square': PlusSquare,\n 'receipt': Receipt,\n 'receipt-text': ReceiptText,\n 'refresh-ccw': RefreshCcw,\n 'refresh-cw': RefreshCw,\n 'reply': Reply,\n 'rotate-ccw': RotateCcw,\n 'ruler': Ruler,\n 'send': Send,\n 'settings': Settings,\n 'shapes': Shapes,\n 'share-2': Share2,\n 'shield': Shield,\n 'shield-alert': ShieldAlert,\n 'shield-check': ShieldCheck,\n 'shopping-bag': ShoppingBag,\n 'shopping-cart': ShoppingCart,\n 'shuffle': Shuffle,\n 'sliders': Sliders,\n 'smartphone': Smartphone,\n 'snowflake': Snowflake,\n 'sparkles': Sparkles,\n 'star': Star,\n 'sticky-note': StickyNote,\n 'store': Store,\n 'tag': Tag,\n 'target': Target,\n 'thumbs-up': ThumbsUp,\n 'ticket': Ticket,\n 'timer': Timer,\n 'trash-2': Trash2,\n 'trending-up': TrendingUp,\n 'triangle-alert': TriangleAlert,\n 'trophy': Trophy,\n 'truck': Truck,\n 'undo-2': Undo2,\n 'unlock': Unlock,\n 'user': User,\n 'user-check': UserCheck,\n 'user-minus': UserMinus,\n 'user-plus': UserPlus,\n 'user-round': UserRound,\n 'user-x': UserX,\n 'users': Users,\n 'wallet': Wallet,\n 'warehouse': Warehouse,\n 'webhook': Webhook,\n 'workflow': Workflow,\n 'wrench': Wrench,\n 'x': X,\n 'x-circle': XCircle,\n};\n"],
|
|
5
|
+
"mappings": "AAKA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRegisteredLucideIcon,
|
|
3
|
-
resolveRegisteredLucideIconNode
|
|
4
|
-
|
|
5
|
-
} from "./lucideRegistry.generated.js";
|
|
3
|
+
resolveRegisteredLucideIconNode
|
|
4
|
+
} from "./lucideRegistryRuntime.js";
|
|
5
|
+
import { LUCIDE_ICON_REGISTRY } from "./lucideRegistry.generated.js";
|
|
6
6
|
import { LUCIDE_ICON_REGISTRY as LUCIDE_ICON_REGISTRY2 } from "./lucideRegistry.generated.js";
|
|
7
7
|
function registerAdditionalIcons(icons) {
|
|
8
8
|
for (const [name, component] of Object.entries(icons)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/icons/lucideRegistry.ts"],
|
|
4
|
-
"sourcesContent": ["export {\n resolveRegisteredLucideIcon,\n resolveRegisteredLucideIconNode,\n
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["export {\n resolveRegisteredLucideIcon,\n resolveRegisteredLucideIconNode,\n} from './lucideRegistryRuntime'\nexport { LUCIDE_ICON_REGISTRY } from './lucideRegistry.generated'\n\nimport type { LucideIcon } from 'lucide-react'\nimport { LUCIDE_ICON_REGISTRY } from './lucideRegistry.generated'\n\nexport function registerAdditionalIcons(icons: Record<string, LucideIcon>): void {\n for (const [name, component] of Object.entries(icons)) {\n LUCIDE_ICON_REGISTRY[name] = component\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,4BAA4B;AAGrC,SAAS,wBAAAA,6BAA4B;AAE9B,SAAS,wBAAwB,OAAyC;AAC/E,aAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,KAAK,GAAG;AACrD,IAAAA,sBAAqB,IAAI,IAAI;AAAA,EAC/B;AACF;",
|
|
6
6
|
"names": ["LUCIDE_ICON_REGISTRY"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { LUCIDE_ICON_REGISTRY } from "./lucideRegistry.generated.js";
|
|
3
|
+
function normalizeKebabIconName(input) {
|
|
4
|
+
const trimmed = input.trim();
|
|
5
|
+
if (!trimmed) return "";
|
|
6
|
+
const withoutPrefix = trimmed.startsWith("lucide:") ? trimmed.slice("lucide:".length) : trimmed;
|
|
7
|
+
if (!withoutPrefix) return "";
|
|
8
|
+
if (!withoutPrefix.includes("-") && !withoutPrefix.includes("_") && !withoutPrefix.includes(" ") && /[A-Z]/.test(withoutPrefix)) {
|
|
9
|
+
return withoutPrefix.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
return withoutPrefix.replace(/[_\s]+/g, "-").replace(/-+/g, "-").toLowerCase();
|
|
12
|
+
}
|
|
13
|
+
function resolveRegisteredLucideIcon(name) {
|
|
14
|
+
if (!name) return null;
|
|
15
|
+
const normalized = normalizeKebabIconName(name);
|
|
16
|
+
if (!normalized) return null;
|
|
17
|
+
return LUCIDE_ICON_REGISTRY[normalized] ?? null;
|
|
18
|
+
}
|
|
19
|
+
function resolveRegisteredLucideIconNode(name, className) {
|
|
20
|
+
const Icon = resolveRegisteredLucideIcon(name);
|
|
21
|
+
if (!Icon) return null;
|
|
22
|
+
return /* @__PURE__ */ jsx(Icon, { className });
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
resolveRegisteredLucideIcon,
|
|
26
|
+
resolveRegisteredLucideIconNode
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=lucideRegistryRuntime.js.map
|