@alfakit/react 0.1.10 → 0.1.12
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/CHANGELOG.md +12 -0
- package/dist/components/actions/action-button.js +13 -1
- package/dist/components/actions/action-button.js.map +1 -1
- package/dist/components/dev-tools/dev-tools-inspector.js +2 -2
- package/dist/components/dev-tools/dev-tools-inspector.js.map +1 -1
- package/dist/components/entries/other-entries.d.ts.map +1 -1
- package/dist/components/entries/other-entries.js +1 -1
- package/dist/components/entries/other-entries.js.map +1 -1
- package/dist/components/fields/builder.d.ts.map +1 -1
- package/dist/components/fields/builder.js +3 -3
- package/dist/components/fields/builder.js.map +1 -1
- package/dist/components/fields/file-upload.d.ts.map +1 -1
- package/dist/components/fields/file-upload.js +2 -5
- package/dist/components/fields/file-upload.js.map +1 -1
- package/dist/components/fields/money-input.d.ts +5 -0
- package/dist/components/fields/money-input.d.ts.map +1 -1
- package/dist/components/fields/money-input.js +2 -5
- package/dist/components/fields/money-input.js.map +1 -1
- package/dist/components/fields/repeater.d.ts.map +1 -1
- package/dist/components/fields/repeater.js +3 -3
- package/dist/components/fields/repeater.js.map +1 -1
- package/dist/components/fields/rich-editor-extensions.js +5 -2
- package/dist/components/fields/rich-editor-extensions.js.map +1 -1
- package/dist/components/layout/wizard.d.ts.map +1 -1
- package/dist/components/layout/wizard.js +4 -1
- package/dist/components/layout/wizard.js.map +1 -1
- package/dist/components/notifications/flash-toasts.d.ts.map +1 -1
- package/dist/components/notifications/flash-toasts.js +11 -1
- package/dist/components/notifications/flash-toasts.js.map +1 -1
- package/dist/components/notifications/notifications-menu.js +3 -3
- package/dist/components/notifications/notifications-menu.js.map +1 -1
- package/dist/components/panel/lazy-placeholder.d.ts +1 -0
- package/dist/components/panel/lazy-placeholder.d.ts.map +1 -1
- package/dist/components/panel/lazy-placeholder.js +38 -4
- package/dist/components/panel/lazy-placeholder.js.map +1 -1
- package/dist/components/panel/pwa.d.ts.map +1 -1
- package/dist/components/panel/pwa.js +8 -7
- package/dist/components/panel/pwa.js.map +1 -1
- package/dist/components/panel/shortcuts-overlay.js +1 -1
- package/dist/components/panel/shortcuts-overlay.js.map +1 -1
- package/dist/components/table/cells.js +2 -2
- package/dist/components/table/cells.js.map +1 -1
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/calendar.js +7 -0
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/widgets/dashboard-customizer.js +2 -2
- package/dist/components/widgets/dashboard-customizer.js.map +1 -1
- package/dist/components/widgets/widgets-block.js +2 -2
- package/dist/components/widgets/widgets-block.js.map +1 -1
- package/dist/components.css +19 -0
- package/dist/create-alfakit.d.ts.map +1 -1
- package/dist/create-alfakit.js +3 -2
- package/dist/create-alfakit.js.map +1 -1
- package/dist/eject-manifest.json +4 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/pages/page.js +1 -1
- package/dist/pages/page.js.map +1 -1
- package/dist/standalone/alfakit-component.js +2 -2
- package/dist/standalone/alfakit-component.js.map +1 -1
- package/dist/standalone.css +21 -0
- package/dist/starter-kit/index.d.ts +2 -2
- package/dist/starter-kit/index.js +2 -2
- package/dist/starter-kit/starter-kit.d.ts +9 -0
- package/dist/starter-kit/starter-kit.d.ts.map +1 -1
- package/dist/starter-kit/starter-kit.js +21 -2
- package/dist/starter-kit/starter-kit.js.map +1 -1
- package/package.json +2 -2
- package/src/components/actions/action-button.tsx +15 -1
- package/src/components/dev-tools/dev-tools-inspector.tsx +6 -1
- package/src/components/entries/other-entries.tsx +2 -0
- package/src/components/fields/builder.tsx +7 -2
- package/src/components/fields/file-upload.tsx +2 -7
- package/src/components/fields/money-input.tsx +3 -14
- package/src/components/fields/repeater.tsx +6 -3
- package/src/components/fields/rich-editor-extensions.tsx +9 -5
- package/src/components/layout/wizard.tsx +5 -1
- package/src/components/notifications/flash-toasts.tsx +8 -0
- package/src/components/notifications/notifications-menu.tsx +3 -3
- package/src/components/panel/lazy-placeholder.tsx +41 -1
- package/src/components/panel/pwa.tsx +23 -9
- package/src/components/panel/shortcuts-overlay.tsx +1 -1
- package/src/components/table/cells.tsx +6 -2
- package/src/components/ui/calendar.tsx +8 -0
- package/src/components/widgets/dashboard-customizer.tsx +2 -2
- package/src/components/widgets/widgets-block.tsx +2 -2
- package/src/create-alfakit.tsx +9 -1
- package/src/pages/page.tsx +1 -1
- package/src/standalone/alfakit-component.tsx +2 -2
- package/src/starter-kit/index.ts +1 -0
- package/src/starter-kit/starter-kit.tsx +22 -0
package/dist/index.d.ts
CHANGED
|
@@ -147,7 +147,7 @@ import { configureAlfakit } from "./standalone/configure.js";
|
|
|
147
147
|
import "./standalone/index.js";
|
|
148
148
|
import { AlfakitWidgets, AlfakitWidgetsProps } from "./starter-kit/dashboard-widgets.js";
|
|
149
149
|
import { AlfakitNavigation, useAlfakitNavigation } from "./starter-kit/navigation.js";
|
|
150
|
-
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitLayout, StarterKitPageOptions, createStarterKitPage } from "./starter-kit/starter-kit.js";
|
|
150
|
+
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitFullscreenLayout, StarterKitLayout, StarterKitPageOptions, createStarterKitPage } from "./starter-kit/starter-kit.js";
|
|
151
151
|
import { AlfakitCopilot, AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitTenantSwitcher } from "./starter-kit/widgets.js";
|
|
152
152
|
import "./starter-kit/index.js";
|
|
153
153
|
import { Alert, AlertDescription, AlertTitle } from "./components/ui/alert.js";
|
|
@@ -180,4 +180,4 @@ import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, Tabl
|
|
|
180
180
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs.js";
|
|
181
181
|
import { Textarea } from "./components/ui/textarea.js";
|
|
182
182
|
export * from "@alfakit/core";
|
|
183
|
-
export { ActionButton, ActionGroupMenu, ActionList, ActionModals, AiCopilot, AiStream, Alert, AlertDescription, AlertTitle, AlfakitAnalytics, AlfakitComponent, type AlfakitComponentProps, type AlfakitContextValue, AlfakitCopilot, type AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, type AlfakitNavigation, AlfakitNotifications, AlfakitPage, AlfakitProvider, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitToaster, type AlfakitToasterProps, AlfakitWidgets, type AlfakitWidgetsProps, AnalyticsBreakdown, type AnyComponent, AppLayout, AppPage, AppSidebar, AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BlankLayout, BottomNav, Brand, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, BuilderField, Button, CMS_BLOCK_COMPONENTS, Calendar, CalendarWidget, CallToActionBlock, CalloutComponent, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartWidget, Checkbox, CheckboxField, CheckboxListField, CmsBlockHeading, type CmsBlockProps, CmsBlocks, type CmsContextValue, CmsFooter, CmsHead, CmsHeader, CmsImage, CmsLanguageSwitcher, CmsLinkButton, CmsLivePreview, CmsMenuList, CmsNav, CmsPage, CmsProvider, CodeEditorField, CodeEntryComponent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorEntryComponent, ColorPickerField, ColumnManager, ColumnsBlock, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConflictBanner, ContentBlockRenderer, ContentLayout, ContentLayoutSort, type CreateAlfakitOptions, CustomizableWidgetGrid, DataTable, DatePickerField, DebugPanel, DebugPanelSlot, DebugTreeNode, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type DiscoveredComponents, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmbedBlock, EmptyStateComponent, EntryPlaceholder, EntryWrapper, FaqBlock, FeaturesBlock, type FieldBinding, FieldWrapper, FieldsetComponent, FileManager, FileManagerPickerField, FileUploadField, FilterIndicators, FlashToasts, FlexComponent, FormBlock, FormProvider, FormattedText, FullscreenLayout, type FullscreenLayoutProps, FusedGroupComponent, GalleryBlock, GlobalSearch, GridComponent, HelpdeskChat, type HelpdeskChatProps, HelpdeskInbox, HeroBlock, HiddenField, HtmlComponent, Icon, IconComponent, IconEntryComponent, IconPickerField, ImageBlock, ImageComponent, ImageEntryComponent, ImpersonationBanner, Input, Kanban, KeyValueEntryComponent, KeyValueField, KeyboardShortcuts, Label, LazyPlaceholder, LiveRecordsPill, LocaleSubMenu, LocaleSwitcher, MixedContent, ModalTableSelectField, MoneyInputField, NotificationActionButton, NotificationsMenu, OneTimeCodeInputField, PageActionProvider, PageBlock, type PageBlockProps, PageContent, PageForm, PageHeader, PageInfolist, type PageMethodBinding, type PageMethodMap, type PageMethodsBinding, PageShell, PageTable, PageWidgets, PlaceholderComponent, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PwaManager, PwaMenuItems, QueryBuilderRulesField, RadioField, RadioGroup, RadioGroupItem, RealtimeNotifications, RecordCell, RecordPresence, RecordVersionsComponent, RenderComponent, RepeatableEntryComponent, RepeaterField, RichEditorField, RichTextBlock, SchemaChildren, SchemaRenderer, ScrollArea, ScrollBar, SectionBlock, SectionComponent, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, ShortcutKeys, ShortcutsOverlay, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignInLink, Skeleton, SliderField, Slot, Spinner, Spreadsheet, type StandaloneContextValue, StandaloneProvider, StarterKitContentLayout, type StarterKitLayout, type StarterKitPageOptions, StatsOverviewWidget, Switch, Table, TableBody, TableCaption, TableCell, TableCellContent, TableFilters, TableFooter, TableHead, TableHeader, TablePagination, TableRow, TableViews, Tabs, TabsComponent, TabsContent, TabsList, TabsTrigger, TagsInputField, TenantMenu, TestimonialsBlock, TextComponent, TextEntryComponent, TextInputField, Textarea, TextareaField, ThemeToggle, Toaster, ToggleButtonsField, ToggleField, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNavLayout, Topbar, TopbarLocaleSwitcher, TranslationManager, Tree, UndoButton, UnorderedListComponent, type UsePageMethodOptions, UserAvatar, UserMenu, ViewComponent, ViewEntryComponent, type VirtualListBinding, WidgetGrid, WidgetRenderer, WizardComponent, badgeColorClasses, badgeVariants, buttonVariants, cn, colorClass, configureAlfakit, createAlfakit, createDefaultRegistry, createStarterKitPage, cssColor, discoverComponents, discoveredComponent, extraProps, ghostButtonColorClasses, iconBackgroundColorClasses, iconSizeClasses, installPwa, outlineButtonColorClasses, panelLayouts, parseStyle, showToast, solidButtonColorClasses, switchOffColorClasses, switchOnColorClasses, textColorClasses, useActionRunner, useAlfakit, useAlfakitNavigation, useAlfakitProps, useAppPage, useChoice, useCms, useDirection, useField, useFormState, useFormStore, useFormatter, useHydrated, useIsMobile, useLiveProps, useLiveUpdates, useLocalization, useOptionalAlfakit, useOptionalFormStore, usePageActionContext, usePageBlock, usePageForm, usePageMethod, usePageMethods, usePageSchema, usePanel, usePollComponent, useRegistry, useReloadProps, useSchemaComponentContext, useScrollToErroredItem, useShortcut, useSidebar, useStandalone, useStore, useStoreSelector, useT, useVirtualList };
|
|
183
|
+
export { ActionButton, ActionGroupMenu, ActionList, ActionModals, AiCopilot, AiStream, Alert, AlertDescription, AlertTitle, AlfakitAnalytics, AlfakitComponent, type AlfakitComponentProps, type AlfakitContextValue, AlfakitCopilot, type AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, type AlfakitNavigation, AlfakitNotifications, AlfakitPage, AlfakitProvider, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitToaster, type AlfakitToasterProps, AlfakitWidgets, type AlfakitWidgetsProps, AnalyticsBreakdown, type AnyComponent, AppLayout, AppPage, AppSidebar, AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BlankLayout, BottomNav, Brand, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, BuilderField, Button, CMS_BLOCK_COMPONENTS, Calendar, CalendarWidget, CallToActionBlock, CalloutComponent, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartWidget, Checkbox, CheckboxField, CheckboxListField, CmsBlockHeading, type CmsBlockProps, CmsBlocks, type CmsContextValue, CmsFooter, CmsHead, CmsHeader, CmsImage, CmsLanguageSwitcher, CmsLinkButton, CmsLivePreview, CmsMenuList, CmsNav, CmsPage, CmsProvider, CodeEditorField, CodeEntryComponent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorEntryComponent, ColorPickerField, ColumnManager, ColumnsBlock, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConflictBanner, ContentBlockRenderer, ContentLayout, ContentLayoutSort, type CreateAlfakitOptions, CustomizableWidgetGrid, DataTable, DatePickerField, DebugPanel, DebugPanelSlot, DebugTreeNode, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type DiscoveredComponents, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmbedBlock, EmptyStateComponent, EntryPlaceholder, EntryWrapper, FaqBlock, FeaturesBlock, type FieldBinding, FieldWrapper, FieldsetComponent, FileManager, FileManagerPickerField, FileUploadField, FilterIndicators, FlashToasts, FlexComponent, FormBlock, FormProvider, FormattedText, FullscreenLayout, type FullscreenLayoutProps, FusedGroupComponent, GalleryBlock, GlobalSearch, GridComponent, HelpdeskChat, type HelpdeskChatProps, HelpdeskInbox, HeroBlock, HiddenField, HtmlComponent, Icon, IconComponent, IconEntryComponent, IconPickerField, ImageBlock, ImageComponent, ImageEntryComponent, ImpersonationBanner, Input, Kanban, KeyValueEntryComponent, KeyValueField, KeyboardShortcuts, Label, LazyPlaceholder, LiveRecordsPill, LocaleSubMenu, LocaleSwitcher, MixedContent, ModalTableSelectField, MoneyInputField, NotificationActionButton, NotificationsMenu, OneTimeCodeInputField, PageActionProvider, PageBlock, type PageBlockProps, PageContent, PageForm, PageHeader, PageInfolist, type PageMethodBinding, type PageMethodMap, type PageMethodsBinding, PageShell, PageTable, PageWidgets, PlaceholderComponent, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PwaManager, PwaMenuItems, QueryBuilderRulesField, RadioField, RadioGroup, RadioGroupItem, RealtimeNotifications, RecordCell, RecordPresence, RecordVersionsComponent, RenderComponent, RepeatableEntryComponent, RepeaterField, RichEditorField, RichTextBlock, SchemaChildren, SchemaRenderer, ScrollArea, ScrollBar, SectionBlock, SectionComponent, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, ShortcutKeys, ShortcutsOverlay, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignInLink, Skeleton, SliderField, Slot, Spinner, Spreadsheet, type StandaloneContextValue, StandaloneProvider, StarterKitContentLayout, StarterKitFullscreenLayout, type StarterKitLayout, type StarterKitPageOptions, StatsOverviewWidget, Switch, Table, TableBody, TableCaption, TableCell, TableCellContent, TableFilters, TableFooter, TableHead, TableHeader, TablePagination, TableRow, TableViews, Tabs, TabsComponent, TabsContent, TabsList, TabsTrigger, TagsInputField, TenantMenu, TestimonialsBlock, TextComponent, TextEntryComponent, TextInputField, Textarea, TextareaField, ThemeToggle, Toaster, ToggleButtonsField, ToggleField, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNavLayout, Topbar, TopbarLocaleSwitcher, TranslationManager, Tree, UndoButton, UnorderedListComponent, type UsePageMethodOptions, UserAvatar, UserMenu, ViewComponent, ViewEntryComponent, type VirtualListBinding, WidgetGrid, WidgetRenderer, WizardComponent, badgeColorClasses, badgeVariants, buttonVariants, cn, colorClass, configureAlfakit, createAlfakit, createDefaultRegistry, createStarterKitPage, cssColor, discoverComponents, discoveredComponent, extraProps, ghostButtonColorClasses, iconBackgroundColorClasses, iconSizeClasses, installPwa, outlineButtonColorClasses, panelLayouts, parseStyle, showToast, solidButtonColorClasses, switchOffColorClasses, switchOnColorClasses, textColorClasses, useActionRunner, useAlfakit, useAlfakitNavigation, useAlfakitProps, useAppPage, useChoice, useCms, useDirection, useField, useFormState, useFormStore, useFormatter, useHydrated, useIsMobile, useLiveProps, useLiveUpdates, useLocalization, useOptionalAlfakit, useOptionalFormStore, usePageActionContext, usePageBlock, usePageForm, usePageMethod, usePageMethods, usePageSchema, usePanel, usePollComponent, useRegistry, useReloadProps, useSchemaComponentContext, useScrollToErroredItem, useShortcut, useSidebar, useStandalone, useStore, useStoreSelector, useT, useVirtualList };
|
package/dist/index.js
CHANGED
|
@@ -156,9 +156,9 @@ import { AlfakitToaster } from "./standalone/alfakit-toaster.js";
|
|
|
156
156
|
import { AlfakitComponent } from "./standalone/alfakit-component.js";
|
|
157
157
|
import { AlfakitWidgets } from "./starter-kit/dashboard-widgets.js";
|
|
158
158
|
import { useAlfakitNavigation } from "./starter-kit/navigation.js";
|
|
159
|
-
import { AlfakitStarterKitRoot, StarterKitContentLayout, createStarterKitPage } from "./starter-kit/starter-kit.js";
|
|
159
|
+
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitFullscreenLayout, createStarterKitPage } from "./starter-kit/starter-kit.js";
|
|
160
160
|
import { AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitTenantSwitcher } from "./starter-kit/widgets.js";
|
|
161
161
|
import { Alert, AlertDescription, AlertTitle } from "./components/ui/alert.js";
|
|
162
162
|
import { Calendar } from "./components/ui/calendar.js";
|
|
163
163
|
export * from "@alfakit/core";
|
|
164
|
-
export { ActionButton, ActionGroupMenu, ActionList, ActionModals, AiCopilot, AiStream, Alert, AlertDescription, AlertTitle, AlfakitAnalytics, AlfakitComponent, AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitPage, AlfakitProvider, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitToaster, AlfakitWidgets, AnalyticsBreakdown, AppLayout, AppPage, AppSidebar, AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BlankLayout, BottomNav, Brand, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, BuilderField, Button, CMS_BLOCK_COMPONENTS, Calendar, CalendarWidget, CallToActionBlock, CalloutComponent, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartWidget, Checkbox, CheckboxField, CheckboxListField, CmsBlockHeading, CmsBlocks, CmsFooter, CmsHead, CmsHeader, CmsImage, CmsLanguageSwitcher, CmsLinkButton, CmsLivePreview, CmsMenuList, CmsNav, CmsPage, CmsProvider, CodeEditorField, CodeEntryComponent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorEntryComponent, ColorPickerField, ColumnManager, ColumnsBlock, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConflictBanner, ContentBlockRenderer, ContentLayout, ContentLayoutSort, CustomizableWidgetGrid, DataTable, DatePickerField, DebugPanel, DebugPanelSlot, DebugTreeNode, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmbedBlock, EmptyStateComponent, EntryPlaceholder, EntryWrapper, FaqBlock, FeaturesBlock, FieldWrapper, FieldsetComponent, FileManager, FileManagerPickerField, FileUploadField, FilterIndicators, FlashToasts, FlexComponent, FormBlock, FormProvider, FormattedText, FullscreenLayout, FusedGroupComponent, GalleryBlock, GlobalSearch, GridComponent, HelpdeskChat, HelpdeskInbox, HeroBlock, HiddenField, HtmlComponent, Icon, IconComponent, IconEntryComponent, IconPickerField, ImageBlock, ImageComponent, ImageEntryComponent, ImpersonationBanner, Input, Kanban, KeyValueEntryComponent, KeyValueField, KeyboardShortcuts, Label, LazyPlaceholder, LiveRecordsPill, LocaleSubMenu, LocaleSwitcher, MixedContent, ModalTableSelectField, MoneyInputField, NotificationActionButton, NotificationsMenu, OneTimeCodeInputField, PageActionProvider, PageBlock, PageContent, PageForm, PageHeader, PageInfolist, PageShell, PageTable, PageWidgets, PlaceholderComponent, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PwaManager, PwaMenuItems, QueryBuilderRulesField, RadioField, RadioGroup, RadioGroupItem, RealtimeNotifications, RecordCell, RecordPresence, RecordVersionsComponent, RenderComponent, RepeatableEntryComponent, RepeaterField, RichEditorField, RichTextBlock, SchemaChildren, SchemaRenderer, ScrollArea, ScrollBar, SectionBlock, SectionComponent, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, ShortcutKeys, ShortcutsOverlay, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignInLink, Skeleton, SliderField, Slot, Spinner, Spreadsheet, StandaloneProvider, StarterKitContentLayout, StatsOverviewWidget, Switch, Table, TableBody, TableCaption, TableCell, TableCellContent, TableFilters, TableFooter, TableHead, TableHeader, TablePagination, TableRow, TableViews, Tabs, TabsComponent, TabsContent, TabsList, TabsTrigger, TagsInputField, TenantMenu, TestimonialsBlock, TextComponent, TextEntryComponent, TextInputField, Textarea, TextareaField, ThemeToggle, Toaster, ToggleButtonsField, ToggleField, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNavLayout, Topbar, TopbarLocaleSwitcher, TranslationManager, Tree, UndoButton, UnorderedListComponent, UserAvatar, UserMenu, ViewComponent, ViewEntryComponent, WidgetGrid, WidgetRenderer, WizardComponent, badgeColorClasses, badgeVariants, buttonVariants, cn, colorClass, configureAlfakit, createAlfakit, createDefaultRegistry, createStarterKitPage, cssColor, discoverComponents, discoveredComponent, extraProps, ghostButtonColorClasses, iconBackgroundColorClasses, iconSizeClasses, installPwa, outlineButtonColorClasses, panelLayouts, parseStyle, showToast, solidButtonColorClasses, switchOffColorClasses, switchOnColorClasses, textColorClasses, useActionRunner, useAlfakit, useAlfakitNavigation, useAlfakitProps, useAppPage, useChoice, useCms, useDirection, useField, useFormState, useFormStore, useFormatter, useHydrated, useIsMobile, useLiveProps, useLiveUpdates, useLocalization, useOptionalAlfakit, useOptionalFormStore, usePageActionContext, usePageBlock, usePageForm, usePageMethod, usePageMethods, usePageSchema, usePanel, usePollComponent, useRegistry, useReloadProps, useSchemaComponentContext, useScrollToErroredItem, useShortcut, useSidebar, useStandalone, useStore, useStoreSelector, useT, useVirtualList };
|
|
164
|
+
export { ActionButton, ActionGroupMenu, ActionList, ActionModals, AiCopilot, AiStream, Alert, AlertDescription, AlertTitle, AlfakitAnalytics, AlfakitComponent, AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitPage, AlfakitProvider, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitToaster, AlfakitWidgets, AnalyticsBreakdown, AppLayout, AppPage, AppSidebar, AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BlankLayout, BottomNav, Brand, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Breadcrumbs, BuilderField, Button, CMS_BLOCK_COMPONENTS, Calendar, CalendarWidget, CallToActionBlock, CalloutComponent, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartWidget, Checkbox, CheckboxField, CheckboxListField, CmsBlockHeading, CmsBlocks, CmsFooter, CmsHead, CmsHeader, CmsImage, CmsLanguageSwitcher, CmsLinkButton, CmsLivePreview, CmsMenuList, CmsNav, CmsPage, CmsProvider, CodeEditorField, CodeEntryComponent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorEntryComponent, ColorPickerField, ColumnManager, ColumnsBlock, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConflictBanner, ContentBlockRenderer, ContentLayout, ContentLayoutSort, CustomizableWidgetGrid, DataTable, DatePickerField, DebugPanel, DebugPanelSlot, DebugTreeNode, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmbedBlock, EmptyStateComponent, EntryPlaceholder, EntryWrapper, FaqBlock, FeaturesBlock, FieldWrapper, FieldsetComponent, FileManager, FileManagerPickerField, FileUploadField, FilterIndicators, FlashToasts, FlexComponent, FormBlock, FormProvider, FormattedText, FullscreenLayout, FusedGroupComponent, GalleryBlock, GlobalSearch, GridComponent, HelpdeskChat, HelpdeskInbox, HeroBlock, HiddenField, HtmlComponent, Icon, IconComponent, IconEntryComponent, IconPickerField, ImageBlock, ImageComponent, ImageEntryComponent, ImpersonationBanner, Input, Kanban, KeyValueEntryComponent, KeyValueField, KeyboardShortcuts, Label, LazyPlaceholder, LiveRecordsPill, LocaleSubMenu, LocaleSwitcher, MixedContent, ModalTableSelectField, MoneyInputField, NotificationActionButton, NotificationsMenu, OneTimeCodeInputField, PageActionProvider, PageBlock, PageContent, PageForm, PageHeader, PageInfolist, PageShell, PageTable, PageWidgets, PlaceholderComponent, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PwaManager, PwaMenuItems, QueryBuilderRulesField, RadioField, RadioGroup, RadioGroupItem, RealtimeNotifications, RecordCell, RecordPresence, RecordVersionsComponent, RenderComponent, RepeatableEntryComponent, RepeaterField, RichEditorField, RichTextBlock, SchemaChildren, SchemaRenderer, ScrollArea, ScrollBar, SectionBlock, SectionComponent, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, ShortcutKeys, ShortcutsOverlay, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignInLink, Skeleton, SliderField, Slot, Spinner, Spreadsheet, StandaloneProvider, StarterKitContentLayout, StarterKitFullscreenLayout, StatsOverviewWidget, Switch, Table, TableBody, TableCaption, TableCell, TableCellContent, TableFilters, TableFooter, TableHead, TableHeader, TablePagination, TableRow, TableViews, Tabs, TabsComponent, TabsContent, TabsList, TabsTrigger, TagsInputField, TenantMenu, TestimonialsBlock, TextComponent, TextEntryComponent, TextInputField, Textarea, TextareaField, ThemeToggle, Toaster, ToggleButtonsField, ToggleField, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNavLayout, Topbar, TopbarLocaleSwitcher, TranslationManager, Tree, UndoButton, UnorderedListComponent, UserAvatar, UserMenu, ViewComponent, ViewEntryComponent, WidgetGrid, WidgetRenderer, WizardComponent, badgeColorClasses, badgeVariants, buttonVariants, cn, colorClass, configureAlfakit, createAlfakit, createDefaultRegistry, createStarterKitPage, cssColor, discoverComponents, discoveredComponent, extraProps, ghostButtonColorClasses, iconBackgroundColorClasses, iconSizeClasses, installPwa, outlineButtonColorClasses, panelLayouts, parseStyle, showToast, solidButtonColorClasses, switchOffColorClasses, switchOnColorClasses, textColorClasses, useActionRunner, useAlfakit, useAlfakitNavigation, useAlfakitProps, useAppPage, useChoice, useCms, useDirection, useField, useFormState, useFormStore, useFormatter, useHydrated, useIsMobile, useLiveProps, useLiveUpdates, useLocalization, useOptionalAlfakit, useOptionalFormStore, usePageActionContext, usePageBlock, usePageForm, usePageMethod, usePageMethods, usePageSchema, usePanel, usePollComponent, useRegistry, useReloadProps, useSchemaComponentContext, useScrollToErroredItem, useShortcut, useSidebar, useStandalone, useStore, useStoreSelector, useT, useVirtualList };
|
package/dist/pages/page.js
CHANGED
package/dist/pages/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","names":["FormBlock"],"sources":["../../src/pages/page.tsx"],"sourcesContent":["import type {\n ContentBlock,\n FormBlock as FormBlockSchema,\n InfolistBlock,\n LinksBlock,\n PageSchema,\n RelationManagersBlock,\n SchemaBlock,\n TableBlock as TableBlockSchema,\n WidgetsBlock as WidgetsBlockSchema,\n} from '@alfakit/core'\nimport {\n applyBodyAttributes,\n customPageProps,\n hasRelationManagerTabs,\n isLazyPlaceholder,\n openDefaultAction,\n RELATION_QUERY_KEY,\n relationManagerTabs,\n relationTabFromQuery,\n relationTabSlug,\n resolveLazyComponents,\n type DefaultActionOpener,\n} from '@alfakit/core'\nimport { Head, Link, usePage } from '@inertiajs/react'\nimport {\n createElement,\n Fragment,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { PageActionProvider } from '../components/actions/action-context'\nimport { ActionList } from '../components/actions/action-list'\nimport { FormBlock } from '../components/form/form-block'\nimport { KeyboardShortcuts } from '../components/panel/keyboard-shortcuts'\nimport { LazyPlaceholder } from '../components/panel/lazy-placeholder'\nimport { Slot } from '../components/panel/slot'\nimport { SubNavigationLayout } from '../components/panel/sub-navigation'\nimport { ConflictBanner } from '../components/realtime/conflict-banner'\nimport { RecordPresence } from '../components/realtime/record-presence'\nimport { SchemaRenderer } from '../components/schema/schema-renderer'\nimport { ListTabs, ListTabsPanel } from '../components/table/list-tabs'\nimport { DataTable } from '../components/table/table-block'\nimport { Badge } from '../components/ui/badge'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/ui/tabs'\nimport { WidgetGrid } from '../components/widgets/widgets-block'\nimport {\n useActionRunner,\n useAlfakit,\n useAlfakitProps,\n usePanel,\n useT,\n type AnyComponent,\n} from '../context'\nimport { BlankLayout } from '../layouts/blank-layout'\nimport { badgeColorClasses, colorClass } from '../lib/colors'\nimport { Icon } from '../lib/icons'\nimport { cn } from '../lib/utils'\n\n/**\n * `Alfakit/Page`: renders any schema-driven page. Custom pages (`Page::$component`) are\n * resolved from the `pages` map passed to `createAlfakit()`.\n */\nexport function AlfakitPage() {\n const props = useAlfakitProps()\n const panel = usePanel()\n const t = useT()\n const { pages } = useAlfakit()\n // Lazy widgets and relation managers arrive in a deferred prop after the first response.\n const page = useMemo(\n () => (props.page ? resolveLazyComponents(props.page, props.alfakitLazy) : undefined),\n [props.page, props.alfakitLazy],\n )\n\n useDefaultAction(page)\n\n if (!page) {\n return null\n }\n\n // Starter kit mode: the host's `title` callback adds the application name.\n const title = panel.starterKit ? page.title : `${page.title} - ${panel.brandName}`\n\n if (page.view) {\n const Custom = pages[page.view.component]\n\n if (!Custom) {\n return (\n <div className=\"text-destructive p-6\">\n {t(\n 'page_not_registered',\n { component: page.view.component },\n `Page component ${page.view.component} is not registered in createAlfakit({ pages }).`,\n )}\n </div>\n )\n }\n\n return (\n <PageActionProvider value={{ token: page.token, component: 'page' }}>\n <Head title={title} />\n {/* The component brings its own PageShell (as in panel mode, where it is the Inertia\n page itself) and takes the live props, so `reloadProps()` reaches it. */}\n <Custom\n {...customPageProps(page.view.props, props as Record<string, unknown>)}\n page={page}\n />\n </PageActionProvider>\n )\n }\n\n return (\n <PageActionProvider value={{ token: page.token, component: 'page' }}>\n <Head title={title} />\n <PageShell page={page}>\n <PageContent page={page} />\n </PageShell>\n </PageActionProvider>\n )\n}\n\n/**\n * Opens the page's default action (`$defaultAction`, `?tableAction=`) once the page has\n * hydrated, and once per page: re-renders after the action ran don't open it again.\n */\nexport function useDefaultAction(page: PageSchema | undefined) {\n const runner = useActionRunner()\n const opener = useRef<DefaultActionOpener>({ opened: null })\n\n useEffect(() => {\n openDefaultAction(page, opener.current, (action, context) => runner.trigger(action, context))\n }, [page, runner])\n}\n\n/** Sets the page's `$extraBodyAttributes` on `<body>` while it is open. */\nexport function useBodyAttributes(attributes: Record<string, string> | undefined) {\n const key = attributes ? JSON.stringify(attributes) : ''\n\n useEffect(\n () => applyBodyAttributes(key ? (JSON.parse(key) as Record<string, string>) : undefined),\n [key],\n )\n}\n\n/**\n * The registered layout: `createAlfakit()` registers the panel's (`panelLayouts`), the starter\n * kit its content layout. Without one the page renders bare: importing the panel layouts here\n * would put the sidebar and top bar in every starter kit page.\n */\nfunction layout(registry: { resolve(key: string): AnyComponent | undefined }, key: string) {\n return registry.resolve(key) ?? BlankLayout\n}\n\nexport function PageShell({ page, children }: { page: PageSchema; children: ReactNode }) {\n const { registry } = useAlfakit()\n\n useBodyAttributes(page.extraBodyAttributes)\n\n // Each layout can be replaced: createAlfakit({ components: { 'layout:app': MyLayout } }).\n if (page.layout === 'auth') {\n return createElement(\n layout(registry, 'layout:auth'),\n { heading: page.heading ?? page.title, subheading: page.subheading, page },\n children,\n )\n }\n\n if (page.layout === 'blank') {\n return createElement(layout(registry, 'layout:blank'), { page }, children)\n }\n\n if (page.layout === 'fullscreen') {\n return createElement(layout(registry, 'layout:fullscreen'), { page }, children)\n }\n\n return createElement(\n layout(registry, 'layout:app'),\n { breadcrumbs: page.breadcrumbs, maxContentWidth: page.maxContentWidth, page },\n <>\n {/* `?` overlay, `/`, `g d` and panel command shortcuts (`keyboardShortcuts()`). */}\n <KeyboardShortcuts />\n <Slot name=\"page.start\" />\n <PageHeader page={page} />\n {/* Edit pages: somebody else saved the record (`detectConflicts()`, `Panel::realtime()`). */}\n {page.conflicts &&\n createElement(registry.resolve('page:conflict-banner') ?? ConflictBanner, { page })}\n {page.subNavigation ? (\n <SubNavigationLayout navigation={page.subNavigation}>{children}</SubNavigationLayout>\n ) : (\n children\n )}\n <Slot name=\"page.end\" />\n </>,\n )\n}\n\nexport function PageHeader({ page }: { page: PageSchema }) {\n const { registry } = useAlfakit()\n const actions = page.headerActions ?? []\n // `$headerActionsAlignment`: the default (end) sits beside the heading; the others\n // stack the actions under it.\n const alignment = page.headerActionsAlignment\n\n return (\n <>\n <Slot name=\"page.header.before\" />\n <header\n data-slot=\"page-header\"\n data-actions-alignment={alignment}\n className={cn(\n 'flex flex-col gap-4',\n !alignment && 'sm:flex-row sm:items-start sm:justify-between',\n )}\n >\n <div className=\"min-w-0\">\n <Slot name=\"page.heading.before\" />\n <h1 className=\"text-2xl font-semibold tracking-tight\">{page.heading ?? page.title}</h1>\n {page.subheading && (\n <p className=\"text-muted-foreground mt-1 text-sm\">{page.subheading}</p>\n )}\n <Slot name=\"page.heading.after\" />\n </div>\n <div\n className={cn(\n 'flex shrink-0 flex-wrap items-center gap-2',\n alignment === 'start'\n ? 'justify-start'\n : alignment === 'center'\n ? 'justify-center'\n : alignment === 'between' || alignment === 'justify'\n ? 'justify-between'\n : 'justify-end',\n )}\n >\n {/* Record pages with `Panel::realtime()`: who else is on the record. */}\n {page.presence &&\n createElement(registry.resolve('page:presence') ?? RecordPresence, {\n presence: page.presence,\n })}\n <Slot name=\"page.actions.before\" />\n {actions.length > 0 && (\n <ActionList\n actions={actions}\n context={{ token: page.token, component: 'page' }}\n align=\"end\"\n className=\"max-w-full shrink-0\"\n />\n )}\n <Slot name=\"page.actions.after\" />\n </div>\n </header>\n <Slot name=\"page.header.after\" />\n </>\n )\n}\n\nexport function PageContent({ page }: { page: PageSchema }) {\n return (\n <div className=\"flex flex-col gap-6\">\n {page.content.map((block) => (\n <ContentBlockRenderer key={block.key} block={block} />\n ))}\n </div>\n )\n}\n\nexport function ContentBlockRenderer({ block }: { block: ContentBlock }) {\n const { registry } = useAlfakit()\n // Links list tabs to the table they control.\n const tabsIdBase = `alfakit-list-tabs-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`\n\n switch (block.type) {\n case 'Form':\n return <FormBlock block={block as FormBlockSchema} />\n case 'Infolist':\n return (\n <div data-slot=\"infolist\" className=\"contents\">\n <SchemaRenderer\n components={(block as InfolistBlock).components}\n columns={{ default: 1, lg: 2 }}\n />\n </div>\n )\n case 'Schema':\n return (\n <SchemaRenderer components={(block as SchemaBlock).components} columns={{ default: 1 }} />\n )\n case 'Table': {\n const table = block as TableBlockSchema\n const content = table.tabs?.length ? (\n <div className=\"flex flex-col gap-4\">\n <ListTabs\n tabs={table.tabs}\n activeTab={table.activeTab}\n tabsQueryKey={table.tabsQueryKey}\n label={table.pluralModelLabel}\n idBase={tabsIdBase}\n />\n <ListTabsPanel idBase={tabsIdBase} activeTab={table.activeTab}>\n <DataTable table={table} component={table.component} />\n </ListTabsPanel>\n </div>\n ) : (\n <DataTable table={table} component={table.component} />\n )\n\n if (block.key !== 'table') {\n return content\n }\n\n // The page's main table: the server sends these slots on List / ManageRelatedRecords pages only.\n return (\n <>\n <Slot name=\"resource.list-records.table.before\" />\n <Slot name=\"resource.manage-related-records.table.before\" />\n {content}\n <Slot name=\"resource.manage-related-records.table.after\" />\n <Slot name=\"resource.list-records.table.after\" />\n </>\n )\n }\n case 'RelationManagers':\n return <RelationManagers block={block as RelationManagersBlock} />\n case 'Widgets':\n return block.key === 'headerWidgets' ? (\n <>\n <Slot name=\"page.header-widgets.before\" />\n <WidgetGrid block={block as WidgetsBlockSchema} />\n <Slot name=\"page.header-widgets.after\" />\n </>\n ) : block.key === 'footerWidgets' ? (\n <>\n <Slot name=\"page.footer-widgets.before\" />\n <WidgetGrid block={block as WidgetsBlockSchema} />\n <Slot name=\"page.footer-widgets.after\" />\n </>\n ) : (\n <WidgetGrid block={block as WidgetsBlockSchema} />\n )\n case 'Links':\n return (\n <div className=\"flex flex-col items-center gap-1 text-center text-sm\">\n {(block as LinksBlock).links.map((link) => (\n <Link\n key={link.url}\n href={link.url}\n className=\"text-primary underline-offset-4 hover:underline\"\n >\n {link.label}\n </Link>\n ))}\n </div>\n )\n default: {\n const Custom = registry.resolve(block.type)\n\n return Custom ? createElement(Custom, { block }) : null\n }\n }\n}\n\nfunction RelationManagers({ block }: { block: RelationManagersBlock }) {\n const tabs = useMemo(() => relationManagerTabs(block), [block])\n // `?relation=`: a key in `getRelations()` or a position. The page URL (not\n // `window.location`) so the server renders the same tab as the browser.\n const url = usePage().url\n const [active, setActive] = useState(\n () =>\n relationTabFromQuery(\n tabs,\n new URL(url, 'http://localhost').searchParams.get(RELATION_QUERY_KEY),\n )?.key ??\n tabs[0]?.key ??\n '',\n )\n\n const changeTab = (key: string) => {\n setActive(key)\n\n if (typeof window === 'undefined') return\n\n const next = new URL(window.location.href)\n const slug = relationTabSlug(tabs, key)\n\n if (slug === null) next.searchParams.delete(RELATION_QUERY_KEY)\n else next.searchParams.set(RELATION_QUERY_KEY, slug)\n\n window.history.replaceState(window.history.state, '', next)\n }\n\n if (block.managers.length === 0) {\n return null\n }\n\n if (!hasRelationManagerTabs(block)) {\n const manager = block.managers[0]!\n\n return (\n <section className=\"flex flex-col gap-3\">\n <Slot name=\"resource.relation-manager.before\" scope={manager.key} />\n {isLazyPlaceholder(manager) ? (\n <LazyPlaceholder variant=\"table\" />\n ) : (\n <DataTable\n table={{ ...manager.table, heading: manager.table.heading ?? manager.title }}\n component={manager.component}\n />\n )}\n <Slot name=\"resource.relation-manager.after\" scope={manager.key} />\n </section>\n )\n }\n\n return (\n <Tabs value={active} onValueChange={changeTab}>\n <TabsList>\n <Slot name=\"resource.tabs.start\" />\n {tabs.map((tab) => (\n <TabsTrigger key={tab.key} value={tab.key}>\n {tab.icon && <Icon name={tab.icon} />}\n {tab.title}\n {tab.badge !== undefined && tab.badge !== null && tab.badge !== '' && (\n <Badge\n variant=\"secondary\"\n title={tab.badgeTooltip}\n className={cn(\n 'ms-1 px-1.5 py-0',\n tab.badgeColor && colorClass(badgeColorClasses, tab.badgeColor, 'gray'),\n )}\n >\n {tab.badge}\n {tab.badgeTooltip && <span className=\"sr-only\">{` (${tab.badgeTooltip})`}</span>}\n </Badge>\n )}\n </TabsTrigger>\n ))}\n <Slot name=\"resource.tabs.end\" />\n </TabsList>\n {tabs.map((tab) => (\n <TabsContent\n key={tab.key}\n value={tab.key}\n className=\"flex flex-col gap-6 pt-2 data-[state=inactive]:hidden\"\n data-slot={tab.group ? 'relation-group' : tab.content ? 'relation-content' : undefined}\n // The form keeps its unsaved state while another tab is open.\n forceMount={tab.content ? true : undefined}\n >\n {/* The page's form / infolist (`hasCombinedRelationManagerTabsWithContent()`). */}\n {tab.content && <ContentBlockRenderer block={tab.content as ContentBlock} />}\n {tab.managers.map((manager) => (\n <Fragment key={manager.key}>\n <Slot name=\"resource.relation-manager.before\" scope={manager.key} />\n {isLazyPlaceholder(manager) ? (\n <LazyPlaceholder variant=\"table\" />\n ) : (\n <DataTable\n // Inside a group each table keeps its own heading; a lone manager's is the tab.\n table={{\n ...manager.table,\n heading: tab.group ? (manager.table.heading ?? manager.title) : undefined,\n }}\n component={manager.component}\n />\n )}\n <Slot name=\"resource.relation-manager.after\" scope={manager.key} />\n </Fragment>\n ))}\n </TabsContent>\n ))}\n </Tabs>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"page.js","names":["FormBlock"],"sources":["../../src/pages/page.tsx"],"sourcesContent":["import type {\n ContentBlock,\n FormBlock as FormBlockSchema,\n InfolistBlock,\n LinksBlock,\n PageSchema,\n RelationManagersBlock,\n SchemaBlock,\n TableBlock as TableBlockSchema,\n WidgetsBlock as WidgetsBlockSchema,\n} from '@alfakit/core'\nimport {\n applyBodyAttributes,\n customPageProps,\n hasRelationManagerTabs,\n isLazyPlaceholder,\n openDefaultAction,\n RELATION_QUERY_KEY,\n relationManagerTabs,\n relationTabFromQuery,\n relationTabSlug,\n resolveLazyComponents,\n type DefaultActionOpener,\n} from '@alfakit/core'\nimport { Head, Link, usePage } from '@inertiajs/react'\nimport {\n createElement,\n Fragment,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { PageActionProvider } from '../components/actions/action-context'\nimport { ActionList } from '../components/actions/action-list'\nimport { FormBlock } from '../components/form/form-block'\nimport { KeyboardShortcuts } from '../components/panel/keyboard-shortcuts'\nimport { LazyPlaceholder } from '../components/panel/lazy-placeholder'\nimport { Slot } from '../components/panel/slot'\nimport { SubNavigationLayout } from '../components/panel/sub-navigation'\nimport { ConflictBanner } from '../components/realtime/conflict-banner'\nimport { RecordPresence } from '../components/realtime/record-presence'\nimport { SchemaRenderer } from '../components/schema/schema-renderer'\nimport { ListTabs, ListTabsPanel } from '../components/table/list-tabs'\nimport { DataTable } from '../components/table/table-block'\nimport { Badge } from '../components/ui/badge'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/ui/tabs'\nimport { WidgetGrid } from '../components/widgets/widgets-block'\nimport {\n useActionRunner,\n useAlfakit,\n useAlfakitProps,\n usePanel,\n useT,\n type AnyComponent,\n} from '../context'\nimport { BlankLayout } from '../layouts/blank-layout'\nimport { badgeColorClasses, colorClass } from '../lib/colors'\nimport { Icon } from '../lib/icons'\nimport { cn } from '../lib/utils'\n\n/**\n * `Alfakit/Page`: renders any schema-driven page. Custom pages (`Page::$component`) are\n * resolved from the `pages` map passed to `createAlfakit()`.\n */\nexport function AlfakitPage() {\n const props = useAlfakitProps()\n const panel = usePanel()\n const t = useT()\n const { pages } = useAlfakit()\n // Lazy widgets and relation managers arrive in a deferred prop after the first response.\n const page = useMemo(\n () => (props.page ? resolveLazyComponents(props.page, props.alfakitLazy) : undefined),\n [props.page, props.alfakitLazy],\n )\n\n useDefaultAction(page)\n\n if (!page) {\n return null\n }\n\n // Starter kit mode: the host's `title` callback adds the application name.\n const title = panel.starterKit ? page.title : `${page.title} - ${panel.brandName}`\n\n if (page.view) {\n const Custom = pages[page.view.component]\n\n if (!Custom) {\n return (\n <div className=\"text-destructive p-6\">\n {t(\n 'page_not_registered',\n { component: page.view.component },\n `Page component ${page.view.component} is not registered in createAlfakit({ pages }).`,\n )}\n </div>\n )\n }\n\n return (\n <PageActionProvider value={{ token: page.token, component: 'page' }}>\n <Head title={title} />\n {/* The component brings its own PageShell (as in panel mode, where it is the Inertia\n page itself) and takes the live props, so `reloadProps()` reaches it. */}\n <Custom\n {...customPageProps(page.view.props, props as Record<string, unknown>)}\n page={page}\n />\n </PageActionProvider>\n )\n }\n\n return (\n <PageActionProvider value={{ token: page.token, component: 'page' }}>\n <Head title={title} />\n <PageShell page={page}>\n <PageContent page={page} />\n </PageShell>\n </PageActionProvider>\n )\n}\n\n/**\n * Opens the page's default action (`$defaultAction`, `?tableAction=`) once the page has\n * hydrated, and once per page: re-renders after the action ran don't open it again.\n */\nexport function useDefaultAction(page: PageSchema | undefined) {\n const runner = useActionRunner()\n const opener = useRef<DefaultActionOpener>({ opened: null })\n\n useEffect(() => {\n openDefaultAction(page, opener.current, (action, context) => runner.trigger(action, context))\n }, [page, runner])\n}\n\n/** Sets the page's `$extraBodyAttributes` on `<body>` while it is open. */\nexport function useBodyAttributes(attributes: Record<string, string> | undefined) {\n const key = attributes ? JSON.stringify(attributes) : ''\n\n useEffect(\n () => applyBodyAttributes(key ? (JSON.parse(key) as Record<string, string>) : undefined),\n [key],\n )\n}\n\n/**\n * The registered layout: `createAlfakit()` registers the panel's (`panelLayouts`), the starter\n * kit its content layout. Without one the page renders bare: importing the panel layouts here\n * would put the sidebar and top bar in every starter kit page.\n */\nfunction layout(registry: { resolve(key: string): AnyComponent | undefined }, key: string) {\n return registry.resolve(key) ?? BlankLayout\n}\n\nexport function PageShell({ page, children }: { page: PageSchema; children: ReactNode }) {\n const { registry } = useAlfakit()\n\n useBodyAttributes(page.extraBodyAttributes)\n\n // Each layout can be replaced: createAlfakit({ components: { 'layout:app': MyLayout } }).\n if (page.layout === 'auth') {\n return createElement(\n layout(registry, 'layout:auth'),\n { heading: page.heading ?? page.title, subheading: page.subheading, page },\n children,\n )\n }\n\n if (page.layout === 'blank') {\n return createElement(layout(registry, 'layout:blank'), { page }, children)\n }\n\n if (page.layout === 'fullscreen') {\n return createElement(layout(registry, 'layout:fullscreen'), { page }, children)\n }\n\n return createElement(\n layout(registry, 'layout:app'),\n { breadcrumbs: page.breadcrumbs, maxContentWidth: page.maxContentWidth, page },\n <>\n {/* `?` overlay, `/`, `g d` and panel command shortcuts (`keyboardShortcuts()`). */}\n <KeyboardShortcuts />\n <Slot name=\"page.start\" />\n <PageHeader page={page} />\n {/* Edit pages: somebody else saved the record (`detectConflicts()`, `Panel::realtime()`). */}\n {page.conflicts &&\n createElement(registry.resolve('page:conflict-banner') ?? ConflictBanner, { page })}\n {page.subNavigation ? (\n <SubNavigationLayout navigation={page.subNavigation}>{children}</SubNavigationLayout>\n ) : (\n children\n )}\n <Slot name=\"page.end\" />\n </>,\n )\n}\n\nexport function PageHeader({ page }: { page: PageSchema }) {\n const { registry } = useAlfakit()\n const actions = page.headerActions ?? []\n // `$headerActionsAlignment`: the default (end) sits beside the heading; the others\n // stack the actions under it.\n const alignment = page.headerActionsAlignment\n\n return (\n <>\n <Slot name=\"page.header.before\" />\n <header\n data-slot=\"page-header\"\n data-actions-alignment={alignment}\n className={cn(\n 'flex flex-col gap-4',\n !alignment && 'sm:flex-row sm:items-start sm:justify-between',\n )}\n >\n <div className=\"min-w-0\">\n <Slot name=\"page.heading.before\" />\n <h1 className=\"text-2xl font-semibold tracking-tight\">{page.heading ?? page.title}</h1>\n {page.subheading && (\n <p className=\"text-muted-foreground mt-1 text-sm\">{page.subheading}</p>\n )}\n <Slot name=\"page.heading.after\" />\n </div>\n <div\n className={cn(\n 'flex shrink-0 flex-wrap items-center gap-2',\n alignment === 'start'\n ? 'justify-start'\n : alignment === 'center'\n ? 'justify-center'\n : alignment === 'between' || alignment === 'justify'\n ? 'justify-between'\n : 'justify-end',\n )}\n >\n {/* Record pages with `Panel::realtime()`: who else is on the record. */}\n {page.presence &&\n createElement(registry.resolve('page:presence') ?? RecordPresence, {\n presence: page.presence,\n })}\n <Slot name=\"page.actions.before\" />\n {actions.length > 0 && (\n <ActionList\n actions={actions}\n context={{ token: page.token, component: 'page' }}\n align=\"end\"\n className=\"max-w-full shrink-0\"\n />\n )}\n <Slot name=\"page.actions.after\" />\n </div>\n </header>\n <Slot name=\"page.header.after\" />\n </>\n )\n}\n\nexport function PageContent({ page }: { page: PageSchema }) {\n return (\n <div className=\"flex flex-col gap-6\">\n {page.content.map((block) => (\n <ContentBlockRenderer key={block.key} block={block} />\n ))}\n </div>\n )\n}\n\nexport function ContentBlockRenderer({ block }: { block: ContentBlock }) {\n const { registry } = useAlfakit()\n // Links list tabs to the table they control.\n const tabsIdBase = `alfakit-list-tabs-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`\n\n switch (block.type) {\n case 'Form':\n return <FormBlock block={block as FormBlockSchema} />\n case 'Infolist':\n return (\n <div data-slot=\"infolist\" className=\"contents\">\n <SchemaRenderer\n components={(block as InfolistBlock).components}\n columns={(block as InfolistBlock).columns ?? { default: 1, lg: 2 }}\n />\n </div>\n )\n case 'Schema':\n return (\n <SchemaRenderer components={(block as SchemaBlock).components} columns={{ default: 1 }} />\n )\n case 'Table': {\n const table = block as TableBlockSchema\n const content = table.tabs?.length ? (\n <div className=\"flex flex-col gap-4\">\n <ListTabs\n tabs={table.tabs}\n activeTab={table.activeTab}\n tabsQueryKey={table.tabsQueryKey}\n label={table.pluralModelLabel}\n idBase={tabsIdBase}\n />\n <ListTabsPanel idBase={tabsIdBase} activeTab={table.activeTab}>\n <DataTable table={table} component={table.component} />\n </ListTabsPanel>\n </div>\n ) : (\n <DataTable table={table} component={table.component} />\n )\n\n if (block.key !== 'table') {\n return content\n }\n\n // The page's main table: the server sends these slots on List / ManageRelatedRecords pages only.\n return (\n <>\n <Slot name=\"resource.list-records.table.before\" />\n <Slot name=\"resource.manage-related-records.table.before\" />\n {content}\n <Slot name=\"resource.manage-related-records.table.after\" />\n <Slot name=\"resource.list-records.table.after\" />\n </>\n )\n }\n case 'RelationManagers':\n return <RelationManagers block={block as RelationManagersBlock} />\n case 'Widgets':\n return block.key === 'headerWidgets' ? (\n <>\n <Slot name=\"page.header-widgets.before\" />\n <WidgetGrid block={block as WidgetsBlockSchema} />\n <Slot name=\"page.header-widgets.after\" />\n </>\n ) : block.key === 'footerWidgets' ? (\n <>\n <Slot name=\"page.footer-widgets.before\" />\n <WidgetGrid block={block as WidgetsBlockSchema} />\n <Slot name=\"page.footer-widgets.after\" />\n </>\n ) : (\n <WidgetGrid block={block as WidgetsBlockSchema} />\n )\n case 'Links':\n return (\n <div className=\"flex flex-col items-center gap-1 text-center text-sm\">\n {(block as LinksBlock).links.map((link) => (\n <Link\n key={link.url}\n href={link.url}\n className=\"text-primary underline-offset-4 hover:underline\"\n >\n {link.label}\n </Link>\n ))}\n </div>\n )\n default: {\n const Custom = registry.resolve(block.type)\n\n return Custom ? createElement(Custom, { block }) : null\n }\n }\n}\n\nfunction RelationManagers({ block }: { block: RelationManagersBlock }) {\n const tabs = useMemo(() => relationManagerTabs(block), [block])\n // `?relation=`: a key in `getRelations()` or a position. The page URL (not\n // `window.location`) so the server renders the same tab as the browser.\n const url = usePage().url\n const [active, setActive] = useState(\n () =>\n relationTabFromQuery(\n tabs,\n new URL(url, 'http://localhost').searchParams.get(RELATION_QUERY_KEY),\n )?.key ??\n tabs[0]?.key ??\n '',\n )\n\n const changeTab = (key: string) => {\n setActive(key)\n\n if (typeof window === 'undefined') return\n\n const next = new URL(window.location.href)\n const slug = relationTabSlug(tabs, key)\n\n if (slug === null) next.searchParams.delete(RELATION_QUERY_KEY)\n else next.searchParams.set(RELATION_QUERY_KEY, slug)\n\n window.history.replaceState(window.history.state, '', next)\n }\n\n if (block.managers.length === 0) {\n return null\n }\n\n if (!hasRelationManagerTabs(block)) {\n const manager = block.managers[0]!\n\n return (\n <section className=\"flex flex-col gap-3\">\n <Slot name=\"resource.relation-manager.before\" scope={manager.key} />\n {isLazyPlaceholder(manager) ? (\n <LazyPlaceholder variant=\"table\" />\n ) : (\n <DataTable\n table={{ ...manager.table, heading: manager.table.heading ?? manager.title }}\n component={manager.component}\n />\n )}\n <Slot name=\"resource.relation-manager.after\" scope={manager.key} />\n </section>\n )\n }\n\n return (\n <Tabs value={active} onValueChange={changeTab}>\n <TabsList>\n <Slot name=\"resource.tabs.start\" />\n {tabs.map((tab) => (\n <TabsTrigger key={tab.key} value={tab.key}>\n {tab.icon && <Icon name={tab.icon} />}\n {tab.title}\n {tab.badge !== undefined && tab.badge !== null && tab.badge !== '' && (\n <Badge\n variant=\"secondary\"\n title={tab.badgeTooltip}\n className={cn(\n 'ms-1 px-1.5 py-0',\n tab.badgeColor && colorClass(badgeColorClasses, tab.badgeColor, 'gray'),\n )}\n >\n {tab.badge}\n {tab.badgeTooltip && <span className=\"sr-only\">{` (${tab.badgeTooltip})`}</span>}\n </Badge>\n )}\n </TabsTrigger>\n ))}\n <Slot name=\"resource.tabs.end\" />\n </TabsList>\n {tabs.map((tab) => (\n <TabsContent\n key={tab.key}\n value={tab.key}\n className=\"flex flex-col gap-6 pt-2 data-[state=inactive]:hidden\"\n data-slot={tab.group ? 'relation-group' : tab.content ? 'relation-content' : undefined}\n // The form keeps its unsaved state while another tab is open.\n forceMount={tab.content ? true : undefined}\n >\n {/* The page's form / infolist (`hasCombinedRelationManagerTabsWithContent()`). */}\n {tab.content && <ContentBlockRenderer block={tab.content as ContentBlock} />}\n {tab.managers.map((manager) => (\n <Fragment key={manager.key}>\n <Slot name=\"resource.relation-manager.before\" scope={manager.key} />\n {isLazyPlaceholder(manager) ? (\n <LazyPlaceholder variant=\"table\" />\n ) : (\n <DataTable\n // Inside a group each table keeps its own heading; a lone manager's is the tab.\n table={{\n ...manager.table,\n heading: tab.group ? (manager.table.heading ?? manager.title) : undefined,\n }}\n component={manager.component}\n />\n )}\n <Slot name=\"resource.relation-manager.after\" scope={manager.key} />\n </Fragment>\n ))}\n </TabsContent>\n ))}\n </Tabs>\n )\n}\n"],"mappings":"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"}
|
|
@@ -111,7 +111,7 @@ function AlfakitComponent({ component, components, className, header, footer, ch
|
|
|
111
111
|
"data-slot": "page-header",
|
|
112
112
|
className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
|
|
113
113
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
114
|
-
className: "min-w-0",
|
|
114
|
+
className: "min-w-0 sm:max-w-[50%] sm:shrink-0",
|
|
115
115
|
children: [page.heading && /* @__PURE__ */ jsx("h2", {
|
|
116
116
|
className: "text-xl font-semibold tracking-tight",
|
|
117
117
|
children: page.heading
|
|
@@ -123,7 +123,7 @@ function AlfakitComponent({ component, components, className, header, footer, ch
|
|
|
123
123
|
actions: page.headerActions,
|
|
124
124
|
context: actionContext,
|
|
125
125
|
align: "end",
|
|
126
|
-
className: "max-w-full
|
|
126
|
+
className: "max-w-full min-w-0"
|
|
127
127
|
})]
|
|
128
128
|
}),
|
|
129
129
|
header,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alfakit-component.js","names":[],"sources":["../../src/standalone/alfakit-component.tsx"],"sourcesContent":["import {\n StandaloneComponentState,\n findStandalonePropName,\n registerStandaloneProp,\n standalonePanelSchema,\n type ContentBlock,\n type StandaloneComponentSchema,\n} from '@alfakit/core'\nimport { usePage } from '@inertiajs/react'\nimport { Direction } from 'radix-ui'\nimport { useEffect, useLayoutEffect, useMemo, useState, type ReactNode } from 'react'\nimport { PageActionProvider } from '../components/actions/action-context'\nimport { ActionList } from '../components/actions/action-list'\nimport { ActionModals } from '../components/actions/action-modals'\nimport { TooltipProvider } from '../components/ui/tooltip'\nimport {\n AlfakitProvider,\n StandaloneProvider,\n useOptionalAlfakit,\n type AlfakitContextValue,\n type AnyComponent,\n} from '../context'\nimport { cn } from '../lib/utils'\nimport { ContentBlockRenderer } from '../pages/page'\nimport { AlfakitToaster } from './alfakit-toaster'\nimport {\n claimToaster,\n createStandaloneContext,\n createStandaloneRegistry,\n ensureStandaloneRuntime,\n hasToaster,\n} from './runtime'\n\nexport interface AlfakitComponentProps {\n /** The payload: `ContactForm::make()` passed as an Inertia prop. */\n component: StandaloneComponentSchema\n /** Renderer overrides for this instance (`{ TextInput: MyInput }`), on top of `configureAlfakit()`. */\n components?: Record<string, AnyComponent>\n className?: string\n /** Rendered above the content blocks (after the heading and actions). */\n header?: ReactNode\n /** Rendered below the content blocks. */\n footer?: ReactNode\n /** Render each content block yourself (e.g. to lay a form and a table side by side). */\n children?: (blocks: ContentBlock[], render: (block: ContentBlock) => ReactNode) => ReactNode\n}\n\n/**\n * Renders an Alfakit component outside a panel: a form, table, infolist, widgets or any mix\n * (`AlfaSix\\Alfakit\\Standalone\\*`) in any Inertia page of the application. Needs no\n * `createAlfakit()` and no panel layout: it provides its own translator, registry, action\n * runner and modals, and inherits the application's shadcn tokens.\n *\n * ```tsx\n * <AlfakitComponent component={orders} className=\"max-w-4xl\" />\n * ```\n */\n// `useLayoutEffect` warns during a server render, where nothing registers anyway.\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\nexport function AlfakitComponent({\n component,\n components,\n className,\n header,\n footer,\n children,\n}: AlfakitComponentProps) {\n const parent = useOptionalAlfakit()\n const props = useOptionalPageProps()\n const [, setVersion] = useState(0)\n // The registry overrides are an object literal in JSX: compare them by their keys.\n const overrideKeys = Object.keys(components ?? {}).join(',')\n\n // Lazy and polled schemas of this component, merged into the page it renders.\n const state = useMemo(\n () => new StandaloneComponentState(component, () => setVersion((value) => value + 1)),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n state.setComponent(component)\n\n const context = useMemo<AlfakitContextValue>(() => {\n const poll = (target: string, interval: string | number | null | undefined) =>\n state.poll(target, interval)\n const refresh = (targets: string[]) => state.refresh(targets)\n\n if (parent) {\n // Inside a panel page: the panel's registry and translator, but this component's own\n // action runner, so its actions post to its own endpoints with its own token (sharing\n // the panel's runner sent them to the panel's endpoint: 403).\n const own = createStandaloneContext(\n { action: component.endpoints.action, modal: component.endpoints.modal },\n components,\n poll,\n )\n\n return {\n ...parent,\n actions: own.actions,\n registry: createStandaloneRegistry(components, parent.registry),\n poll,\n refresh,\n }\n }\n\n return {\n ...createStandaloneContext(\n { action: component.endpoints.action, modal: component.endpoints.modal },\n components,\n poll,\n ),\n refresh,\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parent, state, overrideKeys])\n\n // Endpoints follow the latest payload (they change per locale or path).\n context.actions.setEndpoints({\n action: component.endpoints.action,\n modal: component.endpoints.modal,\n })\n\n // Inside `createAlfakit()` the panel feeds the shared translator; on a page without the\n // `alfakit` prop (the rest of the app) the component's own translations apply.\n const ownsTranslator = !parent || !props?.alfakit\n\n if (ownsTranslator) {\n context.translator.setTranslations(component.translations ?? {})\n context.translator.setLocale(component.localization?.tag ?? 'en')\n }\n\n const panel = useMemo(() => standalonePanelSchema(component), [component])\n const page = state.page\n const direction = component.localization?.direction ?? 'ltr'\n\n useEffect(() => {\n ensureStandaloneRuntime()\n }, [])\n\n // Partial reloads (sorting, paging, inline edits) request this component's own prop.\n const propName = findStandalonePropName(props, component)\n\n // A layout effect runs before the children's effects: a `deferLoading()` table's first\n // reload must already ask for this component's prop, not the panel `page` prop.\n useIsomorphicLayoutEffect(() => registerStandaloneProp(propName ?? null), [propName])\n\n useEffect(() => {\n void state.loadLazy(component)\n // The token identifies a new payload.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state, component.token])\n\n // Toasts: use the layout's <AlfakitToaster /> when there is one, else the first component\n // on the page renders one (checked after every component's effects ran).\n const [ownsToaster, setOwnsToaster] = useState(false)\n\n useEffect(() => {\n if (parent) return\n\n let release: (() => void) | null = null\n let cancelled = false\n\n queueMicrotask(() => {\n if (cancelled || hasToaster()) return\n\n release = claimToaster()\n setOwnsToaster(true)\n })\n\n return () => {\n cancelled = true\n release?.()\n }\n }, [parent])\n\n const render = (block: ContentBlock) => <ContentBlockRenderer key={block.key} block={block} />\n const actionContext = useMemo(\n () => ({ token: component.token, component: 'page' }),\n [component.token],\n )\n\n const body = (\n <PageActionProvider value={actionContext}>\n <div\n data-slot=\"standalone\"\n data-alfakit-component={component.class}\n dir={direction}\n className={cn('flex flex-col gap-6', className)}\n >\n {(page.heading || page.headerActions?.length) && (\n <header\n data-slot=\"page-header\"\n className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\"\n >\n <div className=\"min-w-0\">\n {page.heading && (\n <h2 className=\"text-xl font-semibold tracking-tight\">{page.heading}</h2>\n )}\n {page.subheading && (\n <p className=\"text-muted-foreground mt-1 text-sm\">{page.subheading}</p>\n )}\n </div>\n {page.headerActions && page.headerActions.length > 0 && (\n <ActionList\n actions={page.headerActions}\n context={actionContext}\n align=\"end\"\n className=\"max-w-full shrink-0\"\n />\n )}\n </header>\n )}\n {header}\n {children ? children(page.content, render) : page.content.map(render)}\n {footer}\n </div>\n <ActionModals />\n {ownsToaster && <AlfakitToaster claimed dir={direction} />}\n </PageActionProvider>\n )\n\n return (\n <AlfakitProvider value={context}>\n <StandaloneProvider value={{ panel, page }}>\n {parent ? (\n body\n ) : (\n <Direction.Provider dir={direction}>\n <TooltipProvider delayDuration={0}>{body}</TooltipProvider>\n </Direction.Provider>\n )}\n </StandaloneProvider>\n </AlfakitProvider>\n )\n}\n\n/**\n * The host page's Inertia props, or undefined when rendered outside an Inertia app (a\n * component test, Storybook, a plain server render): partial reloads then reload every prop.\n */\nfunction useOptionalPageProps(): Record<string, unknown> | undefined {\n try {\n return usePage().props as Record<string, unknown>\n } catch {\n return undefined\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alfakit-component.js","names":[],"sources":["../../src/standalone/alfakit-component.tsx"],"sourcesContent":["import {\n StandaloneComponentState,\n findStandalonePropName,\n registerStandaloneProp,\n standalonePanelSchema,\n type ContentBlock,\n type StandaloneComponentSchema,\n} from '@alfakit/core'\nimport { usePage } from '@inertiajs/react'\nimport { Direction } from 'radix-ui'\nimport { useEffect, useLayoutEffect, useMemo, useState, type ReactNode } from 'react'\nimport { PageActionProvider } from '../components/actions/action-context'\nimport { ActionList } from '../components/actions/action-list'\nimport { ActionModals } from '../components/actions/action-modals'\nimport { TooltipProvider } from '../components/ui/tooltip'\nimport {\n AlfakitProvider,\n StandaloneProvider,\n useOptionalAlfakit,\n type AlfakitContextValue,\n type AnyComponent,\n} from '../context'\nimport { cn } from '../lib/utils'\nimport { ContentBlockRenderer } from '../pages/page'\nimport { AlfakitToaster } from './alfakit-toaster'\nimport {\n claimToaster,\n createStandaloneContext,\n createStandaloneRegistry,\n ensureStandaloneRuntime,\n hasToaster,\n} from './runtime'\n\nexport interface AlfakitComponentProps {\n /** The payload: `ContactForm::make()` passed as an Inertia prop. */\n component: StandaloneComponentSchema\n /** Renderer overrides for this instance (`{ TextInput: MyInput }`), on top of `configureAlfakit()`. */\n components?: Record<string, AnyComponent>\n className?: string\n /** Rendered above the content blocks (after the heading and actions). */\n header?: ReactNode\n /** Rendered below the content blocks. */\n footer?: ReactNode\n /** Render each content block yourself (e.g. to lay a form and a table side by side). */\n children?: (blocks: ContentBlock[], render: (block: ContentBlock) => ReactNode) => ReactNode\n}\n\n/**\n * Renders an Alfakit component outside a panel: a form, table, infolist, widgets or any mix\n * (`AlfaSix\\Alfakit\\Standalone\\*`) in any Inertia page of the application. Needs no\n * `createAlfakit()` and no panel layout: it provides its own translator, registry, action\n * runner and modals, and inherits the application's shadcn tokens.\n *\n * ```tsx\n * <AlfakitComponent component={orders} className=\"max-w-4xl\" />\n * ```\n */\n// `useLayoutEffect` warns during a server render, where nothing registers anyway.\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\nexport function AlfakitComponent({\n component,\n components,\n className,\n header,\n footer,\n children,\n}: AlfakitComponentProps) {\n const parent = useOptionalAlfakit()\n const props = useOptionalPageProps()\n const [, setVersion] = useState(0)\n // The registry overrides are an object literal in JSX: compare them by their keys.\n const overrideKeys = Object.keys(components ?? {}).join(',')\n\n // Lazy and polled schemas of this component, merged into the page it renders.\n const state = useMemo(\n () => new StandaloneComponentState(component, () => setVersion((value) => value + 1)),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n state.setComponent(component)\n\n const context = useMemo<AlfakitContextValue>(() => {\n const poll = (target: string, interval: string | number | null | undefined) =>\n state.poll(target, interval)\n const refresh = (targets: string[]) => state.refresh(targets)\n\n if (parent) {\n // Inside a panel page: the panel's registry and translator, but this component's own\n // action runner, so its actions post to its own endpoints with its own token (sharing\n // the panel's runner sent them to the panel's endpoint: 403).\n const own = createStandaloneContext(\n { action: component.endpoints.action, modal: component.endpoints.modal },\n components,\n poll,\n )\n\n return {\n ...parent,\n actions: own.actions,\n registry: createStandaloneRegistry(components, parent.registry),\n poll,\n refresh,\n }\n }\n\n return {\n ...createStandaloneContext(\n { action: component.endpoints.action, modal: component.endpoints.modal },\n components,\n poll,\n ),\n refresh,\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parent, state, overrideKeys])\n\n // Endpoints follow the latest payload (they change per locale or path).\n context.actions.setEndpoints({\n action: component.endpoints.action,\n modal: component.endpoints.modal,\n })\n\n // Inside `createAlfakit()` the panel feeds the shared translator; on a page without the\n // `alfakit` prop (the rest of the app) the component's own translations apply.\n const ownsTranslator = !parent || !props?.alfakit\n\n if (ownsTranslator) {\n context.translator.setTranslations(component.translations ?? {})\n context.translator.setLocale(component.localization?.tag ?? 'en')\n }\n\n const panel = useMemo(() => standalonePanelSchema(component), [component])\n const page = state.page\n const direction = component.localization?.direction ?? 'ltr'\n\n useEffect(() => {\n ensureStandaloneRuntime()\n }, [])\n\n // Partial reloads (sorting, paging, inline edits) request this component's own prop.\n const propName = findStandalonePropName(props, component)\n\n // A layout effect runs before the children's effects: a `deferLoading()` table's first\n // reload must already ask for this component's prop, not the panel `page` prop.\n useIsomorphicLayoutEffect(() => registerStandaloneProp(propName ?? null), [propName])\n\n useEffect(() => {\n void state.loadLazy(component)\n // The token identifies a new payload.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state, component.token])\n\n // Toasts: use the layout's <AlfakitToaster /> when there is one, else the first component\n // on the page renders one (checked after every component's effects ran).\n const [ownsToaster, setOwnsToaster] = useState(false)\n\n useEffect(() => {\n if (parent) return\n\n let release: (() => void) | null = null\n let cancelled = false\n\n queueMicrotask(() => {\n if (cancelled || hasToaster()) return\n\n release = claimToaster()\n setOwnsToaster(true)\n })\n\n return () => {\n cancelled = true\n release?.()\n }\n }, [parent])\n\n const render = (block: ContentBlock) => <ContentBlockRenderer key={block.key} block={block} />\n const actionContext = useMemo(\n () => ({ token: component.token, component: 'page' }),\n [component.token],\n )\n\n const body = (\n <PageActionProvider value={actionContext}>\n <div\n data-slot=\"standalone\"\n data-alfakit-component={component.class}\n dir={direction}\n className={cn('flex flex-col gap-6', className)}\n >\n {(page.heading || page.headerActions?.length) && (\n <header\n data-slot=\"page-header\"\n className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\"\n >\n <div className=\"min-w-0 sm:max-w-[50%] sm:shrink-0\">\n {page.heading && (\n <h2 className=\"text-xl font-semibold tracking-tight\">{page.heading}</h2>\n )}\n {page.subheading && (\n <p className=\"text-muted-foreground mt-1 text-sm\">{page.subheading}</p>\n )}\n </div>\n {page.headerActions && page.headerActions.length > 0 && (\n <ActionList\n actions={page.headerActions}\n context={actionContext}\n align=\"end\"\n className=\"max-w-full min-w-0\"\n />\n )}\n </header>\n )}\n {header}\n {children ? children(page.content, render) : page.content.map(render)}\n {footer}\n </div>\n <ActionModals />\n {ownsToaster && <AlfakitToaster claimed dir={direction} />}\n </PageActionProvider>\n )\n\n return (\n <AlfakitProvider value={context}>\n <StandaloneProvider value={{ panel, page }}>\n {parent ? (\n body\n ) : (\n <Direction.Provider dir={direction}>\n <TooltipProvider delayDuration={0}>{body}</TooltipProvider>\n </Direction.Provider>\n )}\n </StandaloneProvider>\n </AlfakitProvider>\n )\n}\n\n/**\n * The host page's Inertia props, or undefined when rendered outside an Inertia app (a\n * component test, Storybook, a plain server render): partial reloads then reload every prop.\n */\nfunction useOptionalPageProps(): Record<string, unknown> | undefined {\n try {\n return usePage().props as Record<string, unknown>\n } catch {\n return undefined\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,MAAM,4BAA4B,OAAO,WAAW,cAAc,YAAY;AAE9E,SAAgB,iBAAiB,EAC/B,WACA,YACA,WACA,QACA,QACA,YACwB;CACxB,MAAM,SAAS,mBAAmB;CAClC,MAAM,QAAQ,qBAAqB;CACnC,MAAM,GAAG,cAAc,SAAS,CAAC;CAEjC,MAAM,eAAe,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;CAG3D,MAAM,QAAQ,cACN,IAAI,yBAAyB,iBAAiB,YAAY,UAAU,QAAQ,CAAC,CAAC,GAEpF,CAAC,CACH;CACA,MAAM,aAAa,SAAS;CAE5B,MAAM,UAAU,cAAmC;EACjD,MAAM,QAAQ,QAAgB,aAC5B,MAAM,KAAK,QAAQ,QAAQ;EAC7B,MAAM,WAAW,YAAsB,MAAM,QAAQ,OAAO;EAE5D,IAAI,QAAQ;GAIV,MAAM,MAAM,wBACV;IAAE,QAAQ,UAAU,UAAU;IAAQ,OAAO,UAAU,UAAU;GAAM,GACvE,YACA,IACF;GAEA,OAAO;IACL,GAAG;IACH,SAAS,IAAI;IACb,UAAU,yBAAyB,YAAY,OAAO,QAAQ;IAC9D;IACA;GACF;EACF;EAEA,OAAO;GACL,GAAG,wBACD;IAAE,QAAQ,UAAU,UAAU;IAAQ,OAAO,UAAU,UAAU;GAAM,GACvE,YACA,IACF;GACA;EACF;CAEF,GAAG;EAAC;EAAQ;EAAO;CAAY,CAAC;CAGhC,QAAQ,QAAQ,aAAa;EAC3B,QAAQ,UAAU,UAAU;EAC5B,OAAO,UAAU,UAAU;CAC7B,CAAC;CAMD,IAFuB,CAAC,UAAU,CAAC,OAAO,SAEtB;EAClB,QAAQ,WAAW,gBAAgB,UAAU,gBAAgB,CAAC,CAAC;EAC/D,QAAQ,WAAW,UAAU,UAAU,cAAc,OAAO,IAAI;CAClE;CAEA,MAAM,QAAQ,cAAc,sBAAsB,SAAS,GAAG,CAAC,SAAS,CAAC;CACzE,MAAM,OAAO,MAAM;CACnB,MAAM,YAAY,UAAU,cAAc,aAAa;CAEvD,gBAAgB;EACd,wBAAwB;CAC1B,GAAG,CAAC,CAAC;CAGL,MAAM,WAAW,uBAAuB,OAAO,SAAS;CAIxD,gCAAgC,uBAAuB,YAAY,IAAI,GAAG,CAAC,QAAQ,CAAC;CAEpF,gBAAgB;EACd,MAAW,SAAS,SAAS;CAG/B,GAAG,CAAC,OAAO,UAAU,KAAK,CAAC;CAI3B,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CAEpD,gBAAgB;EACd,IAAI,QAAQ;EAEZ,IAAI,UAA+B;EACnC,IAAI,YAAY;EAEhB,qBAAqB;GACnB,IAAI,aAAa,WAAW,GAAG;GAE/B,UAAU,aAAa;GACvB,eAAe,IAAI;EACrB,CAAC;EAED,aAAa;GACX,YAAY;GACZ,UAAU;EACZ;CACF,GAAG,CAAC,MAAM,CAAC;CAEX,MAAM,UAAU,UAAwB,oBAAC,sBAAD,EAA6C,MAAQ,GAA1B,MAAM,GAAoB;CAC7F,MAAM,gBAAgB,eACb;EAAE,OAAO,UAAU;EAAO,WAAW;CAAO,IACnD,CAAC,UAAU,KAAK,CAClB;CAEA,MAAM,OACJ,qBAAC,oBAAD;EAAoB,OAAO;EAA3B,UAAA;GACE,qBAAC,OAAD;IACE,aAAU;IACV,0BAAwB,UAAU;IAClC,KAAK;IACL,WAAW,GAAG,uBAAuB,SAAS;IAJhD,UAAA;MAMI,KAAK,WAAW,KAAK,eAAe,WACpC,qBAAC,UAAD;MACE,aAAU;MACV,WAAU;MAFZ,UAAA,CAIE,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACG,KAAK,WACJ,oBAAC,MAAD;QAAI,WAAU;QAAwC,UAAA,KAAK;OAAY,CAAA,GAExE,KAAK,cACJ,oBAAC,KAAD;QAAG,WAAU;QAAsC,UAAA,KAAK;OAAc,CAAA,CAErE;MACJ,CAAA,GAAA,KAAK,iBAAiB,KAAK,cAAc,SAAS,KACjD,oBAAC,YAAD;OACE,SAAS,KAAK;OACd,SAAS;OACT,OAAM;OACN,WAAU;MACX,CAAA,CAEG;;KAET;KACA,WAAW,SAAS,KAAK,SAAS,MAAM,IAAI,KAAK,QAAQ,IAAI,MAAM;KACnE;IACE;;GACL,oBAAC,cAAD,CAAe,CAAA;GACd,eAAe,oBAAC,gBAAD;IAAgB,SAAA;IAAQ,KAAK;GAAY,CAAA;EACvC;;CAGtB,OACE,oBAAC,iBAAD;EAAiB,OAAO;EACtB,UAAA,oBAAC,oBAAD;GAAoB,OAAO;IAAE;IAAO;GAAK;GACtC,UAAA,SACC,OAEA,oBAAC,UAAU,UAAX;IAAoB,KAAK;IACvB,UAAA,oBAAC,iBAAD;KAAiB,eAAe;KAAI,UAAA;IAAsB,CAAA;GACxC,CAAA;EAEJ,CAAA;CACL,CAAA;AAErB;;;;;AAMA,SAAS,uBAA4D;CACnE,IAAI;EACF,OAAO,QAAQ,CAAC,CAAC;CACnB,QAAQ;EACN;CACF;AACF"}
|
package/dist/standalone.css
CHANGED
|
@@ -96,6 +96,27 @@
|
|
|
96
96
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/*
|
|
100
|
+
* Danger text in dark mode. The starter kits' dark `--destructive` is a dark red meant as a
|
|
101
|
+
* button background (about 2:1 as text on their near-black page), so danger text (row
|
|
102
|
+
* actions, links, messages) in AlfaKit's views and the dialogs and menus they open uses a
|
|
103
|
+
* lighter red (W-D-11). Solid danger buttons keep the kit's red. Override it with
|
|
104
|
+
* `--alfakit-danger-text`.
|
|
105
|
+
*/
|
|
106
|
+
.dark :where([data-alfakit-embedded], [data-alfakit-component]) .text-destructive,
|
|
107
|
+
.dark
|
|
108
|
+
:where(body:has([data-alfakit-embedded], [data-alfakit-component]))
|
|
109
|
+
:where(
|
|
110
|
+
[data-slot='dialog-content'],
|
|
111
|
+
[data-slot='sheet-content'],
|
|
112
|
+
[data-slot='alert-dialog-content'],
|
|
113
|
+
[data-slot='dropdown-menu-content'],
|
|
114
|
+
[data-slot='popover-content']
|
|
115
|
+
)
|
|
116
|
+
.text-destructive {
|
|
117
|
+
color: var(--alfakit-danger-text, oklch(0.704 0.191 22.216));
|
|
118
|
+
}
|
|
119
|
+
|
|
99
120
|
/* Rich editor content and extensions (same rules as the panel stylesheet). */
|
|
100
121
|
.alfakit-prose :where(h2) {
|
|
101
122
|
@apply mt-4 mb-2 text-xl font-semibold;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AlfakitWidgets, AlfakitWidgetsProps } from "./dashboard-widgets.js";
|
|
2
2
|
import { AlfakitNavigation, useAlfakitNavigation } from "./navigation.js";
|
|
3
|
-
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitLayout, StarterKitPageOptions, createStarterKitPage } from "./starter-kit.js";
|
|
3
|
+
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitFullscreenLayout, StarterKitLayout, StarterKitPageOptions, createStarterKitPage } from "./starter-kit.js";
|
|
4
4
|
import { AlfakitCopilot, AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitTenantSwitcher } from "./widgets.js";
|
|
5
|
-
export { AlfakitCopilot, type AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, type AlfakitNavigation, AlfakitNotifications, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitWidgets, type AlfakitWidgetsProps, StarterKitContentLayout, type StarterKitLayout, type StarterKitPageOptions, createStarterKitPage, useAlfakitNavigation };
|
|
5
|
+
export { AlfakitCopilot, type AlfakitHeaderWidgetProps, AlfakitLanguageSwitcher, type AlfakitNavigation, AlfakitNotifications, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitWidgets, type AlfakitWidgetsProps, StarterKitContentLayout, StarterKitFullscreenLayout, type StarterKitLayout, type StarterKitPageOptions, createStarterKitPage, useAlfakitNavigation };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AlfakitWidgets } from "./dashboard-widgets.js";
|
|
2
2
|
import { useAlfakitNavigation } from "./navigation.js";
|
|
3
|
-
import { AlfakitStarterKitRoot, StarterKitContentLayout, createStarterKitPage } from "./starter-kit.js";
|
|
3
|
+
import { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitFullscreenLayout, createStarterKitPage } from "./starter-kit.js";
|
|
4
4
|
import { AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitTenantSwitcher } from "./widgets.js";
|
|
5
|
-
export { AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitWidgets, StarterKitContentLayout, createStarterKitPage, useAlfakitNavigation };
|
|
5
|
+
export { AlfakitCopilot, AlfakitLanguageSwitcher, AlfakitNotifications, AlfakitSearch, AlfakitStarterKitRoot, AlfakitTenantSwitcher, AlfakitWidgets, StarterKitContentLayout, StarterKitFullscreenLayout, createStarterKitPage, useAlfakitNavigation };
|
|
@@ -28,6 +28,15 @@ export interface StarterKitPageOptions extends Pick<AlfakitOptions<AnyComponent>
|
|
|
28
28
|
* `createStarterKitPage({ components: { 'layout:app': MyContent } })`.
|
|
29
29
|
*/
|
|
30
30
|
export declare function StarterKitContentLayout({ children, maxContentWidth }: AppLayoutProps): import("react").JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* A `$layout = 'fullscreen'` page inside the host layout: what `layout:fullscreen` renders in
|
|
33
|
+
* starter kit mode. The host layout is the chrome, so there is no AlfaKit header (brand, top
|
|
34
|
+
* bar slots, user menu, Exit); the screen gets the whole content area. Replace it with
|
|
35
|
+
* `{ components: { 'layout:fullscreen': MyScreen } }`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function StarterKitFullscreenLayout({ children }: {
|
|
38
|
+
children: ReactNode;
|
|
39
|
+
}): import("react").JSX.Element;
|
|
31
40
|
/**
|
|
32
41
|
* The Inertia layout around every Alfakit page in starter kit mode, inside the host layout:
|
|
33
42
|
* Alfakit's context, modals, toasts and the reading direction. It stays mounted while the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-kit.d.ts","names":[],"sources":["../../src/starter-kit/starter-kit.tsx"],"mappings":";;;;;;YAsCY,mBAAmB;EAC7B,cAAc;EACd,UAAU;;iBAGK,8BAA8B,KAC7C,eAAe;;;;;;EAQf,SAAS;;;;;;EAMT,WAAW,eAAe;;;;;;;wBAQZ,0BAA0B,UAAU,mBAAmB,iCAAc,IAAA;;;;;;
|
|
1
|
+
{"version":3,"file":"starter-kit.d.ts","names":[],"sources":["../../src/starter-kit/starter-kit.tsx"],"mappings":";;;;;;YAsCY,mBAAmB;EAC7B,cAAc;EACd,UAAU;;iBAGK,8BAA8B,KAC7C,eAAe;;;;;;EAQf,SAAS;;;;;;EAMT,WAAW,eAAe;;;;;;;wBAQZ,0BAA0B,UAAU,mBAAmB,iCAAc,IAAA;;;;;;;wBA2BrE,6BAA6B;EAAc,UAAU;oBAAW,IAAA;;;;;;wBAkEhE,wBACd,SACA;EAEA,UAAU;EACV,WAAW;oBACZ,IAAA;;;;;;;;;;;;;;wBAoEe,qBAAqB,UAAS;;EAYL,OAAA,OAAA,qCAAuB"}
|
|
@@ -35,10 +35,29 @@ function StarterKitContentLayout({ children, maxContentWidth }) {
|
|
|
35
35
|
]
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* A `$layout = 'fullscreen'` page inside the host layout: what `layout:fullscreen` renders in
|
|
40
|
+
* starter kit mode. The host layout is the chrome, so there is no AlfaKit header (brand, top
|
|
41
|
+
* bar slots, user menu, Exit); the screen gets the whole content area. Replace it with
|
|
42
|
+
* `{ components: { 'layout:fullscreen': MyScreen } }`.
|
|
43
|
+
*/
|
|
44
|
+
function StarterKitFullscreenLayout({ children }) {
|
|
45
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
46
|
+
"data-slot": "content",
|
|
47
|
+
"data-layout": "fullscreen",
|
|
48
|
+
"data-alfakit-embedded": "",
|
|
49
|
+
className: "flex min-h-0 w-full min-w-0 flex-1 flex-col",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsx(Slot, { name: "content.start" }),
|
|
52
|
+
children,
|
|
53
|
+
/* @__PURE__ */ jsx(Slot, { name: "content.end" })
|
|
54
|
+
]
|
|
55
|
+
});
|
|
56
|
+
}
|
|
38
57
|
let browserContext = null;
|
|
39
58
|
function createStarterKitContext(options) {
|
|
40
59
|
const discovered = discoverComponents(options.discover);
|
|
41
|
-
const registry = createDefaultRegistry().registerMany(lazyPanelLayouts).register("layout:auth", AuthLayout).register("layout:app", StarterKitContentLayout).registerMany(discovered.components).registerMany(options.components ?? {});
|
|
60
|
+
const registry = createDefaultRegistry().registerMany(lazyPanelLayouts).register("layout:auth", AuthLayout).register("layout:app", StarterKitContentLayout).register("layout:fullscreen", StarterKitFullscreenLayout).registerMany(discovered.components).registerMany(options.components ?? {});
|
|
42
61
|
const translator = new Translator();
|
|
43
62
|
return {
|
|
44
63
|
registry,
|
|
@@ -131,6 +150,6 @@ function createStarterKitPage(options = {}) {
|
|
|
131
150
|
return AlfakitStarterKitPage;
|
|
132
151
|
}
|
|
133
152
|
//#endregion
|
|
134
|
-
export { AlfakitStarterKitRoot, StarterKitContentLayout, createStarterKitPage };
|
|
153
|
+
export { AlfakitStarterKitRoot, StarterKitContentLayout, StarterKitFullscreenLayout, createStarterKitPage };
|
|
135
154
|
|
|
136
155
|
//# sourceMappingURL=starter-kit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-kit.js","names":[],"sources":["../../src/starter-kit/starter-kit.tsx"],"sourcesContent":["import {\n ActionRunner,\n STARTER_KIT_TOASTER_ID,\n Translator,\n configureCharts,\n installStarterKitRuntime,\n registerRichEditorExtensions,\n resolveRequestErrorNotification,\n starterKitBreadcrumbsFromProps,\n syncStarterKitPage,\n usesStarterKitHostLayout,\n type AlfakitOptions,\n type AlfakitPageProps,\n type StarterKitBreadcrumb,\n} from '@alfakit/core'\nimport { usePage } from '@inertiajs/react'\nimport { useEffect, useState, type ComponentType, type ReactNode } from 'react'\nimport { setToasterId, showToast } from '../components/notifications/flash-toasts'\nimport { DebugPanelSlot } from '../components/panel/debug-panel-slot'\nimport { Slot } from '../components/panel/slot'\nimport {\n AlfakitProvider,\n useAlfakitProps,\n type AlfakitContextValue,\n type AnyComponent,\n} from '../context'\nimport { AlfakitRoot } from '../create-alfakit'\nimport type { AppLayoutProps } from '../layouts/app-layout'\nimport { AuthLayout } from '../layouts/auth-layout'\nimport { lazyPanelLayouts } from '../layouts/lazy-layouts'\nimport { MAX_WIDTHS } from '../layouts/max-widths'\nimport { discoverComponents } from '../lib/discovery'\nimport { preloadIcons } from '../lib/icons'\nimport { cn } from '../lib/utils'\nimport { AlfakitPage } from '../pages/page'\nimport { createDefaultRegistry } from '../registry'\n\n/** The host's layout, as the starter kits' `AppLayout` takes its props. */\nexport type StarterKitLayout = ComponentType<{\n breadcrumbs?: StarterKitBreadcrumb[]\n children: ReactNode\n}>\n\nexport interface StarterKitPageOptions extends Pick<\n AlfakitOptions<AnyComponent>,\n 'components' | 'pages' | 'chartFormatters' | 'chartPlugins' | 'richEditorExtensions'\n> {\n /**\n * The host layout Alfakit pages render in, usually the starter kit's `AppLayout`\n * (`@/layouts/app-layout`). It receives the page's breadcrumbs as `{ title, href }`.\n * `null` renders the pages without a host layout.\n */\n layout?: StarterKitLayout | null\n /**\n * Auto-registered custom components, as for `createAlfakit({ discover })`: pass\n * `import.meta.glob('../../alfakit/{fields,columns,entries,widgets,pages,components,blocks}/**\\/*.tsx')`\n * from `resources/js/pages/Alfakit/Page.tsx` and every file there registers under its name.\n */\n discover?: AlfakitOptions<AnyComponent>['discover']\n}\n\n/**\n * The content area of an Alfakit page inside the host layout: what `layout:app` renders in\n * starter kit mode instead of Alfakit's sidebar and top bar. Replace it with\n * `createStarterKitPage({ components: { 'layout:app': MyContent } })`.\n */\nexport function StarterKitContentLayout({ children, maxContentWidth }: AppLayoutProps) {\n const props = useAlfakitProps()\n // The host's pages fill the content area, so starter kit pages default to the full width.\n const width = maxContentWidth ?? props.alfakit.maxContentWidth ?? 'full'\n\n return (\n <div\n data-slot=\"content\"\n data-alfakit-embedded=\"\"\n className={cn(\n 'mx-auto flex w-full min-w-0 flex-1 flex-col gap-6 p-4 md:p-6',\n MAX_WIDTHS[width] ?? 'max-w-full',\n )}\n >\n <Slot name=\"content.start\" />\n {children}\n <Slot name=\"content.end\" />\n </div>\n )\n}\n\n// One context for the browser session (it survives navigations between host and Alfakit\n// pages); a server render builds one per request so concurrent renders never share a locale.\nlet browserContext: AlfakitContextValue | null = null\n\nfunction createStarterKitContext(options: StarterKitPageOptions): AlfakitContextValue {\n // The host's layout replaces the panel's. Auth pages (invitations, tenant registration)\n // keep the panel's card; the fullscreen layout loads on demand.\n // Auto-registered files sit between the built-ins and the explicit `components` / `pages`.\n const discovered = discoverComponents(options.discover)\n const registry = createDefaultRegistry()\n .registerMany(lazyPanelLayouts)\n .register('layout:auth', AuthLayout)\n .register('layout:app', StarterKitContentLayout)\n .registerMany(discovered.components)\n .registerMany(options.components ?? {})\n const translator = new Translator()\n\n return {\n registry,\n pages: { 'Alfakit/Page': AlfakitPage, ...discovered.pages, ...options.pages },\n translator,\n actions: new ActionRunner({\n endpoints: { action: '', modal: '' },\n // A failed action request is a toast, never a silent no-op.\n onError: (error) => {\n const notification = resolveRequestErrorNotification(\n error,\n null,\n (key, replacements, fallback) => translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n },\n }),\n }\n}\n\nfunction starterKitContext(options: StarterKitPageOptions): AlfakitContextValue {\n if (typeof window === 'undefined') return createStarterKitContext(options)\n\n browserContext ??= createStarterKitContext(options)\n\n return browserContext\n}\n\n/**\n * The Inertia layout around every Alfakit page in starter kit mode, inside the host layout:\n * Alfakit's context, modals, toasts and the reading direction. It stays mounted while the\n * user moves between Alfakit pages.\n */\nexport function AlfakitStarterKitRoot({\n options,\n children,\n}: {\n options?: StarterKitPageOptions\n children?: ReactNode\n}) {\n const [context] = useState(() => starterKitContext(options ?? {}))\n const props = usePage<AlfakitPageProps>().props\n const panel = props.alfakit\n\n // Endpoints and error notifications follow the open page.\n if (panel) {\n context.actions.setEndpoints({\n action: panel.endpoints.action ?? '',\n modal: panel.endpoints.modal ?? '',\n })\n }\n\n useEffect(() => {\n syncStarterKitPage(props)\n }, [props])\n\n useEffect(() => {\n installStarterKitRuntime(\n (notification) => showToast(notification),\n (key, replacements, fallback) => context.translator.t(key, replacements, fallback),\n )\n setToasterId(STARTER_KIT_TOASTER_ID)\n\n return () => {\n // A host page is open: its errors and toasts are the host's again.\n syncStarterKitPage(null)\n setToasterId(undefined)\n }\n }, [context])\n\n return (\n <AlfakitProvider value={context}>\n {/* The reading direction and language of Alfakit's content only: the host layout around\n it (sidebar, header) and the app's own pages keep the document's. */}\n <div\n data-slot=\"starter-kit-root\"\n dir={panel?.localization?.direction ?? 'ltr'}\n lang={panel?.localization?.tag}\n className=\"contents\"\n >\n <AlfakitRoot toasterId={STARTER_KIT_TOASTER_ID}>\n {children}\n {/* The debug panel's button lives in AlfaKit's top bar, which a starter kit doesn't\n render: float it in the corner instead (nothing without `alfakitDebug`). The corner is the\n document's right: the kit's sidebar stays on the left in a right-to-left panel language. */}\n <div data-slot=\"starter-kit-debug-panel\" className=\"fixed right-16 bottom-16 z-40\">\n <DebugPanelSlot />\n </div>\n </AlfakitRoot>\n </div>\n </AlfakitProvider>\n )\n}\n\n/**\n * The page component for `Alfakit/Page` in a starter kit app: the host's\n * `resources/js/pages/Alfakit/Page.tsx` (written by `alfakit:install --starter-kit`) exports it,\n * so Inertia's page resolution, the root view's page preload and SSR all find it like any\n * other host page.\n *\n * ```tsx\n * import { createStarterKitPage } from '@alfakit/react'\n * import AppLayout from '@/layouts/app-layout'\n *\n * export default createStarterKitPage({ layout: AppLayout })\n * ```\n */\nexport function createStarterKitPage(options: StarterKitPageOptions = {}) {\n // Panel pages draw named icons: fetch `lucide-react/dynamic` with the page.\n preloadIcons()\n // `'js:name'` chart option callbacks, Chart.js plugins and rich editor extensions.\n configureCharts(options)\n registerRichEditorExtensions(options.richEditorExtensions ?? {})\n\n function AlfakitStarterKitPage() {\n return <AlfakitPage />\n }\n\n // A layout callback: the host layout (with the page's breadcrumbs), then Alfakit's root.\n AlfakitStarterKitPage.layout = (props: Record<string, unknown>) => [\n ...(options.layout && usesStarterKitHostLayout(props)\n ? [[options.layout, { breadcrumbs: starterKitBreadcrumbsFromProps(props) }] as const]\n : []),\n [AlfakitStarterKitRoot, { options }] as const,\n ]\n\n return AlfakitStarterKitPage\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"starter-kit.js","names":[],"sources":["../../src/starter-kit/starter-kit.tsx"],"sourcesContent":["import {\n ActionRunner,\n STARTER_KIT_TOASTER_ID,\n Translator,\n configureCharts,\n installStarterKitRuntime,\n registerRichEditorExtensions,\n resolveRequestErrorNotification,\n starterKitBreadcrumbsFromProps,\n syncStarterKitPage,\n usesStarterKitHostLayout,\n type AlfakitOptions,\n type AlfakitPageProps,\n type StarterKitBreadcrumb,\n} from '@alfakit/core'\nimport { usePage } from '@inertiajs/react'\nimport { useEffect, useState, type ComponentType, type ReactNode } from 'react'\nimport { setToasterId, showToast } from '../components/notifications/flash-toasts'\nimport { DebugPanelSlot } from '../components/panel/debug-panel-slot'\nimport { Slot } from '../components/panel/slot'\nimport {\n AlfakitProvider,\n useAlfakitProps,\n type AlfakitContextValue,\n type AnyComponent,\n} from '../context'\nimport { AlfakitRoot } from '../create-alfakit'\nimport type { AppLayoutProps } from '../layouts/app-layout'\nimport { AuthLayout } from '../layouts/auth-layout'\nimport { lazyPanelLayouts } from '../layouts/lazy-layouts'\nimport { MAX_WIDTHS } from '../layouts/max-widths'\nimport { discoverComponents } from '../lib/discovery'\nimport { preloadIcons } from '../lib/icons'\nimport { cn } from '../lib/utils'\nimport { AlfakitPage } from '../pages/page'\nimport { createDefaultRegistry } from '../registry'\n\n/** The host's layout, as the starter kits' `AppLayout` takes its props. */\nexport type StarterKitLayout = ComponentType<{\n breadcrumbs?: StarterKitBreadcrumb[]\n children: ReactNode\n}>\n\nexport interface StarterKitPageOptions extends Pick<\n AlfakitOptions<AnyComponent>,\n 'components' | 'pages' | 'chartFormatters' | 'chartPlugins' | 'richEditorExtensions'\n> {\n /**\n * The host layout Alfakit pages render in, usually the starter kit's `AppLayout`\n * (`@/layouts/app-layout`). It receives the page's breadcrumbs as `{ title, href }`.\n * `null` renders the pages without a host layout.\n */\n layout?: StarterKitLayout | null\n /**\n * Auto-registered custom components, as for `createAlfakit({ discover })`: pass\n * `import.meta.glob('../../alfakit/{fields,columns,entries,widgets,pages,components,blocks}/**\\/*.tsx')`\n * from `resources/js/pages/Alfakit/Page.tsx` and every file there registers under its name.\n */\n discover?: AlfakitOptions<AnyComponent>['discover']\n}\n\n/**\n * The content area of an Alfakit page inside the host layout: what `layout:app` renders in\n * starter kit mode instead of Alfakit's sidebar and top bar. Replace it with\n * `createStarterKitPage({ components: { 'layout:app': MyContent } })`.\n */\nexport function StarterKitContentLayout({ children, maxContentWidth }: AppLayoutProps) {\n const props = useAlfakitProps()\n // The host's pages fill the content area, so starter kit pages default to the full width.\n const width = maxContentWidth ?? props.alfakit.maxContentWidth ?? 'full'\n\n return (\n <div\n data-slot=\"content\"\n data-alfakit-embedded=\"\"\n className={cn(\n 'mx-auto flex w-full min-w-0 flex-1 flex-col gap-6 p-4 md:p-6',\n MAX_WIDTHS[width] ?? 'max-w-full',\n )}\n >\n <Slot name=\"content.start\" />\n {children}\n <Slot name=\"content.end\" />\n </div>\n )\n}\n\n/**\n * A `$layout = 'fullscreen'` page inside the host layout: what `layout:fullscreen` renders in\n * starter kit mode. The host layout is the chrome, so there is no AlfaKit header (brand, top\n * bar slots, user menu, Exit); the screen gets the whole content area. Replace it with\n * `{ components: { 'layout:fullscreen': MyScreen } }`.\n */\nexport function StarterKitFullscreenLayout({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"content\"\n data-layout=\"fullscreen\"\n data-alfakit-embedded=\"\"\n className=\"flex min-h-0 w-full min-w-0 flex-1 flex-col\"\n >\n <Slot name=\"content.start\" />\n {children}\n <Slot name=\"content.end\" />\n </div>\n )\n}\n\n// One context for the browser session (it survives navigations between host and Alfakit\n// pages); a server render builds one per request so concurrent renders never share a locale.\nlet browserContext: AlfakitContextValue | null = null\n\nfunction createStarterKitContext(options: StarterKitPageOptions): AlfakitContextValue {\n // The host's layout replaces the panel's. Auth pages (invitations, tenant registration)\n // keep the panel's card; the fullscreen layout loads on demand.\n // Auto-registered files sit between the built-ins and the explicit `components` / `pages`.\n const discovered = discoverComponents(options.discover)\n const registry = createDefaultRegistry()\n .registerMany(lazyPanelLayouts)\n .register('layout:auth', AuthLayout)\n .register('layout:app', StarterKitContentLayout)\n .register('layout:fullscreen', StarterKitFullscreenLayout)\n .registerMany(discovered.components)\n .registerMany(options.components ?? {})\n const translator = new Translator()\n\n return {\n registry,\n pages: { 'Alfakit/Page': AlfakitPage, ...discovered.pages, ...options.pages },\n translator,\n actions: new ActionRunner({\n endpoints: { action: '', modal: '' },\n // A failed action request is a toast, never a silent no-op.\n onError: (error) => {\n const notification = resolveRequestErrorNotification(\n error,\n null,\n (key, replacements, fallback) => translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n },\n }),\n }\n}\n\nfunction starterKitContext(options: StarterKitPageOptions): AlfakitContextValue {\n if (typeof window === 'undefined') return createStarterKitContext(options)\n\n browserContext ??= createStarterKitContext(options)\n\n return browserContext\n}\n\n/**\n * The Inertia layout around every Alfakit page in starter kit mode, inside the host layout:\n * Alfakit's context, modals, toasts and the reading direction. It stays mounted while the\n * user moves between Alfakit pages.\n */\nexport function AlfakitStarterKitRoot({\n options,\n children,\n}: {\n options?: StarterKitPageOptions\n children?: ReactNode\n}) {\n const [context] = useState(() => starterKitContext(options ?? {}))\n const props = usePage<AlfakitPageProps>().props\n const panel = props.alfakit\n\n // Endpoints and error notifications follow the open page.\n if (panel) {\n context.actions.setEndpoints({\n action: panel.endpoints.action ?? '',\n modal: panel.endpoints.modal ?? '',\n })\n }\n\n useEffect(() => {\n syncStarterKitPage(props)\n }, [props])\n\n useEffect(() => {\n installStarterKitRuntime(\n (notification) => showToast(notification),\n (key, replacements, fallback) => context.translator.t(key, replacements, fallback),\n )\n setToasterId(STARTER_KIT_TOASTER_ID)\n\n return () => {\n // A host page is open: its errors and toasts are the host's again.\n syncStarterKitPage(null)\n setToasterId(undefined)\n }\n }, [context])\n\n return (\n <AlfakitProvider value={context}>\n {/* The reading direction and language of Alfakit's content only: the host layout around\n it (sidebar, header) and the app's own pages keep the document's. */}\n <div\n data-slot=\"starter-kit-root\"\n dir={panel?.localization?.direction ?? 'ltr'}\n lang={panel?.localization?.tag}\n className=\"contents\"\n >\n <AlfakitRoot toasterId={STARTER_KIT_TOASTER_ID}>\n {children}\n {/* The debug panel's button lives in AlfaKit's top bar, which a starter kit doesn't\n render: float it in the corner instead (nothing without `alfakitDebug`). The corner is the\n document's right: the kit's sidebar stays on the left in a right-to-left panel language. */}\n <div data-slot=\"starter-kit-debug-panel\" className=\"fixed right-16 bottom-16 z-40\">\n <DebugPanelSlot />\n </div>\n </AlfakitRoot>\n </div>\n </AlfakitProvider>\n )\n}\n\n/**\n * The page component for `Alfakit/Page` in a starter kit app: the host's\n * `resources/js/pages/Alfakit/Page.tsx` (written by `alfakit:install --starter-kit`) exports it,\n * so Inertia's page resolution, the root view's page preload and SSR all find it like any\n * other host page.\n *\n * ```tsx\n * import { createStarterKitPage } from '@alfakit/react'\n * import AppLayout from '@/layouts/app-layout'\n *\n * export default createStarterKitPage({ layout: AppLayout })\n * ```\n */\nexport function createStarterKitPage(options: StarterKitPageOptions = {}) {\n // Panel pages draw named icons: fetch `lucide-react/dynamic` with the page.\n preloadIcons()\n // `'js:name'` chart option callbacks, Chart.js plugins and rich editor extensions.\n configureCharts(options)\n registerRichEditorExtensions(options.richEditorExtensions ?? {})\n\n function AlfakitStarterKitPage() {\n return <AlfakitPage />\n }\n\n // A layout callback: the host layout (with the page's breadcrumbs), then Alfakit's root.\n AlfakitStarterKitPage.layout = (props: Record<string, unknown>) => [\n ...(options.layout && usesStarterKitHostLayout(props)\n ? [[options.layout, { breadcrumbs: starterKitBreadcrumbsFromProps(props) }] as const]\n : []),\n [AlfakitStarterKitRoot, { options }] as const,\n ]\n\n return AlfakitStarterKitPage\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfakit/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "React + shadcn/ui renderer for Alfakit, the Laravel admin panel builder by Alfa Six.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alfa Six (https://alfasixbh.com)",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"react-day-picker": "^10.0.2",
|
|
97
97
|
"sonner": "^2.0.8",
|
|
98
98
|
"tailwind-merge": "^3.7.0",
|
|
99
|
-
"@alfakit/core": "0.1.
|
|
99
|
+
"@alfakit/core": "0.1.12"
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
102
|
"@inertiajs/react": "^3.0.0",
|
|
@@ -180,7 +180,21 @@ export function ActionButton({
|
|
|
180
180
|
const ariaLabel = isIconOnly || labeledFrom ? accessibleName : undefined
|
|
181
181
|
|
|
182
182
|
const button = isPlainLink ? (
|
|
183
|
-
action.
|
|
183
|
+
action.download ? (
|
|
184
|
+
// `download()`: a plain link that saves the file (an Inertia visit would discard it).
|
|
185
|
+
<Button
|
|
186
|
+
asChild
|
|
187
|
+
variant="plain"
|
|
188
|
+
size={sizeProp}
|
|
189
|
+
disabled={action.disabled}
|
|
190
|
+
aria-label={ariaLabel}
|
|
191
|
+
{...extraProps(action.extraAttributes, classes)}
|
|
192
|
+
>
|
|
193
|
+
<a href={action.url} download="">
|
|
194
|
+
{content}
|
|
195
|
+
</a>
|
|
196
|
+
</Button>
|
|
197
|
+
) : action.openUrlInNewTab ? (
|
|
184
198
|
<Button
|
|
185
199
|
asChild
|
|
186
200
|
variant="plain"
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
jsonScalar,
|
|
7
7
|
jsonSize,
|
|
8
8
|
latestServerTiming,
|
|
9
|
+
overlayPlacementDirection,
|
|
9
10
|
prettyJson,
|
|
10
11
|
searchJson,
|
|
11
12
|
type JsonEntry,
|
|
@@ -86,7 +87,11 @@ export function DevToolsInspector() {
|
|
|
86
87
|
</Button>
|
|
87
88
|
</SheetTrigger>
|
|
88
89
|
<SheetContent
|
|
89
|
-
side={
|
|
90
|
+
side={
|
|
91
|
+
overlayPlacementDirection(direction, props.alfakit?.starterKit) === 'rtl'
|
|
92
|
+
? 'left'
|
|
93
|
+
: 'right'
|
|
94
|
+
}
|
|
90
95
|
className="flex w-full flex-col gap-0 p-0 sm:max-w-xl"
|
|
91
96
|
>
|
|
92
97
|
<div data-slot="dev-tools" className="flex min-h-0 flex-1 flex-col">
|
|
@@ -115,6 +115,8 @@ export function ImageEntryComponent({ component }: { component: ImageEntrySchema
|
|
|
115
115
|
data-slot="image-remaining"
|
|
116
116
|
className={cn(
|
|
117
117
|
'text-muted-foreground',
|
|
118
|
+
// The last image keeps the stack's negative end margin (W-S3-03).
|
|
119
|
+
component.stacked && usesDefaultImageStack(component) && 'ms-3',
|
|
118
120
|
remainingTextSizeClass(component.limitedRemainingTextSize),
|
|
119
121
|
)}
|
|
120
122
|
>
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
insertBuilderItem,
|
|
18
18
|
isDeferredPlaceholder,
|
|
19
19
|
itemActionContext,
|
|
20
|
+
itemExtraActions,
|
|
20
21
|
moveIndexedState,
|
|
21
22
|
moveRepeaterItem,
|
|
22
23
|
removeIndexedState,
|
|
@@ -316,7 +317,9 @@ function BuilderFieldContent({ component }: { component: BuilderSchema }) {
|
|
|
316
317
|
index={index}
|
|
317
318
|
count={items.length}
|
|
318
319
|
resolve={(name) => resolve(name, serverItem)}
|
|
319
|
-
extraActions={
|
|
320
|
+
extraActions={
|
|
321
|
+
menu || locked ? undefined : itemExtraActions(component, serverItem)
|
|
322
|
+
}
|
|
320
323
|
buttons={buttons && !menu}
|
|
321
324
|
canClone={canClone && !menu}
|
|
322
325
|
canDelete={canDelete && !menu}
|
|
@@ -353,7 +356,9 @@ function BuilderFieldContent({ component }: { component: BuilderSchema }) {
|
|
|
353
356
|
canMoveDown={buttons && index < items.length - 1}
|
|
354
357
|
canClone={canClone}
|
|
355
358
|
canDelete={canDelete}
|
|
356
|
-
extraActions={
|
|
359
|
+
extraActions={
|
|
360
|
+
locked ? undefined : itemExtraActions(component, serverItem)
|
|
361
|
+
}
|
|
357
362
|
onAction={(name, onClient) =>
|
|
358
363
|
runItemAction(
|
|
359
364
|
resolve(name, serverItem),
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
fileManagerSize,
|
|
10
10
|
filesFromClipboard,
|
|
11
11
|
fileUploadAccept,
|
|
12
|
+
fileUploadEntries,
|
|
12
13
|
fileUploadPaths,
|
|
13
14
|
insertUploadedFile,
|
|
14
15
|
moveRepeaterItem,
|
|
@@ -103,13 +104,7 @@ export function FileUploadField({ component }: { component: FileUploadSchema })
|
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
const paths = fileUploadPaths(value)
|
|
106
|
-
const files: LocalFile[] = paths.
|
|
107
|
-
(path) =>
|
|
108
|
-
[...component.files, ...uploaded].find((file) => file.path === path) ?? {
|
|
109
|
-
path,
|
|
110
|
-
name: path.replace(/^tmp:/, ''),
|
|
111
|
-
},
|
|
112
|
-
)
|
|
107
|
+
const files: LocalFile[] = fileUploadEntries(paths, component.files, uploaded)
|
|
113
108
|
const maxFiles = component.multiple ? (component.maxFiles ?? Infinity) : 1
|
|
114
109
|
const canAddMore = files.length + uploading.length < maxFiles
|
|
115
110
|
|