@alfakit/react 0.1.10 → 0.1.11

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/components/actions/action-button.js +13 -1
  3. package/dist/components/actions/action-button.js.map +1 -1
  4. package/dist/components/dev-tools/dev-tools-inspector.js +2 -2
  5. package/dist/components/dev-tools/dev-tools-inspector.js.map +1 -1
  6. package/dist/components/fields/money-input.d.ts +5 -0
  7. package/dist/components/fields/money-input.d.ts.map +1 -1
  8. package/dist/components/fields/money-input.js +2 -5
  9. package/dist/components/fields/money-input.js.map +1 -1
  10. package/dist/components/panel/lazy-placeholder.d.ts +1 -0
  11. package/dist/components/panel/lazy-placeholder.d.ts.map +1 -1
  12. package/dist/components/panel/lazy-placeholder.js +38 -4
  13. package/dist/components/panel/lazy-placeholder.js.map +1 -1
  14. package/dist/components/table/cells.js +1 -1
  15. package/dist/components/table/cells.js.map +1 -1
  16. package/dist/components/ui/calendar.d.ts.map +1 -1
  17. package/dist/components/ui/calendar.js +7 -0
  18. package/dist/components/ui/calendar.js.map +1 -1
  19. package/dist/components/widgets/dashboard-customizer.js +2 -2
  20. package/dist/components/widgets/dashboard-customizer.js.map +1 -1
  21. package/dist/components/widgets/widgets-block.js +2 -2
  22. package/dist/components/widgets/widgets-block.js.map +1 -1
  23. package/dist/create-alfakit.d.ts.map +1 -1
  24. package/dist/create-alfakit.js +3 -2
  25. package/dist/create-alfakit.js.map +1 -1
  26. package/dist/eject-manifest.json +4 -2
  27. package/dist/index.d.ts +2 -2
  28. package/dist/index.js +2 -2
  29. package/dist/standalone/alfakit-component.js +2 -2
  30. package/dist/standalone/alfakit-component.js.map +1 -1
  31. package/dist/standalone.css +21 -0
  32. package/dist/starter-kit/index.d.ts +2 -2
  33. package/dist/starter-kit/index.js +2 -2
  34. package/dist/starter-kit/starter-kit.d.ts +9 -0
  35. package/dist/starter-kit/starter-kit.d.ts.map +1 -1
  36. package/dist/starter-kit/starter-kit.js +21 -2
  37. package/dist/starter-kit/starter-kit.js.map +1 -1
  38. package/package.json +2 -2
  39. package/src/components/actions/action-button.tsx +15 -1
  40. package/src/components/dev-tools/dev-tools-inspector.tsx +6 -1
  41. package/src/components/fields/money-input.tsx +3 -14
  42. package/src/components/panel/lazy-placeholder.tsx +41 -1
  43. package/src/components/table/cells.tsx +3 -1
  44. package/src/components/ui/calendar.tsx +8 -0
  45. package/src/components/widgets/dashboard-customizer.tsx +2 -2
  46. package/src/components/widgets/widgets-block.tsx +2 -2
  47. package/src/create-alfakit.tsx +9 -1
  48. package/src/standalone/alfakit-component.tsx +2 -2
  49. package/src/starter-kit/index.ts +1 -0
  50. package/src/starter-kit/starter-kit.tsx +22 -0
@@ -1,3 +1,4 @@
1
+ import { useT } from "../../context.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { buttonVariants } from "./button.js";
3
4
  import { jsx } from "react/jsx-runtime";
@@ -5,8 +6,14 @@ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
5
6
  import { DayPicker } from "react-day-picker";
6
7
  //#region src/components/ui/calendar.tsx
7
8
  function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
9
+ const t = useT();
8
10
  return /* @__PURE__ */ jsx(DayPicker, {
9
11
  showOutsideDays,
12
+ labels: {
13
+ labelPrevious: () => t("form.previous_month", {}, "Previous month"),
14
+ labelNext: () => t("form.next_month", {}, "Next month"),
15
+ ...props.labels
16
+ },
10
17
  className: cn("p-3", className),
11
18
  classNames: {
12
19
  months: "flex flex-col sm:flex-row gap-2",
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.js","names":[],"sources":["../../../src/components/ui/calendar.tsx"],"sourcesContent":["import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'\nimport type { ComponentProps } from 'react'\nimport { DayPicker } from 'react-day-picker'\nimport { cn } from '../../lib/utils'\nimport { buttonVariants } from './button'\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: ComponentProps<typeof DayPicker>) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn('p-3', className)}\n classNames={{\n months: 'flex flex-col sm:flex-row gap-2',\n month: 'flex flex-col gap-4',\n month_caption: 'flex justify-center pt-1 relative items-center w-full',\n caption_label: 'text-sm font-medium',\n nav: 'flex items-center gap-1 absolute inset-x-0 top-3 justify-between px-3 pointer-events-none',\n button_previous: cn(\n buttonVariants({ variant: 'outline' }),\n 'pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n ),\n button_next: cn(\n buttonVariants({ variant: 'outline' }),\n 'pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex',\n weekday: 'text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]',\n week: 'flex w-full mt-2',\n day: 'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-e-md first:[&:has([aria-selected])]:rounded-s-md last:[&:has([aria-selected])]:rounded-e-md',\n day_button: cn(\n buttonVariants({ variant: 'ghost' }),\n 'size-8 p-0 font-normal aria-selected:opacity-100',\n ),\n range_start:\n 'day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground',\n range_end: 'day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground',\n selected:\n 'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md',\n today: 'bg-accent text-accent-foreground rounded-md',\n outside: 'day-outside text-muted-foreground aria-selected:text-muted-foreground',\n disabled: 'text-muted-foreground opacity-50',\n range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation, className: chevronClassName, ...rest }) =>\n orientation === 'left' ? (\n <ChevronLeftIcon className={cn('size-4', chevronClassName)} {...rest} />\n ) : (\n <ChevronRightIcon className={cn('size-4', chevronClassName)} {...rest} />\n ),\n }}\n {...props}\n />\n )\n}\n\nexport { Calendar }\n"],"mappings":";;;;;;AAMA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,GAAG,SACgC;CACnC,OACE,oBAAC,WAAD;EACmB;EACjB,WAAW,GAAG,OAAO,SAAS;EAC9B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,KAAK;GACL,iBAAiB,GACf,eAAe,EAAE,SAAS,UAAU,CAAC,GACrC,4EACF;GACA,aAAa,GACX,eAAe,EAAE,SAAS,UAAU,CAAC,GACrC,4EACF;GACA,YAAY;GACZ,UAAU;GACV,SAAS;GACT,MAAM;GACN,KAAK;GACL,YAAY,GACV,eAAe,EAAE,SAAS,QAAQ,CAAC,GACnC,kDACF;GACA,aACE;GACF,WAAW;GACX,UACE;GACF,OAAO;GACP,SAAS;GACT,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;EACL;EACA,YAAY,EACV,UAAU,EAAE,aAAa,WAAW,kBAAkB,GAAG,WACvD,gBAAgB,SACd,oBAAC,iBAAD;GAAiB,WAAW,GAAG,UAAU,gBAAgB;GAAG,GAAI;EAAO,CAAA,IAEvE,oBAAC,kBAAD;GAAkB,WAAW,GAAG,UAAU,gBAAgB;GAAG,GAAI;EAAO,CAAA,EAE9E;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"calendar.js","names":[],"sources":["../../../src/components/ui/calendar.tsx"],"sourcesContent":["import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'\nimport type { ComponentProps } from 'react'\nimport { DayPicker } from 'react-day-picker'\nimport { useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport { buttonVariants } from './button'\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: ComponentProps<typeof DayPicker>) {\n const t = useT()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n labels={{\n labelPrevious: () => t('form.previous_month', {}, 'Previous month'),\n labelNext: () => t('form.next_month', {}, 'Next month'),\n ...props.labels,\n }}\n className={cn('p-3', className)}\n classNames={{\n months: 'flex flex-col sm:flex-row gap-2',\n month: 'flex flex-col gap-4',\n month_caption: 'flex justify-center pt-1 relative items-center w-full',\n caption_label: 'text-sm font-medium',\n nav: 'flex items-center gap-1 absolute inset-x-0 top-3 justify-between px-3 pointer-events-none',\n button_previous: cn(\n buttonVariants({ variant: 'outline' }),\n 'pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n ),\n button_next: cn(\n buttonVariants({ variant: 'outline' }),\n 'pointer-events-auto size-7 bg-transparent p-0 opacity-50 hover:opacity-100',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex',\n weekday: 'text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]',\n week: 'flex w-full mt-2',\n day: 'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-e-md first:[&:has([aria-selected])]:rounded-s-md last:[&:has([aria-selected])]:rounded-e-md',\n day_button: cn(\n buttonVariants({ variant: 'ghost' }),\n 'size-8 p-0 font-normal aria-selected:opacity-100',\n ),\n range_start:\n 'day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground',\n range_end: 'day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground',\n selected:\n 'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md',\n today: 'bg-accent text-accent-foreground rounded-md',\n outside: 'day-outside text-muted-foreground aria-selected:text-muted-foreground',\n disabled: 'text-muted-foreground opacity-50',\n range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation, className: chevronClassName, ...rest }) =>\n orientation === 'left' ? (\n <ChevronLeftIcon className={cn('size-4', chevronClassName)} {...rest} />\n ) : (\n <ChevronRightIcon className={cn('size-4', chevronClassName)} {...rest} />\n ),\n }}\n {...props}\n />\n )\n}\n\nexport { Calendar }\n"],"mappings":";;;;;;;AAOA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,GAAG,SACgC;CACnC,MAAM,IAAI,KAAK;CAEf,OACE,oBAAC,WAAD;EACmB;EACjB,QAAQ;GACN,qBAAqB,EAAE,uBAAuB,CAAC,GAAG,gBAAgB;GAClE,iBAAiB,EAAE,mBAAmB,CAAC,GAAG,YAAY;GACtD,GAAG,MAAM;EACX;EACA,WAAW,GAAG,OAAO,SAAS;EAC9B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,KAAK;GACL,iBAAiB,GACf,eAAe,EAAE,SAAS,UAAU,CAAC,GACrC,4EACF;GACA,aAAa,GACX,eAAe,EAAE,SAAS,UAAU,CAAC,GACrC,4EACF;GACA,YAAY;GACZ,UAAU;GACV,SAAS;GACT,MAAM;GACN,KAAK;GACL,YAAY,GACV,eAAe,EAAE,SAAS,QAAQ,CAAC,GACnC,kDACF;GACA,aACE;GACF,WAAW;GACX,UACE;GACF,OAAO;GACP,SAAS;GACT,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;EACL;EACA,YAAY,EACV,UAAU,EAAE,aAAa,WAAW,kBAAkB,GAAG,WACvD,gBAAgB,SACd,oBAAC,iBAAD;GAAiB,WAAW,GAAG,UAAU,gBAAgB;GAAG,GAAI;EAAO,CAAA,IAEvE,oBAAC,kBAAD;GAAkB,WAAW,GAAG,UAAU,gBAAgB;GAAG,GAAI;EAAO,CAAA,EAE9E;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -2,7 +2,7 @@ import { useDirection, useT } from "../../context.js";
2
2
  import { cn } from "../../lib/utils.js";
3
3
  import { Button } from "../ui/button.js";
4
4
  import { useStore } from "../../hooks/use-store.js";
5
- import { LazyPlaceholder } from "../panel/lazy-placeholder.js";
5
+ import { LazyWidgetPlaceholder } from "../panel/lazy-placeholder.js";
6
6
  import { DashboardEditor, columnSpanClasses, dashboardMoveForKey, gridColumnsClasses, isLazyPlaceholder } from "@alfakit/core";
7
7
  import { router } from "@inertiajs/react";
8
8
  import { useEffect, useId, useMemo } from "react";
@@ -94,7 +94,7 @@ function CustomizableWidgetGrid({ block, customize, renderWidget }) {
94
94
  const label = editor.label(entry.id);
95
95
  const span = editor.spanOf(entry.id);
96
96
  const columnSpan = state.editing && library ? library.spans.find((option) => option.value === span)?.columnSpan ?? widget?.columnSpan : widget?.columnSpan;
97
- const content = widget ? isLazyPlaceholder(widget) ? /* @__PURE__ */ jsx(LazyPlaceholder, { variant: widget.type === "TableWidget" ? "table" : "widget" }) : renderWidget(widget) : /* @__PURE__ */ jsx("div", {
97
+ const content = widget ? isLazyPlaceholder(widget) ? /* @__PURE__ */ jsx(LazyWidgetPlaceholder, { widget }) : renderWidget(widget) : /* @__PURE__ */ jsx("div", {
98
98
  className: "bg-card text-muted-foreground flex min-h-24 items-center justify-center rounded-xl border border-dashed p-6 text-sm",
99
99
  children: t("dashboard.customize.pending", { widget: label }, ":widget appears once you save.")
100
100
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-customizer.js","names":[],"sources":["../../../src/components/widgets/dashboard-customizer.tsx"],"sourcesContent":["import type {\n DashboardCustomizeSchema,\n WidgetsBlock as WidgetsBlockSchema,\n WidgetSchema,\n} from '@alfakit/core'\nimport {\n columnSpanClasses,\n DashboardEditor,\n dashboardMoveForKey,\n gridColumnsClasses,\n isLazyPlaceholder,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/react'\nimport {\n CheckIcon,\n EyeOffIcon,\n GripVerticalIcon,\n LayoutDashboardIcon,\n PlusIcon,\n RotateCcwIcon,\n XIcon,\n} from 'lucide-react'\nimport { useEffect, useId, useMemo, type ReactNode } from 'react'\nimport { useDirection, useT } from '../../context'\nimport { useStore } from '../../hooks/use-store'\nimport { cn } from '../../lib/utils'\nimport { LazyPlaceholder } from '../panel/lazy-placeholder'\nimport { Button } from '../ui/button'\n\n/**\n * A customizable dashboard (`Dashboard::customizable()`): the widget grid plus an \"Edit\n * dashboard\" mode where widgets are dragged (pointer) or moved with the arrow keys on their\n * handle, resized, hidden and added from the library. The layout is saved on the server.\n */\nexport function CustomizableWidgetGrid({\n block,\n customize,\n renderWidget,\n}: {\n block: WidgetsBlockSchema\n customize: DashboardCustomizeSchema\n renderWidget: (widget: WidgetSchema) => ReactNode\n}) {\n const t = useT()\n const dir = useDirection()\n const helpId = useId()\n const editor = useMemo(\n () => new DashboardEditor(customize, { t, onSaved: () => router.reload() }),\n // One editor per dashboard; `sync()` follows later schemas.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [customize.endpoint, customize.token],\n )\n\n useEffect(() => editor.sync(customize), [editor, customize])\n\n const state = useStore(editor.store)\n const widgets = new Map(block.widgets.map((widget) => [widget.id, widget]))\n const visible = state.layout.filter((entry) => !entry.hidden)\n const available = editor.available()\n\n return (\n <div\n data-slot=\"dashboard\"\n data-editing={state.editing ? '' : undefined}\n className=\"flex flex-col gap-4\"\n >\n <div\n data-slot=\"dashboard-toolbar\"\n role=\"toolbar\"\n aria-label={t('dashboard.customize.toolbar', {}, 'Dashboard layout')}\n className=\"flex flex-wrap items-center justify-end gap-2\"\n >\n {state.editing ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => {\n editor.resetDraft()\n }}\n >\n <RotateCcwIcon aria-hidden=\"true\" />\n {t('dashboard.customize.reset', {}, 'Reset to default')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => editor.cancel()}\n >\n <XIcon aria-hidden=\"true\" />\n {t('dashboard.customize.cancel', {}, 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => void editor.save()}\n >\n <CheckIcon aria-hidden=\"true\" />\n {t('dashboard.customize.save', {}, 'Save')}\n </Button>\n </>\n ) : (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => editor.start()}>\n <LayoutDashboardIcon aria-hidden=\"true\" />\n {t('dashboard.customize.edit', {}, 'Edit dashboard')}\n </Button>\n )}\n </div>\n\n {state.error && (\n <p role=\"alert\" className=\"text-destructive text-sm\">\n {state.error}\n </p>\n )}\n\n {state.editing && (\n <p id={helpId} className=\"sr-only\">\n {t(\n 'dashboard.customize.move_help',\n {},\n 'Use the arrow keys to move the widget, Home or End to move it to the start or end.',\n )}\n </p>\n )}\n\n {visible.length === 0 ? (\n <p\n data-slot=\"dashboard-empty\"\n className=\"text-muted-foreground rounded-xl border border-dashed p-6 text-center text-sm\"\n >\n {t('dashboard.customize.empty', {}, 'No widgets on this dashboard yet.')}\n </p>\n ) : (\n <div data-slot=\"widgets\" className={cn('grid gap-6', gridColumnsClasses(block.columns))}>\n {visible.map((entry) => {\n const widget = widgets.get(entry.id)\n const library = editor.widget(entry.id)\n const label = editor.label(entry.id)\n const span = editor.spanOf(entry.id)\n const columnSpan =\n state.editing && library\n ? (library.spans.find((option) => option.value === span)?.columnSpan ??\n widget?.columnSpan)\n : widget?.columnSpan\n\n const content = widget ? (\n isLazyPlaceholder(widget) ? (\n <LazyPlaceholder variant={widget.type === 'TableWidget' ? 'table' : 'widget'} />\n ) : (\n renderWidget(widget)\n )\n ) : (\n <div className=\"bg-card text-muted-foreground flex min-h-24 items-center justify-center rounded-xl border border-dashed p-6 text-sm\">\n {t(\n 'dashboard.customize.pending',\n { widget: label },\n ':widget appears once you save.',\n )}\n </div>\n )\n\n if (!state.editing) {\n return (\n <div key={entry.id} className={cn('min-w-0', columnSpanClasses(columnSpan))}>\n {content}\n </div>\n )\n }\n\n return (\n <div\n key={entry.id}\n data-slot=\"dashboard-widget\"\n data-dragging={state.dragging === entry.id ? '' : undefined}\n role=\"group\"\n aria-label={label}\n className={cn(\n 'relative min-w-0 rounded-xl border-2 border-dashed p-1',\n state.dragging === entry.id && 'opacity-50',\n columnSpanClasses(columnSpan),\n )}\n onDragOver={(event) => {\n if (state.dragging !== null) event.preventDefault()\n }}\n onDrop={(event) => {\n event.preventDefault()\n editor.dropOn(entry.id)\n }}\n >\n <div\n data-slot=\"dashboard-widget-controls\"\n className=\"bg-background/95 absolute inset-x-2 top-2 z-10 flex items-center gap-1 rounded-md border p-1 shadow-sm\"\n >\n <button\n type=\"button\"\n data-slot=\"dashboard-widget-handle\"\n draggable\n aria-label={t('dashboard.customize.move', { widget: label }, 'Move :widget')}\n aria-describedby={helpId}\n aria-roledescription={t('dashboard.customize.sortable', {}, 'sortable')}\n className=\"hover:bg-accent focus-visible:ring-ring/50 cursor-grab rounded p-1 outline-none focus-visible:ring-[3px] active:cursor-grabbing\"\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', entry.id)\n editor.dragStart(entry.id)\n }}\n onDragEnd={() => editor.dragEnd()}\n onKeyDown={(event) => {\n const move = dashboardMoveForKey(event.key, dir)\n\n if (move !== null) {\n event.preventDefault()\n editor.move(entry.id, move)\n // Keep focus on the moved widget's handle.\n const target = event.currentTarget\n requestAnimationFrame(() => target.focus())\n }\n }}\n >\n <GripVerticalIcon className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">{label}</span>\n {library && library.spans.length > 1 && (\n <select\n data-slot=\"dashboard-widget-span\"\n aria-label={t(\n 'dashboard.customize.size',\n { widget: label },\n 'Size of :widget',\n )}\n className=\"border-input bg-background h-7 rounded-md border px-1 text-xs\"\n value={span}\n onChange={(event) => editor.setSpan(entry.id, Number(event.target.value))}\n >\n {library.spans.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('dashboard.customize.hide', { widget: label }, 'Hide :widget')}\n onClick={() => editor.hide(entry.id)}\n >\n <EyeOffIcon aria-hidden=\"true\" />\n </Button>\n </div>\n {/* The widget itself is inert while editing: focus stays on the controls. */}\n <div inert className=\"pointer-events-none pt-12 select-none\" aria-hidden=\"true\">\n {content}\n </div>\n </div>\n )\n })}\n </div>\n )}\n\n {state.editing && (\n <section\n data-slot=\"dashboard-library\"\n aria-label={t('dashboard.customize.library', {}, 'Widget library')}\n className=\"bg-muted/40 flex flex-col gap-3 rounded-xl border p-4\"\n >\n <h2 className=\"text-sm font-medium\">{t('dashboard.customize.add', {}, 'Add widget')}</h2>\n {available.length === 0 ? (\n <p className=\"text-muted-foreground text-sm\">\n {t('dashboard.customize.library_empty', {}, 'Every widget is on the dashboard.')}\n </p>\n ) : (\n <ul className=\"flex flex-wrap gap-2\">\n {available.map((widget) => (\n <li key={widget.id}>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n title={widget.description}\n aria-label={t(\n 'dashboard.customize.add_widget',\n { widget: widget.label },\n 'Add :widget',\n )}\n onClick={() => editor.add(widget.id)}\n >\n <PlusIcon aria-hidden=\"true\" />\n {widget.label}\n </Button>\n </li>\n ))}\n </ul>\n )}\n </section>\n )}\n\n <div data-slot=\"dashboard-announcer\" role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {state.announcement}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-customizer.js","names":[],"sources":["../../../src/components/widgets/dashboard-customizer.tsx"],"sourcesContent":["import type {\n DashboardCustomizeSchema,\n WidgetsBlock as WidgetsBlockSchema,\n WidgetSchema,\n} from '@alfakit/core'\nimport {\n columnSpanClasses,\n DashboardEditor,\n dashboardMoveForKey,\n gridColumnsClasses,\n isLazyPlaceholder,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/react'\nimport {\n CheckIcon,\n EyeOffIcon,\n GripVerticalIcon,\n LayoutDashboardIcon,\n PlusIcon,\n RotateCcwIcon,\n XIcon,\n} from 'lucide-react'\nimport { useEffect, useId, useMemo, type ReactNode } from 'react'\nimport { useDirection, useT } from '../../context'\nimport { useStore } from '../../hooks/use-store'\nimport { cn } from '../../lib/utils'\nimport { LazyWidgetPlaceholder } from '../panel/lazy-placeholder'\nimport { Button } from '../ui/button'\n\n/**\n * A customizable dashboard (`Dashboard::customizable()`): the widget grid plus an \"Edit\n * dashboard\" mode where widgets are dragged (pointer) or moved with the arrow keys on their\n * handle, resized, hidden and added from the library. The layout is saved on the server.\n */\nexport function CustomizableWidgetGrid({\n block,\n customize,\n renderWidget,\n}: {\n block: WidgetsBlockSchema\n customize: DashboardCustomizeSchema\n renderWidget: (widget: WidgetSchema) => ReactNode\n}) {\n const t = useT()\n const dir = useDirection()\n const helpId = useId()\n const editor = useMemo(\n () => new DashboardEditor(customize, { t, onSaved: () => router.reload() }),\n // One editor per dashboard; `sync()` follows later schemas.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [customize.endpoint, customize.token],\n )\n\n useEffect(() => editor.sync(customize), [editor, customize])\n\n const state = useStore(editor.store)\n const widgets = new Map(block.widgets.map((widget) => [widget.id, widget]))\n const visible = state.layout.filter((entry) => !entry.hidden)\n const available = editor.available()\n\n return (\n <div\n data-slot=\"dashboard\"\n data-editing={state.editing ? '' : undefined}\n className=\"flex flex-col gap-4\"\n >\n <div\n data-slot=\"dashboard-toolbar\"\n role=\"toolbar\"\n aria-label={t('dashboard.customize.toolbar', {}, 'Dashboard layout')}\n className=\"flex flex-wrap items-center justify-end gap-2\"\n >\n {state.editing ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => {\n editor.resetDraft()\n }}\n >\n <RotateCcwIcon aria-hidden=\"true\" />\n {t('dashboard.customize.reset', {}, 'Reset to default')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => editor.cancel()}\n >\n <XIcon aria-hidden=\"true\" />\n {t('dashboard.customize.cancel', {}, 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={state.saving}\n onClick={() => void editor.save()}\n >\n <CheckIcon aria-hidden=\"true\" />\n {t('dashboard.customize.save', {}, 'Save')}\n </Button>\n </>\n ) : (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => editor.start()}>\n <LayoutDashboardIcon aria-hidden=\"true\" />\n {t('dashboard.customize.edit', {}, 'Edit dashboard')}\n </Button>\n )}\n </div>\n\n {state.error && (\n <p role=\"alert\" className=\"text-destructive text-sm\">\n {state.error}\n </p>\n )}\n\n {state.editing && (\n <p id={helpId} className=\"sr-only\">\n {t(\n 'dashboard.customize.move_help',\n {},\n 'Use the arrow keys to move the widget, Home or End to move it to the start or end.',\n )}\n </p>\n )}\n\n {visible.length === 0 ? (\n <p\n data-slot=\"dashboard-empty\"\n className=\"text-muted-foreground rounded-xl border border-dashed p-6 text-center text-sm\"\n >\n {t('dashboard.customize.empty', {}, 'No widgets on this dashboard yet.')}\n </p>\n ) : (\n <div data-slot=\"widgets\" className={cn('grid gap-6', gridColumnsClasses(block.columns))}>\n {visible.map((entry) => {\n const widget = widgets.get(entry.id)\n const library = editor.widget(entry.id)\n const label = editor.label(entry.id)\n const span = editor.spanOf(entry.id)\n const columnSpan =\n state.editing && library\n ? (library.spans.find((option) => option.value === span)?.columnSpan ??\n widget?.columnSpan)\n : widget?.columnSpan\n\n const content = widget ? (\n isLazyPlaceholder(widget) ? (\n <LazyWidgetPlaceholder widget={widget} />\n ) : (\n renderWidget(widget)\n )\n ) : (\n <div className=\"bg-card text-muted-foreground flex min-h-24 items-center justify-center rounded-xl border border-dashed p-6 text-sm\">\n {t(\n 'dashboard.customize.pending',\n { widget: label },\n ':widget appears once you save.',\n )}\n </div>\n )\n\n if (!state.editing) {\n return (\n <div key={entry.id} className={cn('min-w-0', columnSpanClasses(columnSpan))}>\n {content}\n </div>\n )\n }\n\n return (\n <div\n key={entry.id}\n data-slot=\"dashboard-widget\"\n data-dragging={state.dragging === entry.id ? '' : undefined}\n role=\"group\"\n aria-label={label}\n className={cn(\n 'relative min-w-0 rounded-xl border-2 border-dashed p-1',\n state.dragging === entry.id && 'opacity-50',\n columnSpanClasses(columnSpan),\n )}\n onDragOver={(event) => {\n if (state.dragging !== null) event.preventDefault()\n }}\n onDrop={(event) => {\n event.preventDefault()\n editor.dropOn(entry.id)\n }}\n >\n <div\n data-slot=\"dashboard-widget-controls\"\n className=\"bg-background/95 absolute inset-x-2 top-2 z-10 flex items-center gap-1 rounded-md border p-1 shadow-sm\"\n >\n <button\n type=\"button\"\n data-slot=\"dashboard-widget-handle\"\n draggable\n aria-label={t('dashboard.customize.move', { widget: label }, 'Move :widget')}\n aria-describedby={helpId}\n aria-roledescription={t('dashboard.customize.sortable', {}, 'sortable')}\n className=\"hover:bg-accent focus-visible:ring-ring/50 cursor-grab rounded p-1 outline-none focus-visible:ring-[3px] active:cursor-grabbing\"\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', entry.id)\n editor.dragStart(entry.id)\n }}\n onDragEnd={() => editor.dragEnd()}\n onKeyDown={(event) => {\n const move = dashboardMoveForKey(event.key, dir)\n\n if (move !== null) {\n event.preventDefault()\n editor.move(entry.id, move)\n // Keep focus on the moved widget's handle.\n const target = event.currentTarget\n requestAnimationFrame(() => target.focus())\n }\n }}\n >\n <GripVerticalIcon className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">{label}</span>\n {library && library.spans.length > 1 && (\n <select\n data-slot=\"dashboard-widget-span\"\n aria-label={t(\n 'dashboard.customize.size',\n { widget: label },\n 'Size of :widget',\n )}\n className=\"border-input bg-background h-7 rounded-md border px-1 text-xs\"\n value={span}\n onChange={(event) => editor.setSpan(entry.id, Number(event.target.value))}\n >\n {library.spans.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('dashboard.customize.hide', { widget: label }, 'Hide :widget')}\n onClick={() => editor.hide(entry.id)}\n >\n <EyeOffIcon aria-hidden=\"true\" />\n </Button>\n </div>\n {/* The widget itself is inert while editing: focus stays on the controls. */}\n <div inert className=\"pointer-events-none pt-12 select-none\" aria-hidden=\"true\">\n {content}\n </div>\n </div>\n )\n })}\n </div>\n )}\n\n {state.editing && (\n <section\n data-slot=\"dashboard-library\"\n aria-label={t('dashboard.customize.library', {}, 'Widget library')}\n className=\"bg-muted/40 flex flex-col gap-3 rounded-xl border p-4\"\n >\n <h2 className=\"text-sm font-medium\">{t('dashboard.customize.add', {}, 'Add widget')}</h2>\n {available.length === 0 ? (\n <p className=\"text-muted-foreground text-sm\">\n {t('dashboard.customize.library_empty', {}, 'Every widget is on the dashboard.')}\n </p>\n ) : (\n <ul className=\"flex flex-wrap gap-2\">\n {available.map((widget) => (\n <li key={widget.id}>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n title={widget.description}\n aria-label={t(\n 'dashboard.customize.add_widget',\n { widget: widget.label },\n 'Add :widget',\n )}\n onClick={() => editor.add(widget.id)}\n >\n <PlusIcon aria-hidden=\"true\" />\n {widget.label}\n </Button>\n </li>\n ))}\n </ul>\n )}\n </section>\n )}\n\n <div data-slot=\"dashboard-announcer\" role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {state.announcement}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { useRegistry, useT } from "../../context.js";
2
2
  import { cn } from "../../lib/utils.js";
3
3
  import { lazyComponent } from "../../lib/lazy.js";
4
- import { LazyPlaceholder } from "../panel/lazy-placeholder.js";
4
+ import { LazyWidgetPlaceholder } from "../panel/lazy-placeholder.js";
5
5
  import { Slot } from "../panel/slot.js";
6
6
  import { DataTable } from "../table/table-block.js";
7
7
  import { ChartWidget } from "./chart-lazy.js";
@@ -30,7 +30,7 @@ function StaticWidgetGrid({ block }) {
30
30
  className: cn("grid gap-6", gridColumnsClasses(block.columns)),
31
31
  children: block.widgets.map((widget) => /* @__PURE__ */ jsx("div", {
32
32
  className: cn("min-w-0", columnSpanClasses(widget.columnSpan)),
33
- children: isLazyPlaceholder(widget) ? /* @__PURE__ */ jsx(LazyPlaceholder, { variant: widget.type === "TableWidget" ? "table" : "widget" }) : /* @__PURE__ */ jsx(WidgetRenderer, { widget })
33
+ children: isLazyPlaceholder(widget) ? /* @__PURE__ */ jsx(LazyWidgetPlaceholder, { widget }) : /* @__PURE__ */ jsx(WidgetRenderer, { widget })
34
34
  }, widget.key))
35
35
  });
36
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"widgets-block.js","names":[],"sources":["../../../src/components/widgets/widgets-block.tsx"],"sourcesContent":["import type { WidgetSchema, WidgetsBlock as WidgetsBlockSchema } from '@alfakit/core'\nimport {\n columnSpanClasses,\n gridColumnsClasses,\n isLazyPlaceholder,\n resolveFirst,\n widgetRegistryKeys,\n} from '@alfakit/core'\nimport { createElement, type ComponentProps } from 'react'\nimport { useRegistry, useT } from '../../context'\nimport { lazyComponent } from '../../lib/lazy'\nimport { cn } from '../../lib/utils'\nimport { LazyPlaceholder } from '../panel/lazy-placeholder'\nimport { Slot } from '../panel/slot'\nimport { DataTable } from '../table/table-block'\nimport { ChartWidget } from './chart-lazy'\nimport type { CustomizableWidgetGrid as CustomizableWidgetGridComponent } from './dashboard-customizer'\nimport { StatsOverviewWidget } from './stats-overview'\n\n/**\n * `Dashboard::customizable()`: the grid with its \"Edit dashboard\" mode. The editor's code\n * loads with the first customizable dashboard; until then (and on the server) the widgets\n * show in the plain grid.\n */\nconst CustomizableWidgetGrid = lazyComponent<\n ComponentProps<typeof CustomizableWidgetGridComponent>\n>(\n () => import('./dashboard-customizer').then((module) => module.CustomizableWidgetGrid),\n ({ block }) => <StaticWidgetGrid block={block} />,\n)\n\nexport function WidgetGrid({ block }: { block: WidgetsBlockSchema }) {\n if (block.customize) {\n return (\n <CustomizableWidgetGrid\n block={block}\n customize={block.customize}\n renderWidget={(widget) => <WidgetRenderer widget={widget} />}\n />\n )\n }\n\n return <StaticWidgetGrid block={block} />\n}\n\nfunction StaticWidgetGrid({ block }: { block: WidgetsBlockSchema }) {\n return (\n <div data-slot=\"widgets\" className={cn('grid gap-6', gridColumnsClasses(block.columns))}>\n {block.widgets.map((widget) => (\n <div key={widget.key} className={cn('min-w-0', columnSpanClasses(widget.columnSpan))}>\n {isLazyPlaceholder(widget) ? (\n <LazyPlaceholder variant={widget.type === 'TableWidget' ? 'table' : 'widget'} />\n ) : (\n <WidgetRenderer widget={widget} />\n )}\n </div>\n ))}\n </div>\n )\n}\n\nexport function WidgetRenderer({ widget }: { widget: WidgetSchema }) {\n const registry = useRegistry()\n const t = useT()\n // Registered components win over the built-in renderers: `Widget::$component`,\n // then `widget:<type>` (e.g. `widget:Chart`), then a custom widget's own type.\n const Custom = resolveFirst(registry, widgetRegistryKeys(widget))\n\n if (Custom) {\n return createElement(Custom, {\n ...(widget.type === 'View' ? (widget.props ?? {}) : {}),\n widget,\n })\n }\n\n switch (widget.type) {\n case 'StatsOverviewWidget':\n return <StatsOverviewWidget widget={widget} />\n case 'Chart':\n return <ChartWidget widget={widget} />\n case 'TableWidget':\n return (\n <>\n <Slot name=\"table-widget.start\" scope={widget.component} />\n <DataTable table={widget.table} component={widget.component} />\n <Slot name=\"table-widget.end\" scope={widget.component} />\n </>\n )\n case 'View':\n return (\n <div className=\"text-destructive rounded-md border border-dashed p-3 text-xs\">\n {t(\n 'widget_not_registered',\n { component: widget.component },\n 'Widget component :component is not registered.',\n )}\n </div>\n )\n default:\n return null\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,MAAM,yBAAyB,oBAGvB,OAAO,4BAAyB,CAAC,MAAM,WAAW,OAAO,sBAAsB,IACpF,EAAE,YAAY,oBAAC,kBAAD,EAAyB,MAAQ,CAAA,CAClD;AAEA,SAAgB,WAAW,EAAE,SAAwC;CACnE,IAAI,MAAM,WACR,OACE,oBAAC,wBAAD;EACS;EACP,WAAW,MAAM;EACjB,eAAe,WAAW,oBAAC,gBAAD,EAAwB,OAAS,CAAA;CAC5D,CAAA;CAIL,OAAO,oBAAC,kBAAD,EAAyB,MAAQ,CAAA;AAC1C;AAEA,SAAS,iBAAiB,EAAE,SAAwC;CAClE,OACE,oBAAC,OAAD;EAAK,aAAU;EAAU,WAAW,GAAG,cAAc,mBAAmB,MAAM,OAAO,CAAC;EACnF,UAAA,MAAM,QAAQ,KAAK,WAClB,oBAAC,OAAD;GAAsB,WAAW,GAAG,WAAW,kBAAkB,OAAO,UAAU,CAAC;GAChF,UAAA,kBAAkB,MAAM,IACvB,oBAAC,iBAAD,EAAiB,SAAS,OAAO,SAAS,gBAAgB,UAAU,SAAW,CAAA,IAE/E,oBAAC,gBAAD,EAAwB,OAAS,CAAA;EAEhC,GANK,OAAO,GAMZ,CACN;CACE,CAAA;AAET;AAEA,SAAgB,eAAe,EAAE,UAAoC;CACnE,MAAM,WAAW,YAAY;CAC7B,MAAM,IAAI,KAAK;CAGf,MAAM,SAAS,aAAa,UAAU,mBAAmB,MAAM,CAAC;CAEhE,IAAI,QACF,OAAO,cAAc,QAAQ;EAC3B,GAAI,OAAO,SAAS,SAAU,OAAO,SAAS,CAAC,IAAK,CAAC;EACrD;CACF,CAAC;CAGH,QAAQ,OAAO,MAAf;EACE,KAAK,uBACH,OAAO,oBAAC,qBAAD,EAA6B,OAAS,CAAA;EAC/C,KAAK,SACH,OAAO,oBAAC,aAAD,EAAqB,OAAS,CAAA;EACvC,KAAK,eACH,OACE,qBAAA,YAAA,EAAA,UAAA;GACE,oBAAC,MAAD;IAAM,MAAK;IAAqB,OAAO,OAAO;GAAY,CAAA;GAC1D,oBAAC,WAAD;IAAW,OAAO,OAAO;IAAO,WAAW,OAAO;GAAY,CAAA;GAC9D,oBAAC,MAAD;IAAM,MAAK;IAAmB,OAAO,OAAO;GAAY,CAAA;EACxD,EAAA,CAAA;EAEN,KAAK,QACH,OACE,oBAAC,OAAD;GAAK,WAAU;GACZ,UAAA,EACC,yBACA,EAAE,WAAW,OAAO,UAAU,GAC9B,gDACF;EACG,CAAA;EAET,SACE,OAAO;CACX;AACF"}
1
+ {"version":3,"file":"widgets-block.js","names":[],"sources":["../../../src/components/widgets/widgets-block.tsx"],"sourcesContent":["import type { WidgetSchema, WidgetsBlock as WidgetsBlockSchema } from '@alfakit/core'\nimport {\n columnSpanClasses,\n gridColumnsClasses,\n isLazyPlaceholder,\n resolveFirst,\n widgetRegistryKeys,\n} from '@alfakit/core'\nimport { createElement, type ComponentProps } from 'react'\nimport { useRegistry, useT } from '../../context'\nimport { lazyComponent } from '../../lib/lazy'\nimport { cn } from '../../lib/utils'\nimport { LazyWidgetPlaceholder } from '../panel/lazy-placeholder'\nimport { Slot } from '../panel/slot'\nimport { DataTable } from '../table/table-block'\nimport { ChartWidget } from './chart-lazy'\nimport type { CustomizableWidgetGrid as CustomizableWidgetGridComponent } from './dashboard-customizer'\nimport { StatsOverviewWidget } from './stats-overview'\n\n/**\n * `Dashboard::customizable()`: the grid with its \"Edit dashboard\" mode. The editor's code\n * loads with the first customizable dashboard; until then (and on the server) the widgets\n * show in the plain grid.\n */\nconst CustomizableWidgetGrid = lazyComponent<\n ComponentProps<typeof CustomizableWidgetGridComponent>\n>(\n () => import('./dashboard-customizer').then((module) => module.CustomizableWidgetGrid),\n ({ block }) => <StaticWidgetGrid block={block} />,\n)\n\nexport function WidgetGrid({ block }: { block: WidgetsBlockSchema }) {\n if (block.customize) {\n return (\n <CustomizableWidgetGrid\n block={block}\n customize={block.customize}\n renderWidget={(widget) => <WidgetRenderer widget={widget} />}\n />\n )\n }\n\n return <StaticWidgetGrid block={block} />\n}\n\nfunction StaticWidgetGrid({ block }: { block: WidgetsBlockSchema }) {\n return (\n <div data-slot=\"widgets\" className={cn('grid gap-6', gridColumnsClasses(block.columns))}>\n {block.widgets.map((widget) => (\n <div key={widget.key} className={cn('min-w-0', columnSpanClasses(widget.columnSpan))}>\n {isLazyPlaceholder(widget) ? (\n <LazyWidgetPlaceholder widget={widget} />\n ) : (\n <WidgetRenderer widget={widget} />\n )}\n </div>\n ))}\n </div>\n )\n}\n\nexport function WidgetRenderer({ widget }: { widget: WidgetSchema }) {\n const registry = useRegistry()\n const t = useT()\n // Registered components win over the built-in renderers: `Widget::$component`,\n // then `widget:<type>` (e.g. `widget:Chart`), then a custom widget's own type.\n const Custom = resolveFirst(registry, widgetRegistryKeys(widget))\n\n if (Custom) {\n return createElement(Custom, {\n ...(widget.type === 'View' ? (widget.props ?? {}) : {}),\n widget,\n })\n }\n\n switch (widget.type) {\n case 'StatsOverviewWidget':\n return <StatsOverviewWidget widget={widget} />\n case 'Chart':\n return <ChartWidget widget={widget} />\n case 'TableWidget':\n return (\n <>\n <Slot name=\"table-widget.start\" scope={widget.component} />\n <DataTable table={widget.table} component={widget.component} />\n <Slot name=\"table-widget.end\" scope={widget.component} />\n </>\n )\n case 'View':\n return (\n <div className=\"text-destructive rounded-md border border-dashed p-3 text-xs\">\n {t(\n 'widget_not_registered',\n { component: widget.component },\n 'Widget component :component is not registered.',\n )}\n </div>\n )\n default:\n return null\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,MAAM,yBAAyB,oBAGvB,OAAO,4BAAyB,CAAC,MAAM,WAAW,OAAO,sBAAsB,IACpF,EAAE,YAAY,oBAAC,kBAAD,EAAyB,MAAQ,CAAA,CAClD;AAEA,SAAgB,WAAW,EAAE,SAAwC;CACnE,IAAI,MAAM,WACR,OACE,oBAAC,wBAAD;EACS;EACP,WAAW,MAAM;EACjB,eAAe,WAAW,oBAAC,gBAAD,EAAwB,OAAS,CAAA;CAC5D,CAAA;CAIL,OAAO,oBAAC,kBAAD,EAAyB,MAAQ,CAAA;AAC1C;AAEA,SAAS,iBAAiB,EAAE,SAAwC;CAClE,OACE,oBAAC,OAAD;EAAK,aAAU;EAAU,WAAW,GAAG,cAAc,mBAAmB,MAAM,OAAO,CAAC;EACnF,UAAA,MAAM,QAAQ,KAAK,WAClB,oBAAC,OAAD;GAAsB,WAAW,GAAG,WAAW,kBAAkB,OAAO,UAAU,CAAC;GAChF,UAAA,kBAAkB,MAAM,IACvB,oBAAC,uBAAD,EAA+B,OAAS,CAAA,IAExC,oBAAC,gBAAD,EAAwB,OAAS,CAAA;EAEhC,GANK,OAAO,GAMZ,CACN;CACE,CAAA;AAET;AAEA,SAAgB,eAAe,EAAE,UAAoC;CACnE,MAAM,WAAW,YAAY;CAC7B,MAAM,IAAI,KAAK;CAGf,MAAM,SAAS,aAAa,UAAU,mBAAmB,MAAM,CAAC;CAEhE,IAAI,QACF,OAAO,cAAc,QAAQ;EAC3B,GAAI,OAAO,SAAS,SAAU,OAAO,SAAS,CAAC,IAAK,CAAC;EACrD;CACF,CAAC;CAGH,QAAQ,OAAO,MAAf;EACE,KAAK,uBACH,OAAO,oBAAC,qBAAD,EAA6B,OAAS,CAAA;EAC/C,KAAK,SACH,OAAO,oBAAC,aAAD,EAAqB,OAAS,CAAA;EACvC,KAAK,eACH,OACE,qBAAA,YAAA,EAAA,UAAA;GACE,oBAAC,MAAD;IAAM,MAAK;IAAqB,OAAO,OAAO;GAAY,CAAA;GAC1D,oBAAC,WAAD;IAAW,OAAO,OAAO;IAAO,WAAW,OAAO;GAAY,CAAA;GAC9D,oBAAC,MAAD;IAAM,MAAK;IAAmB,OAAO,OAAO;GAAY,CAAA;EACxD,EAAA,CAAA;EAEN,KAAK,QACH,OACE,oBAAC,OAAD;GAAK,WAAU;GACZ,UAAA,EACC,yBACA,EAAE,WAAW,OAAO,UAAU,GAC9B,gDACF;EACG,CAAA;EAET,SACE,OAAO;CACX;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-alfakit.d.ts","names":[],"sources":["../src/create-alfakit.tsx"],"mappings":";;;;;iBAsHiB,6BAA6B,eAAe;;EAE3D,WAAW,KAAK,cAAc;EAC9B;;;;;;;;;;;;;;wBAsLoB,cAAc,UAAS,uBAA4B"}
1
+ {"version":3,"file":"create-alfakit.d.ts","names":[],"sources":["../src/create-alfakit.tsx"],"mappings":";;;;;iBA8HiB,6BAA6B,eAAe;;EAE3D,WAAW,KAAK,cAAc;EAC9B;;;;;;;;;;;;;;wBAsLoB,cAAc,UAAS,uBAA4B"}
@@ -13,7 +13,7 @@ import { DevToolsSlot } from "./components/dev-tools/dev-tools-slot.js";
13
13
  import { SchemaContractGuard } from "./components/panel/schema-contract-guard.js";
14
14
  import { Toaster } from "./components/ui/sonner.js";
15
15
  import { panelLayouts } from "./layouts/panel-layouts.js";
16
- import { ActionRunner, PANEL_TOAST_OFFSET, Translator, applyDocumentLocale, applyPanelTheme, configureCharts, configureRealtime, debugRecorder, documentNonce, effectiveErrorNotifications, initializeAppearance, installErrorNotifications, installPrefetchInvalidation, installSpaUrlExceptions, registerRichEditorExtensions, reloadOnExpiredPage, resolveRequestErrorNotification, resolveToastPosition, setRequestErrorReporter, whenIdle } from "@alfakit/core";
16
+ import { ActionRunner, PANEL_TOAST_OFFSET, Translator, applyDocumentLocale, applyPanelTheme, configureCharts, configureRealtime, debugRecorder, documentNonce, effectiveErrorNotifications, initializeAppearance, installErrorNotifications, installPrefetchInvalidation, installSpaUrlExceptions, overlayPlacementDirection, registerRichEditorExtensions, reloadOnExpiredPage, resolveRequestErrorNotification, resolveToastPosition, setIconAliases, setRequestErrorReporter, whenIdle } from "@alfakit/core";
17
17
  import { createInertiaApp, router, usePage } from "@inertiajs/react";
18
18
  import { StrictMode, createElement, useLayoutEffect } from "react";
19
19
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -31,6 +31,7 @@ function AlfakitRoot({ children, toasterId }) {
31
31
  if (panel) {
32
32
  translator.setTranslations(panel.translations ?? {});
33
33
  translator.setLocale(localization?.tag ?? "en");
34
+ setIconAliases(panel.theme?.icons);
34
35
  }
35
36
  const ownsDocument = panel?.starterKit !== true;
36
37
  useLayoutEffect(() => {
@@ -56,7 +57,7 @@ function AlfakitRoot({ children, toasterId }) {
56
57
  panel?.impersonation && createElement(registry.resolve("panel:impersonation-banner") ?? ImpersonationBanner, { impersonation: panel.impersonation }),
57
58
  /* @__PURE__ */ jsx(Toaster, {
58
59
  id: toasterId,
59
- position: resolveToastPosition(panel?.toastPosition, direction),
60
+ position: resolveToastPosition(panel?.toastPosition, overlayPlacementDirection(direction, panel?.starterKit)),
60
61
  offset: PANEL_TOAST_OFFSET,
61
62
  mobileOffset: PANEL_TOAST_OFFSET,
62
63
  dir: direction,
@@ -1 +1 @@
1
- {"version":3,"file":"create-alfakit.js","names":[],"sources":["../src/create-alfakit.tsx"],"sourcesContent":["import {\n ActionRunner,\n PANEL_TOAST_OFFSET,\n Translator,\n applyDocumentLocale,\n applyPanelTheme,\n configureCharts,\n configureRealtime,\n debugRecorder,\n documentNonce,\n effectiveErrorNotifications,\n initializeAppearance,\n installErrorNotifications,\n installPrefetchInvalidation,\n installSpaUrlExceptions,\n registerRichEditorExtensions,\n reloadOnExpiredPage,\n resolveRequestErrorNotification,\n resolveToastPosition,\n setRequestErrorReporter,\n whenIdle,\n type AlfakitOptions,\n type AlfakitPageProps,\n type ErrorNotificationsSchema,\n type PanelSchema,\n} from '@alfakit/core'\nimport type { InertiaAppSSRResponse, Page } from '@inertiajs/core'\nimport { createInertiaApp, router, usePage } from '@inertiajs/react'\nimport { Direction } from 'radix-ui'\nimport {\n StrictMode,\n createElement,\n useLayoutEffect,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { ActionModals } from './components/actions/action-modals'\nimport { DevToolsSlot } from './components/dev-tools/dev-tools-slot'\nimport { FlashToasts, showToast } from './components/notifications/flash-toasts'\nimport { RealtimeNotifications } from './components/notifications/realtime-notifications'\nimport { ImpersonationBanner } from './components/panel/impersonation-banner'\nimport { PwaManager } from './components/panel/pwa'\nimport { SchemaContractGuard } from './components/panel/schema-contract-guard'\nimport { Toaster } from './components/ui/sonner'\nimport { TooltipProvider } from './components/ui/tooltip'\nimport { AlfakitProvider, useAlfakit, type AlfakitContextValue, type AnyComponent } from './context'\nimport { panelLayouts } from './layouts/panel-layouts'\nimport { discoverComponents } from './lib/discovery'\nimport { preloadIcons } from './lib/icons'\nimport { AlfakitPage } from './pages/page'\nimport { builtInComponents, createDefaultRegistry } from './registry'\n\n/**\n * Rendered inside Inertia's page tree, so it follows the current page: the reading\n * direction for Radix primitives, modals and toasts.\n */\nexport function AlfakitRoot({\n children,\n toasterId,\n}: {\n children: ReactNode\n /** Starter kit mode: Alfakit's toaster gets an id so the host's id-less one never doubles its toasts. */\n toasterId?: string\n}) {\n const panel = usePage<AlfakitPageProps>().props.alfakit\n const { translator, registry } = useAlfakit()\n const localization = panel?.localization\n const direction = localization?.direction ?? 'ltr'\n\n // Every visit (including the redirect after a language switch) may carry new strings,\n // so the translator is updated before children render.\n if (panel) {\n translator.setTranslations(panel.translations ?? {})\n translator.setLocale(localization?.tag ?? 'en')\n }\n\n // Starter kit mode: the host app owns `<html lang dir>` (its own pages and layout are not\n // mirrored); `AlfakitStarterKitRoot` puts the direction on Alfakit's own root element.\n const ownsDocument = panel?.starterKit !== true\n\n useLayoutEffect(() => {\n if (ownsDocument) applyDocumentLocale(localization)\n }, [localization, ownsDocument])\n\n useLayoutEffect(() => {\n applyPanelTheme(panel)\n }, [panel])\n\n return (\n <Direction.Provider dir={direction}>\n <TooltipProvider delayDuration={0}>\n <SchemaContractGuard panel={panel}>{children}</SchemaContractGuard>\n <ActionModals />\n <FlashToasts />\n <RealtimeNotifications />\n {/* `Panel::pwa()`: service worker and the \"new version\" toast. */}\n <PwaManager />\n {/* Schema inspector: renders (and loads its code) only with `alfakitDevTools`. */}\n <DevToolsSlot />\n {/* Replace with createAlfakit({ components: { 'panel:impersonation-banner': … } }). */}\n {panel?.impersonation &&\n createElement(registry.resolve('panel:impersonation-banner') ?? ImpersonationBanner, {\n impersonation: panel.impersonation,\n })}\n <Toaster\n id={toasterId}\n position={resolveToastPosition(panel?.toastPosition, direction)}\n offset={PANEL_TOAST_OFFSET}\n mobileOffset={PANEL_TOAST_OFFSET}\n dir={direction}\n richColors\n closeButton\n />\n </TooltipProvider>\n </Direction.Provider>\n )\n}\n\nexport interface CreateAlfakitOptions extends AlfakitOptions<AnyComponent> {\n /** Wrap the whole app (e.g. with your own providers). */\n withApp?: (app: ReactNode) => ReactNode\n strictMode?: boolean\n}\n\n/** Renders one Inertia page to HTML: what `createInertiaApp` returns on the server. */\nexport type AlfakitRenderFunction = (\n page: Page,\n renderToString: (element: ReactElement) => string,\n) => Promise<InertiaAppSSRResponse>\n\n/**\n * The Inertia app shared by `createAlfakit()` (browser) and `createAlfakitServer()` (Node):\n * the same registry, pages, layout and providers. In the browser it mounts, or hydrates\n * server-rendered markup; on the server (no `window`) Inertia returns a render function.\n */\nexport function bootAlfakit(\n options: CreateAlfakitOptions = {},\n): Promise<void | AlfakitRenderFunction> {\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(panelLayouts)\n .registerMany(discovered.components)\n .registerMany(options.components ?? {})\n const pages: Record<string, AnyComponent> = {\n 'Alfakit/Page': AlfakitPage,\n ...discovered.pages,\n ...options.pages,\n }\n const isServer = typeof window === 'undefined'\n\n // Every panel page draws named icons: fetch `lucide-react/dynamic` while booting.\n preloadIcons()\n\n // `'js:name'` chart option callbacks and Chart.js plugins for every chart widget.\n configureCharts(options)\n // `createAlfakit({ echo })`: Laravel Echo for `Panel::realtime()` without `window.Echo`.\n if (options.echo !== undefined && !isServer) configureRealtime(null, { echo: options.echo })\n // Rich content plugin extensions, loaded when an editor needs them.\n registerRichEditorExtensions(options.richEditorExtensions ?? {})\n\n // The browser's current panel, read by the SPA-exception and error-notification listeners.\n let currentPanel: PanelSchema | null = null\n // The open page's error notifications (its override, else the panel's).\n let currentErrorNotifications: ErrorNotificationsSchema | false | undefined\n\n // One translator and action runner for the browser session; a server render gets fresh\n // ones per request so concurrent renders never share a locale or endpoints.\n const createContext = (): AlfakitContextValue => {\n const translator = new Translator()\n\n return {\n registry,\n pages,\n translator,\n // The runner's endpoints are refreshed on every navigation from the shared props.\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 currentErrorNotifications,\n (key, replacements, fallback) => translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n },\n }),\n }\n }\n\n const browserContext = isServer ? null : createContext()\n\n const sync = (context: AlfakitContextValue, page: Page, applyToDocument: boolean) => {\n const props = page.props as unknown as AlfakitPageProps\n const panel = props.alfakit\n\n if (!panel) return\n\n if (context === browserContext) {\n currentPanel = panel\n currentErrorNotifications = effectiveErrorNotifications(panel, props.page)\n }\n\n context.translator.setTranslations(panel.translations ?? {})\n context.translator.setLocale(panel.localization?.tag ?? 'en')\n context.actions.setEndpoints({\n action: panel.endpoints.action ?? '',\n modal: panel.endpoints.modal ?? '',\n })\n\n if (applyToDocument) {\n applyDocumentLocale(panel.localization)\n applyPanelTheme(panel)\n // Internal requests and form stores are only recorded while the page carries the debug prop.\n debugRecorder.setEnabled(props.alfakitDebug !== undefined)\n }\n }\n\n if (browserContext) {\n router.on('navigate', (event) => sync(browserContext, event.detail.page, true))\n reloadOnExpiredPage()\n // Prefetched pages and deferred table totals are dropped after every mutation.\n installPrefetchInvalidation()\n installSpaUrlExceptions(() => currentPanel)\n installErrorNotifications(\n () => ({ errorNotifications: currentErrorNotifications }),\n (notification) => showToast(notification),\n )\n // Failed internal requests without their own handler (form live refreshes, step\n // validation) show the configured error notification too.\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(\n error,\n currentErrorNotifications,\n (key, replacements, fallback) => browserContext.translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n })\n }\n\n return createInertiaApp<AlfakitPageProps>({\n title: (title) => title,\n progress: options.progress === undefined ? { color: 'var(--primary)' } : options.progress,\n // The page's CSP nonce, so the progress bar's injected <style> passes a nonce-based policy.\n nonce: documentNonce(),\n resolve: (name, page) => {\n const component = pages[name]\n\n if (!component) {\n throw new Error(\n `Alfakit: page component \"${name}\" is not registered. Pass it to createAlfakit({ pages }).`,\n )\n }\n\n // The page's auto-registered components load first, so the server render and the\n // hydration both show them (no flash, no mismatch).\n // Built-ins split per type (`builtInComponents`) load the same way.\n const pending = [\n builtInComponents.preloadFor(page),\n discovered.discovery.preloadFor(page),\n ].filter((promise) => promise !== undefined)\n\n return pending.length > 0 ? Promise.all(pending).then(() => component) : component\n },\n layout: () => AlfakitRoot,\n strictMode: options.strictMode ?? true,\n withApp: (app, { page, ssr }) => {\n const context = browserContext ?? createContext()\n\n sync(context, page as Page, !ssr)\n\n // Panel pages only: other pages (`pages` option) follow the application's own dark\n // mode, like standalone components do.\n const panel = (page.props as unknown as Partial<AlfakitPageProps>).alfakit\n\n if (!ssr && panel) {\n initializeAppearance(panel)\n }\n\n const tree = <AlfakitProvider value={context}>{app}</AlfakitProvider>\n\n const wrapped = options.withApp ? options.withApp(tree) : tree\n\n return options.strictMode === false ? <>{wrapped}</> : <StrictMode>{wrapped}</StrictMode>\n },\n }) as Promise<void | AlfakitRenderFunction>\n}\n\n/**\n * Boot the Alfakit panel frontend. Call once from your panel entry file. Markup rendered by\n * `createAlfakitServer()` (`@alfakit/react/server`) is hydrated instead of re-rendered.\n *\n * ```tsx\n * createAlfakit({\n * // Files in resources/js/alfakit/fields, columns, … register themselves.\n * discover: import.meta.glob('./{fields,columns,entries,widgets,pages,components,blocks}/**\\/*.tsx'),\n * components: { 'map-picker': MapPicker },\n * })\n * ```\n */\nexport async function createAlfakit(options: CreateAlfakitOptions = {}): Promise<void> {\n await bootAlfakit(options)\n\n // After the first render: the remaining split built-ins (action modals' fields).\n whenIdle(() => void builtInComponents.preloadAll())\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create-alfakit.js","names":[],"sources":["../src/create-alfakit.tsx"],"sourcesContent":["import {\n ActionRunner,\n PANEL_TOAST_OFFSET,\n Translator,\n applyDocumentLocale,\n applyPanelTheme,\n configureCharts,\n configureRealtime,\n debugRecorder,\n documentNonce,\n effectiveErrorNotifications,\n initializeAppearance,\n installErrorNotifications,\n installPrefetchInvalidation,\n installSpaUrlExceptions,\n overlayPlacementDirection,\n registerRichEditorExtensions,\n reloadOnExpiredPage,\n resolveRequestErrorNotification,\n resolveToastPosition,\n setIconAliases,\n setRequestErrorReporter,\n whenIdle,\n type AlfakitOptions,\n type AlfakitPageProps,\n type ErrorNotificationsSchema,\n type PanelSchema,\n} from '@alfakit/core'\nimport type { InertiaAppSSRResponse, Page } from '@inertiajs/core'\nimport { createInertiaApp, router, usePage } from '@inertiajs/react'\nimport { Direction } from 'radix-ui'\nimport {\n StrictMode,\n createElement,\n useLayoutEffect,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { ActionModals } from './components/actions/action-modals'\nimport { DevToolsSlot } from './components/dev-tools/dev-tools-slot'\nimport { FlashToasts, showToast } from './components/notifications/flash-toasts'\nimport { RealtimeNotifications } from './components/notifications/realtime-notifications'\nimport { ImpersonationBanner } from './components/panel/impersonation-banner'\nimport { PwaManager } from './components/panel/pwa'\nimport { SchemaContractGuard } from './components/panel/schema-contract-guard'\nimport { Toaster } from './components/ui/sonner'\nimport { TooltipProvider } from './components/ui/tooltip'\nimport { AlfakitProvider, useAlfakit, type AlfakitContextValue, type AnyComponent } from './context'\nimport { panelLayouts } from './layouts/panel-layouts'\nimport { discoverComponents } from './lib/discovery'\nimport { preloadIcons } from './lib/icons'\nimport { AlfakitPage } from './pages/page'\nimport { builtInComponents, createDefaultRegistry } from './registry'\n\n/**\n * Rendered inside Inertia's page tree, so it follows the current page: the reading\n * direction for Radix primitives, modals and toasts.\n */\nexport function AlfakitRoot({\n children,\n toasterId,\n}: {\n children: ReactNode\n /** Starter kit mode: Alfakit's toaster gets an id so the host's id-less one never doubles its toasts. */\n toasterId?: string\n}) {\n const panel = usePage<AlfakitPageProps>().props.alfakit\n const { translator, registry } = useAlfakit()\n const localization = panel?.localization\n const direction = localization?.direction ?? 'ltr'\n\n // Every visit (including the redirect after a language switch) may carry new strings,\n // so the translator is updated before children render.\n if (panel) {\n translator.setTranslations(panel.translations ?? {})\n translator.setLocale(localization?.tag ?? 'en')\n // Chrome icons replaced with `Icons::register()`, also in a server render, so the server\n // and the browser draw the same glyph (W-V3-28).\n setIconAliases(panel.theme?.icons)\n }\n\n // Starter kit mode: the host app owns `<html lang dir>` (its own pages and layout are not\n // mirrored); `AlfakitStarterKitRoot` puts the direction on Alfakit's own root element.\n const ownsDocument = panel?.starterKit !== true\n\n useLayoutEffect(() => {\n if (ownsDocument) applyDocumentLocale(localization)\n }, [localization, ownsDocument])\n\n useLayoutEffect(() => {\n applyPanelTheme(panel)\n }, [panel])\n\n return (\n <Direction.Provider dir={direction}>\n <TooltipProvider delayDuration={0}>\n <SchemaContractGuard panel={panel}>{children}</SchemaContractGuard>\n <ActionModals />\n <FlashToasts />\n <RealtimeNotifications />\n {/* `Panel::pwa()`: service worker and the \"new version\" toast. */}\n <PwaManager />\n {/* Schema inspector: renders (and loads its code) only with `alfakitDevTools`. */}\n <DevToolsSlot />\n {/* Replace with createAlfakit({ components: { 'panel:impersonation-banner': … } }). */}\n {panel?.impersonation &&\n createElement(registry.resolve('panel:impersonation-banner') ?? ImpersonationBanner, {\n impersonation: panel.impersonation,\n })}\n <Toaster\n id={toasterId}\n position={resolveToastPosition(\n panel?.toastPosition,\n overlayPlacementDirection(direction, panel?.starterKit),\n )}\n offset={PANEL_TOAST_OFFSET}\n mobileOffset={PANEL_TOAST_OFFSET}\n dir={direction}\n richColors\n closeButton\n />\n </TooltipProvider>\n </Direction.Provider>\n )\n}\n\nexport interface CreateAlfakitOptions extends AlfakitOptions<AnyComponent> {\n /** Wrap the whole app (e.g. with your own providers). */\n withApp?: (app: ReactNode) => ReactNode\n strictMode?: boolean\n}\n\n/** Renders one Inertia page to HTML: what `createInertiaApp` returns on the server. */\nexport type AlfakitRenderFunction = (\n page: Page,\n renderToString: (element: ReactElement) => string,\n) => Promise<InertiaAppSSRResponse>\n\n/**\n * The Inertia app shared by `createAlfakit()` (browser) and `createAlfakitServer()` (Node):\n * the same registry, pages, layout and providers. In the browser it mounts, or hydrates\n * server-rendered markup; on the server (no `window`) Inertia returns a render function.\n */\nexport function bootAlfakit(\n options: CreateAlfakitOptions = {},\n): Promise<void | AlfakitRenderFunction> {\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(panelLayouts)\n .registerMany(discovered.components)\n .registerMany(options.components ?? {})\n const pages: Record<string, AnyComponent> = {\n 'Alfakit/Page': AlfakitPage,\n ...discovered.pages,\n ...options.pages,\n }\n const isServer = typeof window === 'undefined'\n\n // Every panel page draws named icons: fetch `lucide-react/dynamic` while booting.\n preloadIcons()\n\n // `'js:name'` chart option callbacks and Chart.js plugins for every chart widget.\n configureCharts(options)\n // `createAlfakit({ echo })`: Laravel Echo for `Panel::realtime()` without `window.Echo`.\n if (options.echo !== undefined && !isServer) configureRealtime(null, { echo: options.echo })\n // Rich content plugin extensions, loaded when an editor needs them.\n registerRichEditorExtensions(options.richEditorExtensions ?? {})\n\n // The browser's current panel, read by the SPA-exception and error-notification listeners.\n let currentPanel: PanelSchema | null = null\n // The open page's error notifications (its override, else the panel's).\n let currentErrorNotifications: ErrorNotificationsSchema | false | undefined\n\n // One translator and action runner for the browser session; a server render gets fresh\n // ones per request so concurrent renders never share a locale or endpoints.\n const createContext = (): AlfakitContextValue => {\n const translator = new Translator()\n\n return {\n registry,\n pages,\n translator,\n // The runner's endpoints are refreshed on every navigation from the shared props.\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 currentErrorNotifications,\n (key, replacements, fallback) => translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n },\n }),\n }\n }\n\n const browserContext = isServer ? null : createContext()\n\n const sync = (context: AlfakitContextValue, page: Page, applyToDocument: boolean) => {\n const props = page.props as unknown as AlfakitPageProps\n const panel = props.alfakit\n\n if (!panel) return\n\n if (context === browserContext) {\n currentPanel = panel\n currentErrorNotifications = effectiveErrorNotifications(panel, props.page)\n }\n\n context.translator.setTranslations(panel.translations ?? {})\n context.translator.setLocale(panel.localization?.tag ?? 'en')\n context.actions.setEndpoints({\n action: panel.endpoints.action ?? '',\n modal: panel.endpoints.modal ?? '',\n })\n\n if (applyToDocument) {\n applyDocumentLocale(panel.localization)\n applyPanelTheme(panel)\n // Internal requests and form stores are only recorded while the page carries the debug prop.\n debugRecorder.setEnabled(props.alfakitDebug !== undefined)\n }\n }\n\n if (browserContext) {\n router.on('navigate', (event) => sync(browserContext, event.detail.page, true))\n reloadOnExpiredPage()\n // Prefetched pages and deferred table totals are dropped after every mutation.\n installPrefetchInvalidation()\n installSpaUrlExceptions(() => currentPanel)\n installErrorNotifications(\n () => ({ errorNotifications: currentErrorNotifications }),\n (notification) => showToast(notification),\n )\n // Failed internal requests without their own handler (form live refreshes, step\n // validation) show the configured error notification too.\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(\n error,\n currentErrorNotifications,\n (key, replacements, fallback) => browserContext.translator.t(key, replacements, fallback),\n )\n\n if (notification) showToast(notification)\n })\n }\n\n return createInertiaApp<AlfakitPageProps>({\n title: (title) => title,\n progress: options.progress === undefined ? { color: 'var(--primary)' } : options.progress,\n // The page's CSP nonce, so the progress bar's injected <style> passes a nonce-based policy.\n nonce: documentNonce(),\n resolve: (name, page) => {\n const component = pages[name]\n\n if (!component) {\n throw new Error(\n `Alfakit: page component \"${name}\" is not registered. Pass it to createAlfakit({ pages }).`,\n )\n }\n\n // The page's auto-registered components load first, so the server render and the\n // hydration both show them (no flash, no mismatch).\n // Built-ins split per type (`builtInComponents`) load the same way.\n const pending = [\n builtInComponents.preloadFor(page),\n discovered.discovery.preloadFor(page),\n ].filter((promise) => promise !== undefined)\n\n return pending.length > 0 ? Promise.all(pending).then(() => component) : component\n },\n layout: () => AlfakitRoot,\n strictMode: options.strictMode ?? true,\n withApp: (app, { page, ssr }) => {\n const context = browserContext ?? createContext()\n\n sync(context, page as Page, !ssr)\n\n // Panel pages only: other pages (`pages` option) follow the application's own dark\n // mode, like standalone components do.\n const panel = (page.props as unknown as Partial<AlfakitPageProps>).alfakit\n\n if (!ssr && panel) {\n initializeAppearance(panel)\n }\n\n const tree = <AlfakitProvider value={context}>{app}</AlfakitProvider>\n\n const wrapped = options.withApp ? options.withApp(tree) : tree\n\n return options.strictMode === false ? <>{wrapped}</> : <StrictMode>{wrapped}</StrictMode>\n },\n }) as Promise<void | AlfakitRenderFunction>\n}\n\n/**\n * Boot the Alfakit panel frontend. Call once from your panel entry file. Markup rendered by\n * `createAlfakitServer()` (`@alfakit/react/server`) is hydrated instead of re-rendered.\n *\n * ```tsx\n * createAlfakit({\n * // Files in resources/js/alfakit/fields, columns, … register themselves.\n * discover: import.meta.glob('./{fields,columns,entries,widgets,pages,components,blocks}/**\\/*.tsx'),\n * components: { 'map-picker': MapPicker },\n * })\n * ```\n */\nexport async function createAlfakit(options: CreateAlfakitOptions = {}): Promise<void> {\n await bootAlfakit(options)\n\n // After the first render: the remaining split built-ins (action modals' fields).\n whenIdle(() => void builtInComponents.preloadAll())\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "package": "@alfakit/react",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "adapter": "react",
5
- "generatedAt": "2026-10-25T11:21:24.983Z",
5
+ "generatedAt": "2026-10-26T05:34:34.271Z",
6
6
  "components": {
7
7
  "TextInput": {
8
8
  "file": "src/components/fields/text-input.tsx",
@@ -915,6 +915,7 @@
915
915
  "src/starter-kit/starter-kit.tsx": {
916
916
  "AlfakitStarterKitRoot": "AlfakitStarterKitRoot",
917
917
  "StarterKitContentLayout": "StarterKitContentLayout",
918
+ "StarterKitFullscreenLayout": "StarterKitFullscreenLayout",
918
919
  "createStarterKitPage": "createStarterKitPage",
919
920
  "StarterKitLayout": "StarterKitLayout",
920
921
  "StarterKitPageOptions": "StarterKitPageOptions"
@@ -934,6 +935,7 @@
934
935
  "AlfakitNavigation": "AlfakitNavigation",
935
936
  "AlfakitStarterKitRoot": "AlfakitStarterKitRoot",
936
937
  "StarterKitContentLayout": "StarterKitContentLayout",
938
+ "StarterKitFullscreenLayout": "StarterKitFullscreenLayout",
937
939
  "createStarterKitPage": "createStarterKitPage",
938
940
  "StarterKitLayout": "StarterKitLayout",
939
941
  "StarterKitPageOptions": "StarterKitPageOptions",
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 };
@@ -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 shrink-0"
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"}
@@ -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;;;;;;wBAuErE,wBACd,SACA;EAEA,UAAU;EACV,WAAW;oBACZ,IAAA;;;;;;;;;;;;;;wBAoEe,qBAAqB,UAAS;;EAYL,OAAA,OAAA,qCAAuB"}
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"}