@open-mercato/ui 0.6.7-develop.6860.1.f796b22e80 → 0.6.7
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/AGENTS.md +2 -4
- package/agentic/standalone-guide.md +1 -1
- package/build.mjs +54 -2
- package/dist/ai/AiChat.js +2 -21
- package/dist/ai/AiChat.js.map +2 -2
- package/dist/backend/AppShell.js +4 -43
- package/dist/backend/AppShell.js.map +2 -2
- package/dist/backend/AuthSessionGuard.js +0 -14
- package/dist/backend/AuthSessionGuard.js.map +2 -2
- package/dist/backend/BackendChromeProvider.js +1 -6
- package/dist/backend/BackendChromeProvider.js.map +2 -2
- package/dist/backend/CrudForm.js +4 -6
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +18 -20
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/JsonBuilder.js +3 -3
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/NextStepCallout.js +4 -4
- package/dist/backend/NextStepCallout.js.map +1 -1
- package/dist/backend/ProfileDropdown.js +1 -2
- package/dist/backend/ProfileDropdown.js.map +2 -2
- package/dist/backend/RowActions.js +2 -2
- package/dist/backend/RowActions.js.map +2 -2
- package/dist/backend/confirm-dialog/ConfirmDialog.js +1 -13
- package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
- package/dist/backend/crud/useGroupOrder.js +21 -14
- package/dist/backend/crud/useGroupOrder.js.map +2 -2
- package/dist/backend/detail/AddressTiles.js +5 -4
- package/dist/backend/detail/AddressTiles.js.map +2 -2
- package/dist/backend/detail/AttachmentDeleteDialog.js +1 -1
- package/dist/backend/detail/AttachmentDeleteDialog.js.map +2 -2
- package/dist/backend/detail/AttachmentMetadataDialog.js.map +1 -1
- package/dist/backend/detail/AttachmentsSection.js +1 -1
- package/dist/backend/detail/AttachmentsSection.js.map +2 -2
- package/dist/backend/detail/NotesSection.js +1 -1
- package/dist/backend/detail/NotesSection.js.map +2 -2
- package/dist/backend/detail/TagsSection.js +1 -1
- package/dist/backend/detail/TagsSection.js.map +2 -2
- package/dist/backend/forms/FormHeader.js +2 -1
- package/dist/backend/forms/FormHeader.js.map +2 -2
- package/dist/backend/icons/lucideRegistry.generated.js +25 -1
- 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/injection/spotIds.js +18 -23
- package/dist/backend/injection/spotIds.js.map +2 -2
- package/dist/backend/schedule/ScheduleAgenda.js +3 -3
- package/dist/backend/schedule/ScheduleAgenda.js.map +1 -1
- package/dist/backend/schedule/ScheduleGrid.js +3 -3
- package/dist/backend/schedule/ScheduleGrid.js.map +1 -1
- package/dist/backend/schedule/ScheduleToolbar.js +70 -87
- package/dist/backend/schedule/ScheduleToolbar.js.map +2 -2
- package/dist/backend/sidebar/SidebarCustomizationEditor.js +2 -30
- package/dist/backend/sidebar/SidebarCustomizationEditor.js.map +2 -2
- package/dist/backend/sidebar/customization-helpers.js +0 -30
- package/dist/backend/sidebar/customization-helpers.js.map +2 -2
- package/dist/backend/utils/api.js +13 -3
- package/dist/backend/utils/api.js.map +2 -2
- package/dist/backend/utils/apiCall.js +1 -21
- package/dist/backend/utils/apiCall.js.map +2 -2
- package/dist/backend/utils/customFieldDefs.js.map +2 -2
- package/dist/backend/utils/customFieldForms.js +9 -10
- package/dist/backend/utils/customFieldForms.js.map +2 -2
- package/dist/backend/utils/nav.js +2 -5
- package/dist/backend/utils/nav.js.map +2 -2
- package/dist/frontend/LanguageSwitcher.js +1 -2
- package/dist/frontend/LanguageSwitcher.js.map +2 -2
- package/dist/portal/PortalContext.js +1 -1
- package/dist/portal/PortalContext.js.map +2 -2
- package/dist/portal/hooks/usePortalEventBridge.js +0 -6
- package/dist/portal/hooks/usePortalEventBridge.js.map +2 -2
- package/dist/portal/hooks/usePortalNotifications.js +4 -42
- package/dist/portal/hooks/usePortalNotifications.js.map +2 -2
- package/dist/portal/utils/nav.js +3 -2
- package/dist/portal/utils/nav.js.map +2 -2
- package/dist/primitives/button.js +4 -9
- package/dist/primitives/button.js.map +2 -2
- package/jest.config.cjs +1 -2
- package/package.json +18 -21
- package/src/ai/AiChat.tsx +1 -30
- package/src/ai/__tests__/AiChat.test.tsx +0 -31
- package/src/backend/AppShell.tsx +4 -55
- package/src/backend/AuthSessionGuard.tsx +0 -29
- package/src/backend/BackendChromeProvider.tsx +1 -19
- package/src/backend/CrudForm.tsx +4 -18
- package/src/backend/DataTable.tsx +19 -36
- package/src/backend/JsonBuilder.tsx +3 -3
- package/src/backend/NextStepCallout.tsx +4 -4
- package/src/backend/ProfileDropdown.tsx +0 -1
- package/src/backend/RowActions.tsx +2 -2
- package/src/backend/__tests__/AppShell.test.tsx +7 -65
- package/src/backend/__tests__/AuthSessionGuard.test.tsx +0 -52
- package/src/backend/__tests__/BackendChromeProvider.test.tsx +2 -98
- package/src/backend/__tests__/DataTable.perspectiveStorage.test.ts +1 -62
- package/src/backend/__tests__/nav-utils.test.ts +0 -139
- package/src/backend/confirm-dialog/ConfirmDialog.tsx +1 -16
- package/src/backend/confirm-dialog/__tests__/ConfirmDialog.test.tsx +1 -68
- package/src/backend/crud/__tests__/useGroupOrder.test.ts +1 -39
- package/src/backend/crud/useGroupOrder.ts +25 -30
- package/src/backend/detail/AddressTiles.tsx +6 -3
- package/src/backend/detail/AttachmentDeleteDialog.tsx +1 -1
- package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
- package/src/backend/detail/AttachmentsSection.tsx +1 -1
- package/src/backend/detail/NotesSection.tsx +1 -1
- package/src/backend/detail/TagsSection.tsx +1 -1
- package/src/backend/detail/__tests__/AttachmentAssignmentsEditor.test.tsx +0 -21
- package/src/backend/forms/FormHeader.tsx +2 -1
- package/src/backend/icons/lucideRegistry.generated.tsx +37 -3
- package/src/backend/icons/lucideRegistry.ts +2 -2
- package/src/backend/injection/spotIds.ts +18 -23
- package/src/backend/schedule/ScheduleAgenda.tsx +3 -3
- package/src/backend/schedule/ScheduleGrid.tsx +3 -3
- package/src/backend/schedule/ScheduleToolbar.tsx +68 -89
- package/src/backend/sidebar/SidebarCustomizationEditor.tsx +3 -42
- package/src/backend/sidebar/customization-helpers.ts +0 -47
- package/src/backend/utils/__tests__/api.test.ts +27 -0
- package/src/backend/utils/__tests__/apiCall.test.ts +0 -61
- package/src/backend/utils/api.ts +20 -3
- package/src/backend/utils/apiCall.ts +1 -29
- package/src/backend/utils/customFieldDefs.ts +0 -1
- package/src/backend/utils/customFieldForms.ts +11 -15
- package/src/backend/utils/nav.ts +2 -22
- package/src/frontend/LanguageSwitcher.tsx +0 -1
- package/src/portal/PortalContext.tsx +1 -1
- package/src/portal/hooks/usePortalEventBridge.ts +0 -6
- package/src/portal/hooks/usePortalNotifications.ts +12 -55
- package/src/portal/utils/__tests__/nav.test.ts +2 -2
- package/src/portal/utils/nav.ts +4 -3
- package/src/primitives/button.tsx +4 -10
- package/dist/backend/icons/lucideRegistryRuntime.js +0 -28
- package/dist/backend/icons/lucideRegistryRuntime.js.map +0 -7
- package/dist/backend/perspectiveState.js +0 -34
- package/dist/backend/perspectiveState.js.map +0 -7
- package/dist/backend/utils/fetchAllPages.js +0 -57
- package/dist/backend/utils/fetchAllPages.js.map +0 -7
- package/dist/portal/hooks/portalBridgeStatus.js +0 -25
- package/dist/portal/hooks/portalBridgeStatus.js.map +0 -7
- package/figma/alert.figma.tsx +0 -35
- package/figma/badge.figma.tsx +0 -33
- package/figma/button.figma.tsx +0 -33
- package/figma/checkbox.figma.tsx +0 -28
- package/figma/drawer.figma.tsx +0 -40
- package/figma/input-variants.figma.tsx +0 -58
- package/figma/radio.figma.tsx +0 -16
- package/figma/select.figma.tsx +0 -24
- package/figma/status-badge.figma.tsx +0 -24
- package/figma/switch.figma.tsx +0 -28
- package/figma/tabs.figma.tsx +0 -22
- package/figma/tag.figma.tsx +0 -27
- package/figma.config.json +0 -6
- package/scripts/lucideRegistrySource.cjs +0 -133
- package/src/backend/__tests__/CrudForm.fieldsetBinding.test.tsx +0 -158
- package/src/backend/__tests__/CrudForm.groupInjectionColumn.test.tsx +0 -98
- package/src/backend/__tests__/DataTable.metaHiddenLateColumns.test.tsx +0 -105
- package/src/backend/icons/__tests__/lucideRegistryGenerator.test.ts +0 -177
- package/src/backend/icons/lucideRegistryRuntime.tsx +0 -36
- package/src/backend/injection/__tests__/spotIds.extension-points.test.ts +0 -38
- package/src/backend/perspectiveState.ts +0 -44
- package/src/backend/sidebar/__tests__/group-visibility.test.ts +0 -131
- package/src/backend/utils/__tests__/customFieldForms.optionsPaging.test.ts +0 -95
- package/src/backend/utils/__tests__/fetchAllPages.test.ts +0 -103
- package/src/backend/utils/fetchAllPages.ts +0 -93
- package/src/portal/hooks/__tests__/usePortalEventBridge.test.tsx +0 -66
- package/src/portal/hooks/__tests__/usePortalNotifications.test.tsx +0 -155
- package/src/portal/hooks/portalBridgeStatus.ts +0 -29
- package/src/primitives/__tests__/button.test.tsx +0 -70
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/forms/FormHeader.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useSearchParams } from 'next/navigation'\nimport { Trash2, Loader2 } from 'lucide-react'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { FormActionButtons, type FormActionButtonsProps } from './FormActionButtons'\nimport { ActionsDropdown, type ActionItem } from './ActionsDropdown'\nimport { InjectionSpot } from '../injection/InjectionSpot'\n\n/** Base props shared by both modes */\ntype FormHeaderBaseProps = {\n /** Back link URL */\n backHref?: string\n /** Back link label */\n backLabel?: string\n}\n\n/** Edit mode: compact header for CrudForm pages */\nexport type FormHeaderEditProps = FormHeaderBaseProps & {\n mode?: 'edit'\n /** Small title next to the back link */\n title?: string\n /** Structured action buttons (Delete/Cancel/Save) */\n actions?: FormActionButtonsProps\n /** Custom right-side content (overrides `actions`) */\n actionsContent?: React.ReactNode\n}\n\n/** Detail mode: large header for view/detail pages */\nexport type FormHeaderDetailProps = FormHeaderBaseProps & {\n mode: 'detail'\n /** Large title -- string renders as h1; ReactNode for InlineTextEditor */\n title?: React.ReactNode\n /** Small uppercase entity type label above the title */\n entityTypeLabel?: string\n /** Subtitle text below the title */\n subtitle?: string\n /** Status badge or similar element below the title */\n statusBadge?: React.ReactNode\n /** Context actions grouped into an \"Actions\" dropdown (preferred) */\n menuActions?: ActionItem[]\n /** Optional label for actions dropdown trigger */\n menuLabel?: string\n /** Trigger style for actions dropdown */\n menuTriggerMode?: 'label' | 'icon'\n /** Accessible label used when trigger is icon-only */\n menuAriaLabel?: string\n /** Optional utility actions (icon-only) displayed before menu actions */\n utilityActions?: React.ReactNode\n /** Delete action -- rendered as a standalone destructive button next to the dropdown */\n onDelete?: () => void\n /** Delete button label */\n deleteLabel?: string\n /** Whether delete is in progress */\n isDeleting?: boolean\n /** Fallback: fully custom right-side content (overrides menuActions + onDelete) */\n actionsContent?: React.ReactNode\n}\n\nexport type FormHeaderProps = FormHeaderEditProps | FormHeaderDetailProps\n\nexport function FormHeader(props: FormHeaderProps) {\n const t = useT()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const resolvedBackLabel = props.backLabel ?? t('ui.navigation.back')\n const injectionContext = React.useMemo(\n () => ({\n path: pathname ?? '',\n query: searchParams?.toString() ?? '',\n }),\n [pathname, searchParams],\n )\n\n if (props.mode === 'detail') {\n return (\n <>\n <DetailHeader {...props} resolvedBackLabel={resolvedBackLabel} />\n <InjectionSpot spotId=\"form-header:detail\" context={injectionContext} />\n </>\n )\n }\n\n return (\n <>\n <EditHeader {...props} resolvedBackLabel={resolvedBackLabel} />\n <InjectionSpot spotId=\"form-header:edit\" context={injectionContext} />\n </>\n )\n}\n\nfunction EditHeader({\n backHref,\n resolvedBackLabel,\n title,\n actions,\n actionsContent,\n}: FormHeaderEditProps & { resolvedBackLabel: string }) {\n return (\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3\">\n <div className=\"flex items-center gap-3\">\n {backHref ? (\n <Link href={backHref} className=\"text-sm text-muted-foreground hover:text-foreground\">\n ← {resolvedBackLabel}\n </Link>\n ) : null}\n {title ? <div className=\"text-base font-medium\">{title}</div> : null}\n </div>\n {actionsContent ?? (actions ? <FormActionButtons {...actions} /> : null)}\n </div>\n )\n}\n\nfunction DetailHeader({\n backHref,\n resolvedBackLabel,\n title,\n entityTypeLabel,\n subtitle,\n statusBadge,\n menuActions,\n menuLabel,\n menuTriggerMode,\n menuAriaLabel,\n utilityActions,\n onDelete,\n deleteLabel,\n isDeleting,\n actionsContent,\n}: FormHeaderDetailProps & { resolvedBackLabel: string }) {\n const t = useT()\n const resolvedDeleteLabel = deleteLabel ?? t('ui.forms.actions.delete')\n\n const hasActions = actionsContent || utilityActions || menuActions?.length || onDelete\n\n return (\n <div className=\"flex flex-col gap-2 md:gap-3 md:flex-row md:items-center md:justify-between\">\n <div className=\"flex flex-wrap items-center gap-2 md:gap-3 min-w-0\">\n {backHref ? (\n <Link\n href={backHref}\n className=\"inline-flex items-center text-sm text-muted-foreground hover:text-foreground shrink-0\"\n >\n <span aria-hidden className=\"mr-1 text-base\">←</span>\n <span className=\"sr-only\">{resolvedBackLabel}</span>\n </Link>\n ) : null}\n <div className=\"space-y-0.5 md:space-y-1 min-w-0\">\n {entityTypeLabel ? (\n <p className=\"text-xs uppercase text-muted-foreground\">{entityTypeLabel}</p>\n ) : null}\n {title ? (\n typeof title === 'string' ? (\n <h1 className=\"text-lg md:text-2xl font-semibold leading-tight truncate\">{title}</h1>\n ) : (\n <div className=\"text-lg md:text-2xl font-semibold leading-tight\">{title}</div>\n )\n ) : null}\n {statusBadge}\n {subtitle ? (\n <p className=\"text-xs md:text-sm text-muted-foreground\">{subtitle}</p>\n ) : null}\n </div>\n </div>\n {hasActions ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n {actionsContent ? actionsContent : (\n <>\n {utilityActions}\n {menuActions?.length ? (\n <ActionsDropdown\n items={menuActions}\n label={menuLabel}\n triggerMode={menuTriggerMode}\n ariaLabel={menuAriaLabel}\n />\n ) : null}\n {onDelete ? (\n <Button\n type=\"button\"\n variant=\"
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useSearchParams } from 'next/navigation'\nimport { Trash2, Loader2 } from 'lucide-react'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { FormActionButtons, type FormActionButtonsProps } from './FormActionButtons'\nimport { ActionsDropdown, type ActionItem } from './ActionsDropdown'\nimport { InjectionSpot } from '../injection/InjectionSpot'\n\n/** Base props shared by both modes */\ntype FormHeaderBaseProps = {\n /** Back link URL */\n backHref?: string\n /** Back link label */\n backLabel?: string\n}\n\n/** Edit mode: compact header for CrudForm pages */\nexport type FormHeaderEditProps = FormHeaderBaseProps & {\n mode?: 'edit'\n /** Small title next to the back link */\n title?: string\n /** Structured action buttons (Delete/Cancel/Save) */\n actions?: FormActionButtonsProps\n /** Custom right-side content (overrides `actions`) */\n actionsContent?: React.ReactNode\n}\n\n/** Detail mode: large header for view/detail pages */\nexport type FormHeaderDetailProps = FormHeaderBaseProps & {\n mode: 'detail'\n /** Large title -- string renders as h1; ReactNode for InlineTextEditor */\n title?: React.ReactNode\n /** Small uppercase entity type label above the title */\n entityTypeLabel?: string\n /** Subtitle text below the title */\n subtitle?: string\n /** Status badge or similar element below the title */\n statusBadge?: React.ReactNode\n /** Context actions grouped into an \"Actions\" dropdown (preferred) */\n menuActions?: ActionItem[]\n /** Optional label for actions dropdown trigger */\n menuLabel?: string\n /** Trigger style for actions dropdown */\n menuTriggerMode?: 'label' | 'icon'\n /** Accessible label used when trigger is icon-only */\n menuAriaLabel?: string\n /** Optional utility actions (icon-only) displayed before menu actions */\n utilityActions?: React.ReactNode\n /** Delete action -- rendered as a standalone destructive button next to the dropdown */\n onDelete?: () => void\n /** Delete button label */\n deleteLabel?: string\n /** Whether delete is in progress */\n isDeleting?: boolean\n /** Fallback: fully custom right-side content (overrides menuActions + onDelete) */\n actionsContent?: React.ReactNode\n}\n\nexport type FormHeaderProps = FormHeaderEditProps | FormHeaderDetailProps\n\nexport function FormHeader(props: FormHeaderProps) {\n const t = useT()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const resolvedBackLabel = props.backLabel ?? t('ui.navigation.back')\n const injectionContext = React.useMemo(\n () => ({\n path: pathname ?? '',\n query: searchParams?.toString() ?? '',\n }),\n [pathname, searchParams],\n )\n\n if (props.mode === 'detail') {\n return (\n <>\n <DetailHeader {...props} resolvedBackLabel={resolvedBackLabel} />\n <InjectionSpot spotId=\"form-header:detail\" context={injectionContext} />\n </>\n )\n }\n\n return (\n <>\n <EditHeader {...props} resolvedBackLabel={resolvedBackLabel} />\n <InjectionSpot spotId=\"form-header:edit\" context={injectionContext} />\n </>\n )\n}\n\nfunction EditHeader({\n backHref,\n resolvedBackLabel,\n title,\n actions,\n actionsContent,\n}: FormHeaderEditProps & { resolvedBackLabel: string }) {\n return (\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3\">\n <div className=\"flex items-center gap-3\">\n {backHref ? (\n <Link href={backHref} className=\"text-sm text-muted-foreground hover:text-foreground\">\n ← {resolvedBackLabel}\n </Link>\n ) : null}\n {title ? <div className=\"text-base font-medium\">{title}</div> : null}\n </div>\n {actionsContent ?? (actions ? <FormActionButtons {...actions} /> : null)}\n </div>\n )\n}\n\nfunction DetailHeader({\n backHref,\n resolvedBackLabel,\n title,\n entityTypeLabel,\n subtitle,\n statusBadge,\n menuActions,\n menuLabel,\n menuTriggerMode,\n menuAriaLabel,\n utilityActions,\n onDelete,\n deleteLabel,\n isDeleting,\n actionsContent,\n}: FormHeaderDetailProps & { resolvedBackLabel: string }) {\n const t = useT()\n const resolvedDeleteLabel = deleteLabel ?? t('ui.forms.actions.delete')\n\n const hasActions = actionsContent || utilityActions || menuActions?.length || onDelete\n\n return (\n <div className=\"flex flex-col gap-2 md:gap-3 md:flex-row md:items-center md:justify-between\">\n <div className=\"flex flex-wrap items-center gap-2 md:gap-3 min-w-0\">\n {backHref ? (\n <Link\n href={backHref}\n className=\"inline-flex items-center text-sm text-muted-foreground hover:text-foreground shrink-0\"\n >\n <span aria-hidden className=\"mr-1 text-base\">←</span>\n <span className=\"sr-only\">{resolvedBackLabel}</span>\n </Link>\n ) : null}\n <div className=\"space-y-0.5 md:space-y-1 min-w-0\">\n {entityTypeLabel ? (\n <p className=\"text-xs uppercase text-muted-foreground\">{entityTypeLabel}</p>\n ) : null}\n {title ? (\n typeof title === 'string' ? (\n <h1 className=\"text-lg md:text-2xl font-semibold leading-tight truncate\">{title}</h1>\n ) : (\n <div className=\"text-lg md:text-2xl font-semibold leading-tight\">{title}</div>\n )\n ) : null}\n {statusBadge}\n {subtitle ? (\n <p className=\"text-xs md:text-sm text-muted-foreground\">{subtitle}</p>\n ) : null}\n </div>\n </div>\n {hasActions ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n {actionsContent ? actionsContent : (\n <>\n {utilityActions}\n {menuActions?.length ? (\n <ActionsDropdown\n items={menuActions}\n label={menuLabel}\n triggerMode={menuTriggerMode}\n ariaLabel={menuAriaLabel}\n />\n ) : null}\n {onDelete ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onDelete}\n disabled={isDeleting}\n className=\"text-red-600 border-red-200 hover:bg-red-50 rounded\"\n >\n {isDeleting ? (\n <Loader2 className=\"size-4 mr-2 animate-spin\" />\n ) : (\n <Trash2 className=\"size-4 mr-2\" />\n )}\n {resolvedDeleteLabel}\n </Button>\n ) : null}\n </>\n )}\n </div>\n ) : null}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
1
2
|
import {
|
|
2
3
|
Activity,
|
|
3
4
|
AlertCircle,
|
|
@@ -292,7 +293,30 @@ const LUCIDE_ICON_REGISTRY = {
|
|
|
292
293
|
"x": X,
|
|
293
294
|
"x-circle": XCircle
|
|
294
295
|
};
|
|
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
|
+
}
|
|
295
317
|
export {
|
|
296
|
-
LUCIDE_ICON_REGISTRY
|
|
318
|
+
LUCIDE_ICON_REGISTRY,
|
|
319
|
+
resolveRegisteredLucideIcon,
|
|
320
|
+
resolveRegisteredLucideIconNode
|
|
297
321
|
};
|
|
298
322
|
//# 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 { LucideIcon } from 'lucide-react'
|
|
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 * as React from 'react'\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\nfunction normalizeKebabIconName(input: string): string {\n const trimmed = input.trim()\n if (!trimmed) return ''\n const withoutPrefix = trimmed.startsWith('lucide:') ? trimmed.slice('lucide:'.length) : trimmed\n if (!withoutPrefix) return ''\n if (!withoutPrefix.includes('-') && !withoutPrefix.includes('_') && !withoutPrefix.includes(' ') && /[A-Z]/.test(withoutPrefix)) {\n return withoutPrefix\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')\n .toLowerCase()\n }\n return withoutPrefix\n .replace(/[_\\s]+/g, '-')\n .replace(/-+/g, '-')\n .toLowerCase()\n}\n\nexport function resolveRegisteredLucideIcon(name: string | undefined): LucideIcon | null {\n if (!name) return null\n const normalized = normalizeKebabIconName(name)\n if (!normalized) return null\n return (LUCIDE_ICON_REGISTRY as Record<string, LucideIcon | undefined>)[normalized] ?? null\n}\n\nexport function resolveRegisteredLucideIconNode(\n name: string | undefined,\n className: string\n): React.ReactNode | null {\n const Icon = resolveRegisteredLucideIcon(name)\n if (!Icon) return null\n return <Icon className={className} />\n}\n"],
|
|
5
|
+
"mappings": "AA4US;AAtUT;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,EAC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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRegisteredLucideIcon,
|
|
3
|
-
resolveRegisteredLucideIconNode
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
resolveRegisteredLucideIconNode,
|
|
4
|
+
LUCIDE_ICON_REGISTRY
|
|
5
|
+
} 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 LUCIDE_ICON_REGISTRY,\n} 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,EACA;AAAA,OACK;AAGP,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
|
}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
crudFormExtensionSpotId,
|
|
3
|
-
dataTableExtensionSpotId
|
|
4
|
-
} from "@open-mercato/shared/modules/widgets/extension-points";
|
|
5
1
|
const BACKEND_RECORD_CURRENT_INJECTION_SPOT_ID = "backend:record:current";
|
|
6
2
|
const BACKEND_LAYOUT_TOP_INJECTION_SPOT_ID = "backend:layout:top";
|
|
7
3
|
const BACKEND_LAYOUT_FOOTER_INJECTION_SPOT_ID = "backend:layout:footer";
|
|
@@ -14,32 +10,31 @@ const BACKEND_SIDEBAR_NAV_FOOTER_INJECTION_SPOT_ID = "backend:sidebar:nav:footer
|
|
|
14
10
|
const GLOBAL_SIDEBAR_STATUS_BADGES_INJECTION_SPOT_ID = "global:sidebar:status-badges";
|
|
15
11
|
const GLOBAL_HEADER_STATUS_INDICATORS_INJECTION_SPOT_ID = "global:header:status-indicators";
|
|
16
12
|
const CrudFormInjectionSpots = {
|
|
17
|
-
base: (entityId) =>
|
|
18
|
-
beforeFields: (entityId) =>
|
|
19
|
-
afterFields: (entityId) =>
|
|
20
|
-
header: (entityId) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
fieldAfter: (entityId, fieldId) => crudFormExtensionSpotId(entityId, `field:${fieldId}:after`)
|
|
13
|
+
base: (entityId) => `crud-form:${entityId}`,
|
|
14
|
+
beforeFields: (entityId) => `crud-form:${entityId}:before-fields`,
|
|
15
|
+
afterFields: (entityId) => `crud-form:${entityId}:after-fields`,
|
|
16
|
+
header: (entityId) => `crud-form:${entityId}:header`,
|
|
17
|
+
footer: (entityId) => `crud-form:${entityId}:footer`,
|
|
18
|
+
sidebar: (entityId) => `crud-form:${entityId}:sidebar`,
|
|
19
|
+
group: (entityId, groupId) => `crud-form:${entityId}:group:${groupId}`,
|
|
20
|
+
fieldBefore: (entityId, fieldId) => `crud-form:${entityId}:field:${fieldId}:before`,
|
|
21
|
+
fieldAfter: (entityId, fieldId) => `crud-form:${entityId}:field:${fieldId}:after`
|
|
27
22
|
};
|
|
28
23
|
const DataTableInjectionSpots = {
|
|
29
|
-
header: (tableId) =>
|
|
30
|
-
footer: (tableId) =>
|
|
31
|
-
toolbar: (tableId) =>
|
|
24
|
+
header: (tableId) => `data-table:${tableId}:header`,
|
|
25
|
+
footer: (tableId) => `data-table:${tableId}:footer`,
|
|
26
|
+
toolbar: (tableId) => `data-table:${tableId}:toolbar`,
|
|
32
27
|
// Slot rendered immediately after the search input on the same row as the
|
|
33
28
|
// FilterBar — intended for compact, icon-sized triggers (AI assistants,
|
|
34
29
|
// saved view shortcuts, etc.). Hosts pass the resolved spot ID through to
|
|
35
30
|
// FilterBar's `searchTrailing` prop. Stays empty when the table has no
|
|
36
31
|
// search input.
|
|
37
|
-
searchTrailing: (tableId) =>
|
|
38
|
-
emptyState: (tableId) =>
|
|
39
|
-
columns: (tableId) =>
|
|
40
|
-
rowActions: (tableId) =>
|
|
41
|
-
bulkActions: (tableId) =>
|
|
42
|
-
filters: (tableId) =>
|
|
32
|
+
searchTrailing: (tableId) => `data-table:${tableId}:search-trailing`,
|
|
33
|
+
emptyState: (tableId) => `data-table:${tableId}:empty-state`,
|
|
34
|
+
columns: (tableId) => `data-table:${tableId}:columns`,
|
|
35
|
+
rowActions: (tableId) => `data-table:${tableId}:row-actions`,
|
|
36
|
+
bulkActions: (tableId) => `data-table:${tableId}:bulk-actions`,
|
|
37
|
+
filters: (tableId) => `data-table:${tableId}:filters`
|
|
43
38
|
};
|
|
44
39
|
const PORTAL_SIDEBAR_MAIN_INJECTION_SPOT_ID = "menu:portal:sidebar:main";
|
|
45
40
|
const PORTAL_SIDEBAR_ACCOUNT_INJECTION_SPOT_ID = "menu:portal:sidebar:account";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/injection/spotIds.ts"],
|
|
4
|
-
"sourcesContent": ["import type { InjectionSpotId } from '@open-mercato/shared/modules/widgets/injection'\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { InjectionSpotId } from '@open-mercato/shared/modules/widgets/injection'\n\nexport const BACKEND_RECORD_CURRENT_INJECTION_SPOT_ID: InjectionSpotId = 'backend:record:current'\nexport const BACKEND_LAYOUT_TOP_INJECTION_SPOT_ID: InjectionSpotId = 'backend:layout:top'\nexport const BACKEND_LAYOUT_FOOTER_INJECTION_SPOT_ID: InjectionSpotId = 'backend:layout:footer'\nexport const BACKEND_SIDEBAR_TOP_INJECTION_SPOT_ID: InjectionSpotId = 'backend:sidebar:top'\nexport const BACKEND_SIDEBAR_FOOTER_INJECTION_SPOT_ID: InjectionSpotId = 'backend:sidebar:footer'\n\n// Standardized backend chrome spot ids\nexport const BACKEND_TOPBAR_PROFILE_MENU_INJECTION_SPOT_ID: InjectionSpotId = 'backend:topbar:profile-menu'\nexport const BACKEND_TOPBAR_ACTIONS_INJECTION_SPOT_ID: InjectionSpotId = 'backend:topbar:actions'\nexport const BACKEND_SIDEBAR_NAV_INJECTION_SPOT_ID: InjectionSpotId = 'backend:sidebar:nav'\nexport const BACKEND_SIDEBAR_NAV_FOOTER_INJECTION_SPOT_ID: InjectionSpotId = 'backend:sidebar:nav:footer'\n\n// Standardized global status spot ids\nexport const GLOBAL_SIDEBAR_STATUS_BADGES_INJECTION_SPOT_ID: InjectionSpotId = 'global:sidebar:status-badges'\nexport const GLOBAL_HEADER_STATUS_INDICATORS_INJECTION_SPOT_ID: InjectionSpotId = 'global:header:status-indicators'\n\n// Standardized pattern helpers\nexport const CrudFormInjectionSpots = {\n base: (entityId: string): InjectionSpotId => `crud-form:${entityId}`,\n beforeFields: (entityId: string): InjectionSpotId => `crud-form:${entityId}:before-fields`,\n afterFields: (entityId: string): InjectionSpotId => `crud-form:${entityId}:after-fields`,\n header: (entityId: string): InjectionSpotId => `crud-form:${entityId}:header`,\n footer: (entityId: string): InjectionSpotId => `crud-form:${entityId}:footer`,\n sidebar: (entityId: string): InjectionSpotId => `crud-form:${entityId}:sidebar`,\n group: (entityId: string, groupId: string): InjectionSpotId => `crud-form:${entityId}:group:${groupId}`,\n fieldBefore: (entityId: string, fieldId: string): InjectionSpotId => `crud-form:${entityId}:field:${fieldId}:before`,\n fieldAfter: (entityId: string, fieldId: string): InjectionSpotId => `crud-form:${entityId}:field:${fieldId}:after`,\n} as const\n\nexport const DataTableInjectionSpots = {\n header: (tableId: string): InjectionSpotId => `data-table:${tableId}:header`,\n footer: (tableId: string): InjectionSpotId => `data-table:${tableId}:footer`,\n toolbar: (tableId: string): InjectionSpotId => `data-table:${tableId}:toolbar`,\n // Slot rendered immediately after the search input on the same row as the\n // FilterBar \u2014 intended for compact, icon-sized triggers (AI assistants,\n // saved view shortcuts, etc.). Hosts pass the resolved spot ID through to\n // FilterBar's `searchTrailing` prop. Stays empty when the table has no\n // search input.\n searchTrailing: (tableId: string): InjectionSpotId => `data-table:${tableId}:search-trailing`,\n emptyState: (tableId: string): InjectionSpotId => `data-table:${tableId}:empty-state`,\n columns: (tableId: string): InjectionSpotId => `data-table:${tableId}:columns`,\n rowActions: (tableId: string): InjectionSpotId => `data-table:${tableId}:row-actions`,\n bulkActions: (tableId: string): InjectionSpotId => `data-table:${tableId}:bulk-actions`,\n filters: (tableId: string): InjectionSpotId => `data-table:${tableId}:filters`,\n} as const\n\n// Portal chrome spot IDs (FROZEN once shipped)\nexport const PORTAL_SIDEBAR_MAIN_INJECTION_SPOT_ID: InjectionSpotId = 'menu:portal:sidebar:main'\nexport const PORTAL_SIDEBAR_ACCOUNT_INJECTION_SPOT_ID: InjectionSpotId = 'menu:portal:sidebar:account'\nexport const PORTAL_HEADER_ACTIONS_INJECTION_SPOT_ID: InjectionSpotId = 'menu:portal:header:actions'\nexport const PORTAL_USER_DROPDOWN_INJECTION_SPOT_ID: InjectionSpotId = 'menu:portal:user-dropdown'\n\n// Portal page injection spots (FROZEN once shipped)\nexport const PortalInjectionSpots = {\n dashboardSections: 'portal:dashboard:sections' as InjectionSpotId,\n dashboardProfile: 'portal:dashboard:profile' as InjectionSpotId,\n dashboardSidebar: 'portal:dashboard:sidebar' as InjectionSpotId,\n pageBefore: (pageId: string): InjectionSpotId => `portal:${pageId}:before` as InjectionSpotId,\n pageAfter: (pageId: string): InjectionSpotId => `portal:${pageId}:after` as InjectionSpotId,\n} as const\n\nexport const DetailInjectionSpots = {\n header: (entityId: string): InjectionSpotId => `detail:${entityId}:header`,\n tabs: (entityId: string): InjectionSpotId => `detail:${entityId}:tabs`,\n sidebar: (entityId: string): InjectionSpotId => `detail:${entityId}:sidebar`,\n footer: (entityId: string): InjectionSpotId => `detail:${entityId}:footer`,\n statusBadges: (entityId: string): InjectionSpotId => `detail:${entityId}:status-badges`,\n} as const\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,2CAA4D;AAClE,MAAM,uCAAwD;AAC9D,MAAM,0CAA2D;AACjE,MAAM,wCAAyD;AAC/D,MAAM,2CAA4D;AAGlE,MAAM,gDAAiE;AACvE,MAAM,2CAA4D;AAClE,MAAM,wCAAyD;AAC/D,MAAM,+CAAgE;AAGtE,MAAM,iDAAkE;AACxE,MAAM,oDAAqE;AAG3E,MAAM,yBAAyB;AAAA,EACpC,MAAM,CAAC,aAAsC,aAAa,QAAQ;AAAA,EAClE,cAAc,CAAC,aAAsC,aAAa,QAAQ;AAAA,EAC1E,aAAa,CAAC,aAAsC,aAAa,QAAQ;AAAA,EACzE,QAAQ,CAAC,aAAsC,aAAa,QAAQ;AAAA,EACpE,QAAQ,CAAC,aAAsC,aAAa,QAAQ;AAAA,EACpE,SAAS,CAAC,aAAsC,aAAa,QAAQ;AAAA,EACrE,OAAO,CAAC,UAAkB,YAAqC,aAAa,QAAQ,UAAU,OAAO;AAAA,EACrG,aAAa,CAAC,UAAkB,YAAqC,aAAa,QAAQ,UAAU,OAAO;AAAA,EAC3G,YAAY,CAAC,UAAkB,YAAqC,aAAa,QAAQ,UAAU,OAAO;AAC5G;AAEO,MAAM,0BAA0B;AAAA,EACrC,QAAQ,CAAC,YAAqC,cAAc,OAAO;AAAA,EACnE,QAAQ,CAAC,YAAqC,cAAc,OAAO;AAAA,EACnE,SAAS,CAAC,YAAqC,cAAc,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpE,gBAAgB,CAAC,YAAqC,cAAc,OAAO;AAAA,EAC3E,YAAY,CAAC,YAAqC,cAAc,OAAO;AAAA,EACvE,SAAS,CAAC,YAAqC,cAAc,OAAO;AAAA,EACpE,YAAY,CAAC,YAAqC,cAAc,OAAO;AAAA,EACvE,aAAa,CAAC,YAAqC,cAAc,OAAO;AAAA,EACxE,SAAS,CAAC,YAAqC,cAAc,OAAO;AACtE;AAGO,MAAM,wCAAyD;AAC/D,MAAM,2CAA4D;AAClE,MAAM,0CAA2D;AACjE,MAAM,yCAA0D;AAGhE,MAAM,uBAAuB;AAAA,EAClC,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,YAAY,CAAC,WAAoC,UAAU,MAAM;AAAA,EACjE,WAAW,CAAC,WAAoC,UAAU,MAAM;AAClE;AAEO,MAAM,uBAAuB;AAAA,EAClC,QAAQ,CAAC,aAAsC,UAAU,QAAQ;AAAA,EACjE,MAAM,CAAC,aAAsC,UAAU,QAAQ;AAAA,EAC/D,SAAS,CAAC,aAAsC,UAAU,QAAQ;AAAA,EAClE,QAAQ,CAAC,aAAsC,UAAU,QAAQ;AAAA,EACjE,cAAc,CAAC,aAAsC,UAAU,QAAQ;AACzE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -47,9 +47,9 @@ function getStatusLabel(status, t) {
|
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
function getKindStyles(kind) {
|
|
50
|
-
if (kind === "event") return "border-
|
|
51
|
-
if (kind === "exception") return "border-
|
|
52
|
-
return "border-
|
|
50
|
+
if (kind === "event") return "border-blue-500/40 bg-blue-500/10 text-blue-950";
|
|
51
|
+
if (kind === "exception") return "border-amber-500/40 bg-amber-500/10 text-amber-950";
|
|
52
|
+
return "border-emerald-500/40 bg-emerald-500/10 text-emerald-950";
|
|
53
53
|
}
|
|
54
54
|
function ScheduleAgenda({ items, range, timezone, onItemClick, onSlotClick, className }) {
|
|
55
55
|
const t = useT();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/schedule/ScheduleAgenda.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ScheduleItem, ScheduleRange, ScheduleSlot } from './types'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '../../primitives/badge'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { expandRecurringItems } from './recurrence'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction startOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate())\n}\n\nfunction endOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate(), 23, 59, 59, 999)\n}\n\nfunction eachDay(start: Date, end: Date): Date[] {\n const days: Date[] = []\n let cursor = startOfDay(start)\n const last = startOfDay(end)\n while (cursor <= last) {\n days.push(new Date(cursor))\n cursor = new Date(cursor.getTime() + DAY_MS)\n }\n return days\n}\n\nfunction overlapsDay(item: ScheduleItem, day: Date): boolean {\n const dayStart = startOfDay(day)\n const dayEnd = endOfDay(day)\n return item.startsAt <= dayEnd && item.endsAt >= dayStart\n}\n\nfunction formatDayLabel(day: Date): string {\n return day.toLocaleDateString(undefined, { weekday: 'long', month: 'short', day: 'numeric' })\n}\n\nfunction formatTimeRange(item: ScheduleItem, timezone?: string): string {\n const options: Intl.DateTimeFormatOptions = { hour: '2-digit', minute: '2-digit' }\n if (timezone) options.timeZone = timezone\n const startLabel = item.startsAt.toLocaleTimeString(undefined, options)\n const endLabel = item.endsAt.toLocaleTimeString(undefined, options)\n return `${startLabel}-${endLabel}`\n}\n\nfunction getStatusLabel(status: ScheduleItem['status'], t: (key: string, fallback?: string) => string): string | null {\n if (!status) return null\n if (status === 'draft') return t('schedule.item.status.draft', 'Draft')\n if (status === 'negotiation') return t('schedule.item.status.negotiation', 'Negotiation')\n if (status === 'confirmed') return t('schedule.item.status.confirmed', 'Confirmed')\n if (status === 'cancelled') return t('schedule.item.status.cancelled', 'Cancelled')\n return null\n}\n\nfunction getKindStyles(kind: ScheduleItem['kind']): string {\n if (kind === 'event') return 'border-
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ScheduleItem, ScheduleRange, ScheduleSlot } from './types'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '../../primitives/badge'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { expandRecurringItems } from './recurrence'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction startOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate())\n}\n\nfunction endOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate(), 23, 59, 59, 999)\n}\n\nfunction eachDay(start: Date, end: Date): Date[] {\n const days: Date[] = []\n let cursor = startOfDay(start)\n const last = startOfDay(end)\n while (cursor <= last) {\n days.push(new Date(cursor))\n cursor = new Date(cursor.getTime() + DAY_MS)\n }\n return days\n}\n\nfunction overlapsDay(item: ScheduleItem, day: Date): boolean {\n const dayStart = startOfDay(day)\n const dayEnd = endOfDay(day)\n return item.startsAt <= dayEnd && item.endsAt >= dayStart\n}\n\nfunction formatDayLabel(day: Date): string {\n return day.toLocaleDateString(undefined, { weekday: 'long', month: 'short', day: 'numeric' })\n}\n\nfunction formatTimeRange(item: ScheduleItem, timezone?: string): string {\n const options: Intl.DateTimeFormatOptions = { hour: '2-digit', minute: '2-digit' }\n if (timezone) options.timeZone = timezone\n const startLabel = item.startsAt.toLocaleTimeString(undefined, options)\n const endLabel = item.endsAt.toLocaleTimeString(undefined, options)\n return `${startLabel}-${endLabel}`\n}\n\nfunction getStatusLabel(status: ScheduleItem['status'], t: (key: string, fallback?: string) => string): string | null {\n if (!status) return null\n if (status === 'draft') return t('schedule.item.status.draft', 'Draft')\n if (status === 'negotiation') return t('schedule.item.status.negotiation', 'Negotiation')\n if (status === 'confirmed') return t('schedule.item.status.confirmed', 'Confirmed')\n if (status === 'cancelled') return t('schedule.item.status.cancelled', 'Cancelled')\n return null\n}\n\nfunction getKindStyles(kind: ScheduleItem['kind']): string {\n if (kind === 'event') return 'border-blue-500/40 bg-blue-500/10 text-blue-950'\n if (kind === 'exception') return 'border-amber-500/40 bg-amber-500/10 text-amber-950'\n return 'border-emerald-500/40 bg-emerald-500/10 text-emerald-950'\n}\n\nexport type ScheduleAgendaProps = {\n items: ScheduleItem[]\n range: ScheduleRange\n timezone?: string\n onItemClick?: (item: ScheduleItem) => void\n onSlotClick?: (slot: ScheduleSlot) => void\n className?: string\n}\n\nexport function ScheduleAgenda({ items, range, timezone, onItemClick, onSlotClick, className }: ScheduleAgendaProps) {\n const t = useT()\n const days = React.useMemo(() => eachDay(range.start, range.end), [range])\n const expandedItems = React.useMemo(() => expandRecurringItems(items, range), [items, range])\n\n return (\n <div className={cn('space-y-4', className)}>\n {days.map((day) => {\n const dayItems = expandedItems.filter((item) => overlapsDay(item, day))\n const slotStart = new Date(day.getFullYear(), day.getMonth(), day.getDate(), 9, 0, 0)\n const slotEnd = new Date(day.getFullYear(), day.getMonth(), day.getDate(), 10, 0, 0)\n return (\n <div key={day.toISOString()} className=\"rounded-xl border bg-card p-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-sm font-semibold text-foreground\">{formatDayLabel(day)}</div>\n {onSlotClick ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onSlotClick({ start: slotStart, end: slotEnd })}\n >\n {t('schedule.actions.add', 'Add')}\n </Button>\n ) : null}\n </div>\n <div className=\"mt-3 space-y-2\">\n {dayItems.length === 0 ? (\n <div className=\"rounded-lg border border-dashed p-3 text-xs text-muted-foreground\">\n {t('schedule.emptyDay', 'No scheduled items')}\n </div>\n ) : (\n dayItems.map((item) => {\n const statusLabel = getStatusLabel(item.status, t)\n return (\n <button\n key={item.id}\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-2 rounded-lg border px-3 py-2 text-left text-xs transition hover:shadow-sm',\n getKindStyles(item.kind)\n )}\n onClick={() => onItemClick?.(item)}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-semibold\">{item.title}</span>\n {statusLabel ? <Badge variant=\"secondary\">{statusLabel}</Badge> : null}\n </div>\n <div className=\"flex items-center justify-between text-overline text-muted-foreground\">\n <span>{formatTimeRange(item, timezone)}</span>\n <span className=\"capitalize\">{item.kind}</span>\n </div>\n </button>\n )\n })\n )}\n </div>\n </div>\n )\n })}\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -47,9 +47,9 @@ function getStatusLabel(status, t) {
|
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
function getKindStyles(kind) {
|
|
50
|
-
if (kind === "event") return "border-
|
|
51
|
-
if (kind === "exception") return "border-
|
|
52
|
-
return "border-
|
|
50
|
+
if (kind === "event") return "border-blue-500/40 bg-blue-500/10 text-blue-950";
|
|
51
|
+
if (kind === "exception") return "border-amber-500/40 bg-amber-500/10 text-amber-950";
|
|
52
|
+
return "border-emerald-500/40 bg-emerald-500/10 text-emerald-950";
|
|
53
53
|
}
|
|
54
54
|
function ScheduleGrid({ items, range, timezone, onItemClick, onSlotClick, className }) {
|
|
55
55
|
const t = useT();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/schedule/ScheduleGrid.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ScheduleItem, ScheduleRange, ScheduleSlot } from './types'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '../../primitives/badge'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { expandRecurringItems } from './recurrence'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction startOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate())\n}\n\nfunction endOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate(), 23, 59, 59, 999)\n}\n\nfunction eachDay(start: Date, end: Date): Date[] {\n const days: Date[] = []\n let cursor = startOfDay(start)\n const last = startOfDay(end)\n while (cursor <= last) {\n days.push(new Date(cursor))\n cursor = new Date(cursor.getTime() + DAY_MS)\n }\n return days\n}\n\nfunction overlapsDay(item: ScheduleItem, day: Date): boolean {\n const dayStart = startOfDay(day)\n const dayEnd = endOfDay(day)\n return item.startsAt <= dayEnd && item.endsAt >= dayStart\n}\n\nfunction formatDayLabel(day: Date): string {\n return day.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })\n}\n\nfunction formatTimeRange(item: ScheduleItem, timezone?: string): string {\n const options: Intl.DateTimeFormatOptions = { hour: '2-digit', minute: '2-digit' }\n if (timezone) options.timeZone = timezone\n const startLabel = item.startsAt.toLocaleTimeString(undefined, options)\n const endLabel = item.endsAt.toLocaleTimeString(undefined, options)\n return `${startLabel}-${endLabel}`\n}\n\nfunction getStatusLabel(status: ScheduleItem['status'], t: (key: string, fallback?: string) => string): string | null {\n if (!status) return null\n if (status === 'draft') return t('schedule.item.status.draft', 'Draft')\n if (status === 'negotiation') return t('schedule.item.status.negotiation', 'Negotiation')\n if (status === 'confirmed') return t('schedule.item.status.confirmed', 'Confirmed')\n if (status === 'cancelled') return t('schedule.item.status.cancelled', 'Cancelled')\n return null\n}\n\nfunction getKindStyles(kind: ScheduleItem['kind']): string {\n if (kind === 'event') return 'border-
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { ScheduleItem, ScheduleRange, ScheduleSlot } from './types'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '../../primitives/badge'\nimport { Button } from '../../primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { expandRecurringItems } from './recurrence'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction startOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate())\n}\n\nfunction endOfDay(value: Date): Date {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate(), 23, 59, 59, 999)\n}\n\nfunction eachDay(start: Date, end: Date): Date[] {\n const days: Date[] = []\n let cursor = startOfDay(start)\n const last = startOfDay(end)\n while (cursor <= last) {\n days.push(new Date(cursor))\n cursor = new Date(cursor.getTime() + DAY_MS)\n }\n return days\n}\n\nfunction overlapsDay(item: ScheduleItem, day: Date): boolean {\n const dayStart = startOfDay(day)\n const dayEnd = endOfDay(day)\n return item.startsAt <= dayEnd && item.endsAt >= dayStart\n}\n\nfunction formatDayLabel(day: Date): string {\n return day.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })\n}\n\nfunction formatTimeRange(item: ScheduleItem, timezone?: string): string {\n const options: Intl.DateTimeFormatOptions = { hour: '2-digit', minute: '2-digit' }\n if (timezone) options.timeZone = timezone\n const startLabel = item.startsAt.toLocaleTimeString(undefined, options)\n const endLabel = item.endsAt.toLocaleTimeString(undefined, options)\n return `${startLabel}-${endLabel}`\n}\n\nfunction getStatusLabel(status: ScheduleItem['status'], t: (key: string, fallback?: string) => string): string | null {\n if (!status) return null\n if (status === 'draft') return t('schedule.item.status.draft', 'Draft')\n if (status === 'negotiation') return t('schedule.item.status.negotiation', 'Negotiation')\n if (status === 'confirmed') return t('schedule.item.status.confirmed', 'Confirmed')\n if (status === 'cancelled') return t('schedule.item.status.cancelled', 'Cancelled')\n return null\n}\n\nfunction getKindStyles(kind: ScheduleItem['kind']): string {\n if (kind === 'event') return 'border-blue-500/40 bg-blue-500/10 text-blue-950'\n if (kind === 'exception') return 'border-amber-500/40 bg-amber-500/10 text-amber-950'\n return 'border-emerald-500/40 bg-emerald-500/10 text-emerald-950'\n}\n\nexport type ScheduleGridProps = {\n items: ScheduleItem[]\n range: ScheduleRange\n timezone?: string\n onItemClick?: (item: ScheduleItem) => void\n onSlotClick?: (slot: ScheduleSlot) => void\n className?: string\n}\n\nexport function ScheduleGrid({ items, range, timezone, onItemClick, onSlotClick, className }: ScheduleGridProps) {\n const t = useT()\n const days = React.useMemo(() => eachDay(range.start, range.end), [range])\n const expandedItems = React.useMemo(() => expandRecurringItems(items, range), [items, range])\n\n return (\n <div className={cn('grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3', className)}>\n {days.map((day) => {\n const dayItems = expandedItems.filter((item) => overlapsDay(item, day))\n const slotStart = new Date(day.getFullYear(), day.getMonth(), day.getDate(), 9, 0, 0)\n const slotEnd = new Date(day.getFullYear(), day.getMonth(), day.getDate(), 10, 0, 0)\n return (\n <div key={day.toISOString()} className=\"rounded-xl border bg-card p-4 shadow-sm\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-sm font-semibold text-foreground\">{formatDayLabel(day)}</div>\n {onSlotClick ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onSlotClick({ start: slotStart, end: slotEnd })}\n >\n {t('schedule.actions.add', 'Add')}\n </Button>\n ) : null}\n </div>\n <div className=\"mt-3 space-y-2\">\n {dayItems.length === 0 ? (\n <div className=\"rounded-lg border border-dashed p-3 text-xs text-muted-foreground\">\n {t('schedule.emptyDay', 'No scheduled items')}\n </div>\n ) : (\n dayItems.map((item) => {\n const statusLabel = getStatusLabel(item.status, t)\n return (\n <button\n key={item.id}\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-2 rounded-lg border px-3 py-2 text-left text-xs transition hover:shadow-sm',\n getKindStyles(item.kind)\n )}\n onClick={() => onItemClick?.(item)}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-semibold\">{item.title}</span>\n {statusLabel ? <Badge variant=\"secondary\">{statusLabel}</Badge> : null}\n </div>\n <div className=\"flex items-center justify-between text-overline text-muted-foreground\">\n <span>{formatTimeRange(item, timezone)}</span>\n <span className=\"capitalize\">{item.kind}</span>\n </div>\n </button>\n )\n })\n )}\n </div>\n </div>\n )\n })}\n </div>\n )\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
SegmentedControl,
|
|
8
|
-
SegmentedControlItem
|
|
9
|
-
} from "../../primitives/segmented-control.js";
|
|
10
|
-
import {
|
|
11
|
-
Select,
|
|
12
|
-
SelectContent,
|
|
13
|
-
SelectItem,
|
|
14
|
-
SelectTrigger,
|
|
15
|
-
SelectValue
|
|
16
|
-
} from "../../primitives/select.js";
|
|
4
|
+
import { Button } from "../../primitives/button.js";
|
|
5
|
+
import { Input } from "../../primitives/input.js";
|
|
17
6
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
18
7
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
19
8
|
import { addDays } from "date-fns/addDays";
|
|
@@ -35,19 +24,16 @@ const VIEW_OPTIONS = [
|
|
|
35
24
|
{ id: "month", labelKey: "schedule.view.month", fallback: "Month" },
|
|
36
25
|
{ id: "agenda", labelKey: "schedule.view.agenda", fallback: "Agenda" }
|
|
37
26
|
];
|
|
38
|
-
function
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
return Array.from(options).sort((a, b) => a.localeCompare(b));
|
|
27
|
+
function formatDateInputValue(value) {
|
|
28
|
+
const year = value.getFullYear();
|
|
29
|
+
const month = String(value.getMonth() + 1).padStart(2, "0");
|
|
30
|
+
const day = String(value.getDate()).padStart(2, "0");
|
|
31
|
+
return `${year}-${month}-${day}`;
|
|
32
|
+
}
|
|
33
|
+
function parseDateInputValue(value, fallback) {
|
|
34
|
+
if (!value) return fallback;
|
|
35
|
+
const next = /* @__PURE__ */ new Date(`${value}T00:00:00`);
|
|
36
|
+
return Number.isNaN(next.getTime()) ? fallback : next;
|
|
51
37
|
}
|
|
52
38
|
function ScheduleToolbar({
|
|
53
39
|
view,
|
|
@@ -117,73 +103,70 @@ function ScheduleToolbar({
|
|
|
117
103
|
const nextStart = startOfDay(addDays(range.start, multiplier * rangeLength));
|
|
118
104
|
onRangeChange({ start: nextStart, end: endOfDay(addDays(nextStart, rangeLength - 1)) });
|
|
119
105
|
}, [onRangeChange, range.start, rangeLength, view]);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
SegmentedControl,
|
|
106
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3 rounded-xl border bg-card p-4 md:flex-row md:items-center md:justify-between", className), children: [
|
|
107
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: VIEW_OPTIONS.map((option) => /* @__PURE__ */ jsx(
|
|
108
|
+
Button,
|
|
124
109
|
{
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
onViewChange(
|
|
130
|
-
onRangeChange(deriveRangeForView(/* @__PURE__ */ new Date(),
|
|
110
|
+
variant: view === option.id ? "default" : "outline",
|
|
111
|
+
size: "sm",
|
|
112
|
+
onClick: () => {
|
|
113
|
+
if (option.id === view) return;
|
|
114
|
+
onViewChange(option.id);
|
|
115
|
+
onRangeChange(deriveRangeForView(/* @__PURE__ */ new Date(), option.id));
|
|
131
116
|
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/* @__PURE__ */ jsx(
|
|
139
|
-
|
|
140
|
-
{
|
|
141
|
-
type: "button",
|
|
142
|
-
variant: "outline",
|
|
143
|
-
onClick: () => shiftRange("prev"),
|
|
144
|
-
"aria-label": t("schedule.range.prev", "Previous"),
|
|
145
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": true })
|
|
146
|
-
}
|
|
147
|
-
),
|
|
148
|
-
/* @__PURE__ */ jsx("div", { className: "min-w-0 whitespace-nowrap px-1 text-sm font-medium text-foreground", children: rangeLabel }),
|
|
149
|
-
/* @__PURE__ */ jsx(
|
|
150
|
-
IconButton,
|
|
151
|
-
{
|
|
152
|
-
type: "button",
|
|
153
|
-
variant: "outline",
|
|
154
|
-
onClick: () => shiftRange("next"),
|
|
155
|
-
"aria-label": t("schedule.range.next", "Next"),
|
|
156
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": true })
|
|
157
|
-
}
|
|
158
|
-
)
|
|
117
|
+
children: t(option.labelKey, option.fallback)
|
|
118
|
+
},
|
|
119
|
+
option.id
|
|
120
|
+
)) }),
|
|
121
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
122
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => shiftRange("prev"), "aria-label": t("schedule.range.prev", "Previous"), children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": true }) }),
|
|
123
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-foreground", children: rangeLabel }),
|
|
124
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => shiftRange("next"), "aria-label": t("schedule.range.next", "Next"), children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": true }) })
|
|
159
125
|
] }),
|
|
160
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
161
|
-
/* @__PURE__ */
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
126
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
127
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
128
|
+
/* @__PURE__ */ jsx("span", { children: t("schedule.range.start", "Start") }),
|
|
129
|
+
/* @__PURE__ */ jsx(
|
|
130
|
+
Input,
|
|
131
|
+
{
|
|
132
|
+
type: "date",
|
|
133
|
+
value: formatDateInputValue(range.start),
|
|
134
|
+
onChange: (event) => {
|
|
135
|
+
const nextStart = parseDateInputValue(event.target.value, range.start);
|
|
136
|
+
onRangeChange({ start: nextStart, end: range.end });
|
|
137
|
+
},
|
|
138
|
+
className: "h-8 w-full sm:w-[140px]"
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
] }),
|
|
142
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
143
|
+
/* @__PURE__ */ jsx("span", { children: t("schedule.range.end", "End") }),
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
Input,
|
|
146
|
+
{
|
|
147
|
+
type: "date",
|
|
148
|
+
value: formatDateInputValue(range.end),
|
|
149
|
+
onChange: (event) => {
|
|
150
|
+
const nextEnd = parseDateInputValue(event.target.value, range.end);
|
|
151
|
+
onRangeChange({ start: range.start, end: nextEnd });
|
|
152
|
+
},
|
|
153
|
+
className: "h-8 w-full sm:w-[140px]"
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
] }),
|
|
157
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
158
|
+
/* @__PURE__ */ jsx("span", { children: t("schedule.range.timezone", "Timezone") }),
|
|
176
159
|
/* @__PURE__ */ jsx(
|
|
177
|
-
|
|
160
|
+
Input,
|
|
178
161
|
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
162
|
+
type: "text",
|
|
163
|
+
value: timezone ?? "",
|
|
164
|
+
onChange: (event) => onTimezoneChange?.(event.target.value),
|
|
165
|
+
className: "h-8 w-full sm:w-[180px]",
|
|
166
|
+
placeholder: t("schedule.range.timezone.placeholder", "UTC")
|
|
183
167
|
}
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
] }) : null
|
|
168
|
+
)
|
|
169
|
+
] })
|
|
187
170
|
] })
|
|
188
171
|
] });
|
|
189
172
|
}
|