@alfakit/core 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/components.css +19 -0
- package/dist/advanced-fields.d.ts +6 -0
- package/dist/advanced-fields.d.ts.map +1 -1
- package/dist/advanced-fields.js +20 -1
- package/dist/advanced-fields.js.map +1 -1
- package/dist/chart.d.ts.map +1 -1
- package/dist/chart.js +23 -15
- package/dist/chart.js.map +1 -1
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/conflicts.js +3 -5
- package/dist/conflicts.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/item-actions.d.ts +10 -0
- package/dist/item-actions.d.ts.map +1 -1
- package/dist/item-actions.js +8 -1
- package/dist/item-actions.js.map +1 -1
- package/dist/prefetch.d.ts.map +1 -1
- package/dist/prefetch.js +5 -2
- package/dist/prefetch.js.map +1 -1
- package/dist/presence.d.ts +0 -4
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +15 -2
- package/dist/presence.js.map +1 -1
- package/dist/schema/components.d.ts +5 -0
- package/dist/schema/components.d.ts.map +1 -1
- package/dist/schema/components.js.map +1 -1
- package/dist/schema/form.d.ts +2 -0
- package/dist/schema/form.d.ts.map +1 -1
- package/dist/schema/form.js.map +1 -1
- package/dist/starter-kit.d.ts.map +1 -1
- package/dist/starter-kit.js +17 -2
- package/dist/starter-kit.js.map +1 -1
- package/package.json +1 -1
|
@@ -539,6 +539,11 @@ export type ItemActionsSchema = Partial<Record<ItemActionName, ItemActionSchema
|
|
|
539
539
|
export interface ItemActionsProps {
|
|
540
540
|
/** Field-level built-in actions (item actions evaluated without an item). */
|
|
541
541
|
itemActions?: ItemActionsSchema;
|
|
542
|
+
/**
|
|
543
|
+
* `extraItemActions()` evaluated without an item (`$arguments['item']` null), for items
|
|
544
|
+
* the browser added since the last response; server-rendered items carry their own.
|
|
545
|
+
*/
|
|
546
|
+
extraItemActions?: ActionSchema[];
|
|
542
547
|
/** `reorderableWithButtons(false)`: no move up / down buttons. */
|
|
543
548
|
reorderableWithButtons?: boolean;
|
|
544
549
|
/** `reorderableWithDragAndDrop(false)`: no drag handle. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","names":[],"sources":["../../src/schema/components.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"components.d.ts","names":[],"sources":["../../src/schema/components.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","names":[],"sources":["../../src/schema/components.ts"],"sourcesContent":["import type { ActionSchema, AnyActionSchema } from './actions'\nimport type {\n BuilderSchema,\n CodeEditorSchema,\n ModalTableSelectSchema,\n SliderSchema,\n ToggleButtonsSchema,\n} from './advanced-fields'\nimport type {\n Alignment,\n Attributes,\n Breakpoints,\n Color,\n ColumnSpanValue,\n IconName,\n IconPosition,\n Operation,\n OptionOrGroup,\n Size,\n VirtualizeSchema,\n} from './common'\nimport type { FileManagerPickerSchema } from './file-manager'\nimport type { IconPickerSchema } from './icon-picker'\n\n/** Properties every schema component carries. */\nexport interface BaseComponent {\n type: string\n key: string\n id?: string\n label?: string | null\n disabled?: boolean\n columns?: Breakpoints\n columnSpan?: Breakpoints<ColumnSpanValue>\n columnStart?: Breakpoints<number | string | null>\n /** `columnOrder()`: CSS `order` in the parent grid, per breakpoint. */\n columnOrder?: Breakpoints<number | null>\n extraAttributes?: Attributes\n meta?: Record<string, unknown>\n /** `false` keeps the component at its natural width inside a `Flex`. */\n grow?: boolean\n /** Child components (layout containers). */\n schema?: SchemaComponent[]\n /** `dense()`: half the gap between the children (layout containers). */\n dense?: boolean\n /** `gap(false)`: no gap between the children (layout containers). */\n gap?: false\n /** `exposeContext()`: what a custom frontend component may read about its schema. */\n context?: SchemaComponentContext\n /**\n * `deferLoading()`: sent without its children on the page's first response; the\n * renderer loads them from `schemaDeferred` once the placeholder is in view.\n */\n deferred?: boolean\n /** State paths of the fields inside a deferred component (loaded early on errors). */\n deferredPaths?: string[]\n}\n\n/** Server-provided context of a component (`exposeContext()`), read with the renderers' context helper. */\nexport interface SchemaComponentContext {\n operation?: Operation | null\n recordKey?: string | number | null\n /** The record attributes listed in `exposeContext(record: [...])`. */\n record?: Record<string, unknown> | null\n /** `exposeContext(data: [...])`. */\n data?: Record<string, unknown> | null\n /** The state path of the component's container (e.g. `items.0` in a repeater item); relative `get()` paths start here. */\n basePath?: string | null\n}\n\nexport interface LiveConfig {\n onBlur: boolean\n debounce: number | null\n}\n\n/**\n * Actions attached to a field or entry: before (`prefixActions`) and after\n * (`suffixActions`) the control, and next to the label (`hintActions`). They run as field\n * actions (`field:{schema}::{key}`, see `fieldActionContext()`).\n */\nexport interface FieldActions {\n prefixActions?: ActionSchema[]\n suffixActions?: ActionSchema[]\n hintActions?: ActionSchema[]\n}\n\n/**\n * Content slots of a field or entry (`aboveLabel()`, `afterContent()`…). The error message\n * slots exist on fields only and show while the field has a validation error.\n */\nexport type ContentSlotName =\n | 'aboveLabel'\n | 'beforeLabel'\n | 'afterLabel'\n | 'belowLabel'\n | 'aboveContent'\n | 'beforeContent'\n | 'afterContent'\n | 'belowContent'\n | 'aboveErrorMessage'\n | 'belowErrorMessage'\n\n/**\n * One item of a content slot: a schema component (strings arrive as `Text`, `Htmlable`\n * values as `Html`) or an action / action group, run as a field action.\n */\nexport type ContentSlotItem =\n { component: SchemaComponent; action?: never } | { action: AnyActionSchema; component?: never }\n\nexport interface ContentSlotSchema {\n items: ContentSlotItem[]\n /** `afterLabel` defaults to `end`, every other slot to `start`. */\n alignment: 'start' | 'end' | 'between'\n}\n\nexport interface ContentSlots {\n slots?: Partial<Record<ContentSlotName, ContentSlotSchema>>\n}\n\n/** Properties every form field carries. */\nexport interface BaseField extends BaseComponent, FieldActions, ContentSlots {\n name: string\n statePath: string\n required?: boolean\n readOnly?: boolean\n autofocus?: boolean\n placeholder?: string\n helperText?: string\n /** HTML: plain strings are escaped by the server, `Htmlable` values are sent as is. */\n hint?: string\n hintIcon?: IconName\n hintColor?: Color\n /** `inlineLabel()`: the label sits beside the control from the `sm` breakpoint up. */\n inlineLabel?: boolean\n live?: LiveConfig\n extraInputAttributes?: Attributes\n /** Attributes for the `data-slot=\"field\"` wrapper, merged with `extraAttributes`. */\n extraFieldWrapperAttributes?: Attributes\n /** `allowHtmlValidationMessages()`: the error message is rendered as HTML. */\n allowHtmlValidationMessages?: boolean\n /**\n * `->translatable()`: the state is a `{ [locale code]: value }` object and the renderer\n * shows one input per language (see `translatableLocaleField()`).\n */\n translatable?: TranslatableSchema\n}\n\n/** A language of a translatable field. */\nexport interface TranslatableLocaleSchema {\n code: string\n /** BCP 47 tag for the `lang` attribute. */\n tag: string\n /** The language's own name. */\n label: string\n direction: 'ltr' | 'rtl'\n /** Must be filled when the field is required. */\n required?: boolean | null\n}\n\nexport interface TranslatableSchema {\n locales: TranslatableLocaleSchema[]\n defaultLocale: string\n}\n\nexport interface Affixes {\n prefix?: string\n suffix?: string\n prefixIcon?: IconName\n suffixIcon?: IconName\n prefixIconColor?: Color\n suffixIconColor?: Color\n}\n\n// ---------------------------------------------------------------- Fields\n\nexport interface TextInputSchema extends BaseField, Affixes {\n type: 'TextInput'\n inputType: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | (string & {})\n revealable?: boolean\n minLength?: number\n maxLength?: number\n min?: number\n max?: number\n step?: number | string\n mask?: string\n /** `autocomplete(false)` arrives as `off`. */\n autocomplete?: string\n inputMode?: string\n datalist?: string[]\n /** HTML `autocapitalize` hint (`on`, `off`, `none`, `sentences`, `words`, `characters`). */\n autocapitalize?: 'on' | 'off' | 'none' | 'sentences' | 'words' | 'characters' | (string & {})\n /** `copyable()`: a button in the input copies its value. */\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copied confirmation stays visible. */\n copyMessageDuration?: number\n}\n\nexport interface TextareaSchema extends BaseField {\n type: 'Textarea'\n rows?: number\n cols?: number\n minLength?: number\n maxLength?: number\n autosize?: boolean\n}\n\nexport interface HiddenSchema extends BaseField {\n type: 'Hidden'\n}\n\n/** `OneTimeCodeInput`: a numeric code with `autocomplete=\"one-time-code\"`. */\nexport interface OneTimeCodeInputSchema extends BaseField {\n type: 'OneTimeCodeInput'\n /** Number of digits. */\n length: number\n /** `submitOnCompletion()`: submit the form once every digit is entered. */\n submitOnCompletion?: boolean\n}\n\nexport interface CheckboxSchema extends BaseField {\n type: 'Checkbox'\n inline: boolean\n}\n\nexport interface ToggleSchema extends BaseField {\n type: 'Toggle'\n inline: boolean\n onIcon?: IconName\n offIcon?: IconName\n onColor?: Color\n offColor?: Color\n}\n\nexport interface SelectSchema extends BaseField, Affixes {\n type: 'Select'\n options: OptionOrGroup[]\n /** Labels for the currently selected values of a searchable select. */\n selectedLabels?: Record<string, string>\n multiple?: boolean\n searchable?: boolean\n native?: boolean\n selectablePlaceholder: boolean\n searchDebounce?: number\n noSearchResultsMessage?: string\n searchPrompt?: string\n loadingMessage?: string\n /** Shown when the select has no options at all. */\n noOptionsMessage?: string\n /** Shown while search results load. */\n searchingMessage?: string\n /** Option labels are HTML (sanitised by the server). */\n allowHtml?: boolean\n /** `false`: long option labels are truncated instead of wrapping. */\n wrapOptionLabels?: false\n maxItems?: number\n minItems?: number\n /** `reorderable()` on a multi-select: chosen chips can be reordered (drag or keyboard). */\n reorderable?: boolean\n}\n\nexport interface CheckboxListSchema extends BaseField {\n type: 'CheckboxList'\n options: OptionOrGroup[]\n searchable?: boolean\n /** `noSearchResultsMessage()`: shown when the search matches no option. */\n noSearchResultsMessage?: string\n /** `searchPrompt()`: placeholder of the search input. */\n searchPrompt?: string\n /** `searchDebounce()`: milliseconds to wait after typing before filtering. */\n searchDebounce?: number\n bulkToggleable?: boolean\n inline?: boolean\n gridColumns?: number\n /** `column` fills the grid column by column; row by row otherwise. */\n gridDirection?: OptionsGridDirection\n /** Option labels are HTML (sanitised by the server). */\n allowHtml?: boolean\n /** Customised bulk toggle links (`selectAllAction()` / `deselectAllAction()`). */\n selectAllAction?: BulkToggleActionSchema\n deselectAllAction?: BulkToggleActionSchema\n}\n\nexport type OptionsGridDirection = 'row' | 'column'\n\nexport interface BulkToggleActionSchema {\n label?: string\n icon?: IconName\n hidden?: boolean\n}\n\nexport interface RadioSchema extends BaseField {\n type: 'Radio'\n options: OptionOrGroup[]\n inline?: boolean\n}\n\nexport interface DatePickerSchema extends BaseField, Affixes {\n type: 'DatePicker' | 'DateTimePicker' | 'TimePicker'\n /** PHP date format of the stored value. */\n format: string\n displayFormat?: string\n hasDate: boolean\n hasTime: boolean\n hasSeconds?: boolean\n minDate?: string\n maxDate?: string\n disabledDates?: string[]\n native: boolean\n timezone: string\n firstDayOfWeek: number\n closeOnDateSelection: boolean\n /** Steps of the time inputs (`hoursStep()`, `minutesStep()`, `secondsStep()`). */\n hoursStep?: number\n minutesStep?: number\n secondsStep?: number\n /** The month the calendar opens on while empty, in the storage format. */\n defaultFocusedDate?: string\n /** `locale()`: BCP 47 tag for this picker's names and display format (the panel's otherwise). */\n locale?: string\n /** `datalist()`: suggested values in the storage format (native pickers only). */\n datalist?: string[]\n}\n\nexport interface MoneyInputSchema extends BaseField, Affixes {\n type: 'MoneyInput'\n /** ISO 4217 code. */\n currency: string\n /** Minor-unit digits of the currency (USD 2, BHD 3, JPY 0). */\n decimals: number\n min?: number\n max?: number\n}\n\nexport interface ColorPickerSchema extends BaseField {\n type: 'ColorPicker'\n format: 'hex' | 'rgb' | 'rgba' | 'hsl'\n}\n\nexport interface TagsInputSchema extends BaseField {\n type: 'TagsInput'\n suggestions?: string[]\n splitKeys: string[]\n color?: Color\n reorderable?: boolean\n tagPrefix?: string\n tagSuffix?: string\n}\n\nexport interface KeyValueSchema extends BaseField {\n type: 'KeyValue'\n keyLabel: string\n valueLabel: string\n keyPlaceholder?: string\n valuePlaceholder?: string\n addActionLabel: string\n addable: boolean\n deletable: boolean\n reorderable: boolean\n editableKeys: boolean\n editableValues: boolean\n /** `addAction()`, `deleteAction()`, `reorderAction()`; null = hidden. */\n itemActions?: Partial<Record<'add' | 'delete' | 'reorder', ItemActionSchema | null>>\n}\n\nexport interface UploadedFile {\n path: string\n name: string\n url?: string\n /** `getOpenableFileUrlUsing()`: where \"open\" links to, when not `url`. */\n openUrl?: string\n /** `getDownloadableFileUrlUsing()`: where \"download\" links to, when not `url`. */\n downloadUrl?: string\n /** `fetchFileInformation()`: the stored file no longer exists on its disk. */\n missing?: boolean\n temporary?: boolean\n size?: number\n}\n\n/** Logical sides of a file upload's controls (`removeUploadedFileButtonPosition()`…). */\nexport interface FileUploadPositions {\n removeButton?: 'start' | 'end'\n progressIndicator?: 'start' | 'end'\n uploadButton?: 'start' | 'center' | 'end'\n}\n\nexport interface FileUploadSchema extends BaseField {\n type: 'FileUpload'\n multiple?: boolean\n image?: boolean\n avatar?: boolean\n acceptedFileTypes?: string[]\n maxSize?: number\n minSize?: number\n /** Encrypted limits sent with each upload so the endpoint applies the field's `maxSize()`. */\n uploadPolicy?: string | null\n maxFiles?: number\n minFiles?: number\n downloadable?: boolean\n openable?: boolean\n previewable: boolean\n reorderable?: boolean\n deletable: boolean\n panelLayout: 'compact' | 'grid' | 'integrated' | 'circle' | (string & {})\n /** `panelAspectRatio()`: aspect ratio of the drop zone, e.g. `'2:1'`. */\n panelAspectRatio?: string\n imagePreviewHeight?: number | string\n /** `maxParallelUploads()`: files of one selection uploading at once (default 1). */\n maxParallelUploads?: number\n /** `appendFiles(false)`: new uploads go before the existing files. */\n appendFiles?: boolean\n /** `mimeTypeMap()`: extension → MIME type, for extensions browsers don't recognise. */\n mimeTypeMap?: Record<string, string>\n positions?: FileUploadPositions\n /** Images are cropped/resized in the browser before upload with these options. */\n imageCropAspectRatio?: string\n imageResizeMode?: 'cover' | 'contain' | 'force' | (string & {})\n imageResizeTargetWidth?: number\n imageResizeTargetHeight?: number\n uploadingMessage?: string\n /** `imageEditor()`: crop / rotate / flip each image before it is uploaded. */\n imageEditor?: FileUploadImageEditorSchema | null\n /** `imageAspectRatio()`: ratios the server accepts (checked on the file's pixels). */\n imageAspectRatio?: string[] | null\n /** `imageDimensions()`: pixel limits the server checks. */\n imageDimensions?: {\n minWidth?: number\n minHeight?: number\n maxWidth?: number\n maxHeight?: number\n } | null\n /** Re-encode JPEGs upright in the browser (sent only when the server can't do it). */\n orientImagesFromExif?: boolean | null\n /** `pasteable()`: accept files pasted while the drop zone has focus. */\n pasteable?: boolean\n files: UploadedFile[]\n}\n\nexport interface FileUploadImageEditorSchema {\n /** `'16:9'`-style ratios; `null` is free cropping. The first one is selected. */\n aspectRatios: Array<string | null>\n /** `circleCropper()`: a round viewport (the output stays square). */\n circle: boolean\n /** `imageEditorMode()` (Cropper.js `viewMode`): `0` lets the crop leave the image. */\n mode?: 0 | 1 | 2 | 3\n /** `imageEditorEmptyFillColor()`: colour of the empty space around the image. */\n emptyFillColor?: string | null\n /** `imageEditorViewportWidth()/Height()`: the crop ratio the editor opens with. */\n viewportWidth?: number | null\n viewportHeight?: number | null\n}\n\n/** A custom block a RichEditor can insert (`RichEditor::blocks()`). */\nexport interface RichEditorCustomBlockSchema {\n id: string\n label: string\n icon?: IconName\n /** The panel group (`customBlocks(['Marketing' => [...]])`). */\n group?: string\n /**\n * The field action (`customBlock:{id}`) that inserts the block: with a modal when the\n * block has a configuration form. It returns `{ id, config, preview }`.\n */\n action: ActionSchema\n}\n\n/** A mention trigger (`RichEditor::mentions()`). */\nexport interface RichEditorMentionSchema {\n /** The character that starts a mention, e.g. `@` or `#`. */\n trigger: string\n /** Static items; omitted when the server searches them (`getSearchResultsUsing`). */\n items?: Array<{ id: string; label: string }>\n /** Search on the server through the options endpoint as the user types. */\n searchable?: boolean\n searchDebounce?: number\n}\n\n/** A merge tag (`RichEditor::mergeTags()`), stored as `{{ id }}`. */\nexport interface RichEditorMergeTagSchema {\n id: string\n label: string\n}\n\n/** A toolbar dropdown (`ToolbarButtonGroup::make()`), referenced as `group:{n}` in a toolbar. */\nexport interface RichEditorToolbarGroupSchema {\n label: string\n /** Fixed trigger icon; without one the trigger shows the active (or first) button's icon. */\n icon?: IconName\n buttons: string[]\n /** `textualButtons()`: list the buttons with their labels. */\n textual?: boolean\n}\n\n/** A toolbar button from a rich content plugin (`RichEditorTool`). */\nexport interface RichEditorToolSchema {\n name: string\n label: string\n icon?: IconName\n /** Tiptap chain commands run on click: `[name, ...args]` each. */\n commands?: Array<[string, ...unknown[]]>\n /**\n * The plugin's editor action (opened with `editorSelection` and `attributes` arguments).\n * It may return `{ editorCommands, editorSelection }` (`RichEditor::runCommands()`).\n */\n action?: ActionSchema\n /** Pressed while this mark or node (with these attributes) is active. */\n active?: { name: string; attributes?: Record<string, unknown> }\n}\n\nexport interface RichEditorSchema extends BaseField {\n type: 'RichEditor' | 'MarkdownEditor'\n /** Button names, `'|'` separators and `group:{n}` dropdowns (see `toolbarButtonGroups`). */\n toolbarButtons: string[]\n toolbarButtonGroups?: Record<string, RichEditorToolbarGroupSchema> | null\n /**\n * `floatingToolbars()`: buttons shown next to the selection, keyed by node name\n * (`paragraph`, `heading`, `table`, `image`, …).\n */\n floatingToolbars?: Record<string, string[]> | null\n stickyToolbar?: boolean | null\n stickyPanels?: boolean | null\n /** CSS length; null measures the panel's sticky topbar. */\n stickyOffset?: string | null\n /** `resizableImages()`: drag handles; the width is stored on the image. */\n resizableImages?: boolean | null\n minimalCustomBlockControls?: boolean | null\n customBlocksGrid?: boolean | null\n searchableCustomBlocks?: boolean | null\n /** The panel open on load (`activePanel()`). */\n activePanel?: 'customBlocks' | 'mergeTags' | null\n /** Plugin toolbar buttons, usable by name in the toolbars. */\n editorTools?: RichEditorToolSchema[] | null\n /** Registry keys of plugin Tiptap extensions (`createAlfakit({ richEditorExtensions })`). */\n extensions?: string[] | null\n fileAttachments: {\n disk: string\n directory: string | null\n /** MIME types an inserted image may have; the server checks them on save. */\n acceptedFileTypes?: string[]\n /** Kilobytes. */\n maxSize?: number\n /** Encrypted limits sent with each upload (size and types of attachments). */\n uploadPolicy?: string | null\n }\n /** The `textColor` button's palette (`textColors()`); only sent with that button. */\n textColors?: Array<{ value: string; label: string }> | null\n /** `customTextColors()`: also offer a free colour picker. */\n customTextColors?: boolean | null\n minHeight?: number\n maxHeight?: number\n /**\n * `linkProtocols()`: URL schemes links may use (relative links always can); null keeps\n * the defaults. The server drops other links when the content is saved.\n */\n linkProtocols?: string[] | null\n /**\n * MarkdownEditor: the Markdown state rendered as HTML, which is what the editor loads.\n * A translatable editor gets one document per language code (see\n * `translatableLocaleField()`, which picks the current one).\n */\n html?: string | Record<string, string | null> | null\n /** RichEditor: the state is a Tiptap JSON document instead of HTML. */\n json?: boolean\n customBlocks?: RichEditorCustomBlockSchema[]\n mentions?: RichEditorMentionSchema[]\n mergeTags?: RichEditorMergeTagSchema[]\n}\n\n/** A column of a Repeater or RepeatableEntry shown as a table (`->table([...])`). */\nexport interface TableColumnSchema {\n label: string\n /** The item component the column shows: a field's relative state path or an entry's name. */\n name?: string\n hiddenLabel?: boolean\n required?: boolean\n /** CSS width, e.g. `200px` or `30%`. */\n width?: string\n alignment?: 'start' | 'center' | 'end'\n wrapHeader?: boolean\n}\n\n/** Built-in actions of a Repeater, Builder or KeyValue (`deleteAction(fn ($a) => …)`). */\nexport type ItemActionName =\n | 'add'\n | 'delete'\n | 'clone'\n | 'reorder'\n | 'moveUp'\n | 'moveDown'\n | 'collapse'\n | 'expand'\n | 'collapseAll'\n | 'expandAll'\n\n/**\n * A built-in item action. Without `server` the renderer applies it in the browser; with\n * it (customised with a modal, handler or hooks) it runs through the field action\n * endpoint with `arguments.item` (`items` for reorder, `block` for a Builder's add).\n */\nexport interface ItemActionSchema extends ActionSchema {\n server?: boolean\n}\n\n/** Customised built-in actions by name; null = hidden. Absent names use the renderer's default. */\nexport type ItemActionsSchema = Partial<Record<ItemActionName, ItemActionSchema | null>>\n\n/** Item action props shared by Repeater and Builder. */\nexport interface ItemActionsProps {\n /** Field-level built-in actions (item actions evaluated without an item). */\n itemActions?: ItemActionsSchema\n /** `reorderableWithButtons(false)`: no move up / down buttons. */\n reorderableWithButtons?: boolean\n /** `reorderableWithDragAndDrop(false)`: no drag handle. */\n reorderableWithDragAndDrop?: boolean\n addActionAlignment?: Alignment\n itemNumbers?: boolean\n}\n\n/** Per-item action props: customised built-ins for this item, `extraItemActions()`. */\nexport interface ItemActionsItemProps {\n itemActions?: ItemActionsSchema\n actions?: ActionSchema[]\n}\n\nexport interface RepeaterItemSchema extends ItemActionsItemProps {\n key: string\n label?: string | null\n schema: SchemaComponent[]\n}\n\nexport interface RepeaterSchema extends BaseField, ItemActionsProps {\n type: 'Repeater'\n items: RepeaterItemSchema[]\n /** Blank item schema; `__INDEX__` placeholders must be replaced with the new index. */\n template: SchemaComponent[]\n templateState: Record<string, unknown>\n simple?: boolean\n minItems?: number\n maxItems?: number\n addable: boolean\n deletable: boolean\n reorderable: boolean\n cloneable?: boolean\n collapsible?: boolean\n collapsed?: boolean\n addActionLabel: string\n grid?: Breakpoints\n /** Render items as table rows: one column per item field, in schema order. */\n table?: TableColumnSchema[]\n /** `compact()`: a table layout with tighter cells. */\n compact?: boolean\n /** Render only the visible items above a threshold (`virtualize()`, on by default). */\n virtualize?: VirtualizeSchema\n}\n\nexport type FieldSchema =\n | TextInputSchema\n | TextareaSchema\n | HiddenSchema\n | OneTimeCodeInputSchema\n | CheckboxSchema\n | ToggleSchema\n | SelectSchema\n | CheckboxListSchema\n | RadioSchema\n | DatePickerSchema\n | MoneyInputSchema\n | ColorPickerSchema\n | TagsInputSchema\n | KeyValueSchema\n | FileUploadSchema\n | RichEditorSchema\n | RepeaterSchema\n | BuilderSchema\n | ToggleButtonsSchema\n | SliderSchema\n | CodeEditorSchema\n | ModalTableSelectSchema\n | IconPickerSchema\n | FileManagerPickerSchema\n\nexport const FIELD_TYPES = [\n 'TextInput',\n 'Textarea',\n 'Hidden',\n 'OneTimeCodeInput',\n 'Checkbox',\n 'Toggle',\n 'Select',\n 'CheckboxList',\n 'Radio',\n 'DatePicker',\n 'DateTimePicker',\n 'MoneyInput',\n 'TimePicker',\n 'ColorPicker',\n 'TagsInput',\n 'KeyValue',\n 'FileUpload',\n 'RichEditor',\n 'MarkdownEditor',\n 'Repeater',\n 'Builder',\n 'ToggleButtons',\n 'Slider',\n 'CodeEditor',\n 'ModalTableSelect',\n 'IconPicker',\n // alfasix/alfakit-file-manager\n 'FileManagerPicker',\n] as const\n\nexport function isField(component: SchemaComponent): component is FieldSchema {\n return (\n 'statePath' in component &&\n typeof (component as BaseField).statePath === 'string' &&\n (FIELD_TYPES as readonly string[]).includes(component.type)\n )\n}\n\n// ---------------------------------------------------------------- Layout\n\nexport interface GridSchema extends BaseComponent {\n type: 'Grid'\n}\n\nexport interface GroupSchema extends BaseComponent {\n type: 'Group'\n}\n\n/**\n * Fields fused into one control (shared border, no gaps). Child labels become\n * screen-reader text and their errors are listed below the group.\n */\nexport interface FusedGroupSchema extends BaseComponent {\n type: 'FusedGroup'\n}\n\nexport interface SectionSchema extends BaseComponent {\n type: 'Section'\n heading?: string\n /** The heading's level (`2` = `h2`): `rootHeadingLevel()` plus the nesting depth. */\n headingLevel?: number\n description?: string\n icon?: IconName\n collapsible?: boolean\n collapsed?: boolean\n /** `persistCollapsed()`: the local storage key the collapsed state is kept under. */\n persistCollapsed?: string\n compact?: boolean\n aside?: boolean\n secondary?: boolean\n headerActions?: AnyActionSchema[]\n /** `afterHeader()`: actions and components at the end of the header. */\n afterHeader?: ContentSlotItem[]\n footerActions?: AnyActionSchema[]\n /** `footerActionsAlignment()`: alignment of `footerActions` (default `start`). */\n footerActionsAlignment?: Alignment\n /** `footer()`: actions and components in the footer, after `footerActions`. */\n footer?: ContentSlotItem[]\n}\n\nexport interface FieldsetSchema extends BaseComponent {\n type: 'Fieldset'\n /** `contained(false)`: no border or padding around the fields. */\n contained?: false\n}\n\nexport interface TabSchema extends BaseComponent {\n type: 'Tab'\n /**\n * The tab's readable value in the query string when its tabs `persistTabInQueryString()`:\n * its `id()`, explicit `key()` or label slug (`?tab=billing-address`).\n */\n queryValue?: string\n icon?: IconName\n iconPosition?: IconPosition\n badge?: string | number\n badgeColor?: Color\n /** `Tab::badgeTooltip()`: shown on hover (title) of the badge. */\n badgeTooltip?: string\n /** `deferBadge()`: the badge is loaded from `schemaDeferred` after the page renders. */\n badgeDeferred?: boolean\n}\n\n/** What `schemaDeferred` returns for a `Tab::deferBadge()` tab. */\nexport interface DeferredBadgeSchema {\n badge?: string | number | null\n badgeColor?: Color | null\n badgeTooltip?: string | null\n}\n\nexport interface TabsSchema extends BaseComponent {\n type: 'Tabs'\n schema: TabSchema[]\n activeTab: number\n contained?: boolean\n vertical?: boolean\n queryStringKey?: string\n /** `scrollable(false)`: the tab list wraps instead of scrolling sideways. */\n scrollable?: false\n /** `persistTab()`: where the active tab is remembered in the browser. */\n persistTab?: { key: string; storage: 'local' | 'session' }\n}\n\nexport interface StepSchema extends BaseComponent {\n type: 'Step'\n description?: string\n icon?: IconName\n /** Icon once the step is completed (falls back to the wizard's, then a check mark). */\n completedIcon?: IconName\n}\n\nexport interface WizardSchema extends BaseComponent {\n type: 'Wizard'\n schema: StepSchema[]\n startStep: number\n skippable?: boolean\n submitActionLabel?: string\n /** `submitAction(Action)`: rendered on the last step, runs through the action endpoint. */\n submitAction?: ActionSchema\n /** `submitAction(Htmlable)`: markup rendered on the last step. */\n submitActionHtml?: string\n nextActionLabel: string\n previousActionLabel: string\n /**\n * `nextAction(fn)` / `previousAction(fn)`: the button's appearance; `false` hides it.\n * Absent when not customised (the default buttons render).\n */\n nextAction?: ActionSchema | false\n previousAction?: ActionSchema | false\n completedIcon?: IconName\n /** Query-string key the current step is kept under (`true` from older servers = `step`). */\n persistStepInQueryString?: string | boolean\n /**\n * `goToStep()`: the server asked the wizard to show the step with this key. `id` is new\n * on every response, so the same step can be requested again.\n */\n goToStep?: { step: string; id: string }\n}\n\nexport interface PlaceholderSchema extends BaseComponent {\n type: 'Placeholder'\n content?: string\n helperText?: string\n}\n\nexport interface HtmlSchema extends BaseComponent {\n type: 'Html'\n content: string\n}\n\nexport interface TextSchema extends BaseComponent {\n type: 'Text'\n content: string\n color?: Color\n icon?: IconName\n size?: string\n weight?: string\n badge?: boolean\n /** `sans`, `serif` or `mono`. */\n fontFamily?: string\n tooltip?: string\n /** `copyable()`: a button copies `content` to the clipboard. */\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows. */\n copyMessageDuration?: number\n}\n\n/** A custom frontend component registered in the renderer. */\nexport interface ViewSchema extends BaseComponent {\n type: 'View'\n component: string\n props?: Record<string, unknown>\n}\n\n/** Children side by side, stacked below the `from` breakpoint. */\nexport interface FlexSchema extends BaseComponent {\n type: 'Flex'\n from: 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n verticalAlignment?: 'start' | 'center' | 'end'\n /** `alignment()`: horizontal alignment of the children (`justify` spreads them like `between`). */\n alignment?: Alignment\n}\n\n/** A highlighted message box. `description` is HTML (plain strings escaped by the server). */\nexport interface CalloutSchema extends BaseComponent {\n type: 'Callout'\n heading?: string\n description?: string\n icon?: IconName\n /** `iconSize()`: `sm`, `md` or `lg` (default). */\n iconSize?: Size\n color?: Color\n /**\n * `status()` / `danger()`…: kept after `color(null)` so the icon keeps its status colour\n * and danger/warning callouts keep `role=\"alert\"`.\n */\n status?: Color\n /** `iconColor()`: overrides the icon's colour. */\n iconColor?: Color\n actions?: AnyActionSchema[]\n /** `footerActionsAlignment()`: alignment of `actions` (default `start`). */\n footerActionsAlignment?: Alignment\n /** `controls()` and `controlActions()`: shown in the top end corner. */\n controls?: ContentSlotItem[]\n /** `footer()`: actions and components under the description. */\n footer?: ContentSlotItem[]\n}\n\n/**\n * A row of action buttons placed freely in a form or infolist. The actions run in the\n * component's field context (`field:{schema}::{key}`), like a field's suffix actions.\n */\nexport interface ActionsComponentSchema extends BaseComponent {\n type: 'Actions'\n actions: AnyActionSchema[]\n alignment?: Alignment\n verticalAlignment?: 'start' | 'center' | 'end'\n fullWidth?: boolean\n}\n\n/** Placeholder for missing content. `description` is HTML (escaped by the server). */\nexport interface EmptyStateComponentSchema extends BaseComponent {\n type: 'EmptyState'\n heading?: string\n description?: string\n icon?: IconName\n color?: Color\n contained: boolean\n actions?: AnyActionSchema[]\n /** `footer()`: actions and components under the description (after `actions`). */\n footer?: ContentSlotItem[]\n}\n\nexport interface IconSchema extends BaseComponent {\n type: 'Icon'\n icon: IconName\n color?: Color\n size?: Size | string\n tooltip?: string\n}\n\nexport interface ImageSchema extends BaseComponent {\n type: 'Image'\n url: string\n alt: string\n /** CSS lengths. */\n imageWidth?: string\n imageHeight?: string\n alignment?: Alignment\n circular?: boolean\n tooltip?: string\n}\n\n/** A bulleted list; every child component is one item. */\nexport interface UnorderedListSchema extends BaseComponent {\n type: 'UnorderedList'\n size?: Size | string\n}\n\nexport type LayoutSchema =\n | FlexSchema\n | CalloutSchema\n | ActionsComponentSchema\n | EmptyStateComponentSchema\n | IconSchema\n | ImageSchema\n | UnorderedListSchema\n | GridSchema\n | GroupSchema\n | FusedGroupSchema\n | SectionSchema\n | FieldsetSchema\n | TabsSchema\n | TabSchema\n | WizardSchema\n | StepSchema\n | PlaceholderSchema\n | HtmlSchema\n | TextSchema\n | ViewSchema\n\n// ---------------------------------------------------------------- Infolist entries\n\nexport interface BaseEntry extends BaseComponent, FieldActions, ContentSlots {\n name: string\n state?: unknown\n url?: string\n openUrlInNewTab?: boolean\n tooltip?: string\n helperText?: string\n /** HTML: plain strings are escaped by the server, `Htmlable` values are sent as is. */\n hint?: string\n hintIcon?: IconName\n hintColor?: Color\n placeholder?: string\n /** `inlineLabel()`: the label sits beside the value from the `sm` breakpoint up. */\n inlineLabel?: boolean\n /**\n * Attributes for the `data-slot=\"entry\"` wrapper. `extraAttributes` go on the value\n * (`data-slot=\"entry-value\"`).\n */\n extraEntryWrapperAttributes?: Attributes\n /** `alignment()`: horizontal alignment of the value. */\n alignment?: Alignment\n}\n\nexport interface TextStyleProps {\n size?: string\n weight?: string\n fontFamily?: string\n lineClamp?: number\n badge?: boolean\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows (`copyMessageDuration()`, default 1500). */\n copyMessageDuration?: number\n wrap?: boolean\n}\n\nexport interface FormattedStateProps {\n html?: boolean\n listWithLineBreaks?: boolean\n bulleted?: boolean\n placeholder?: string\n boolean?: boolean\n /**\n * `limitList()` + `expandableLimitedList()`: every item is sent; the first `listLimit`\n * show with a \"+N more\" toggle for the rest.\n */\n expandableLimitedList?: boolean\n listLimit?: number\n}\n\n/** `ring()` / `overlap()` / `extraImgAttributes()` of image columns and entries. */\nexport interface ImageStackProps {\n /** Ring width in pixels around stacked images (0–8, default 2). */\n ring?: number\n /** Overlap of stacked images in quarter rems (0–8, default 2). */\n overlap?: number\n}\n\nexport interface TextEntrySchema extends BaseEntry, TextStyleProps, FormattedStateProps {\n type: 'TextEntry'\n state?: string | number | boolean | Array<string | number> | null\n color?: Color\n icon?: IconName\n iconPosition?: IconPosition\n iconColor?: Color\n /** Per-item colours of a list state (enums whose items differ), aligned with the items. */\n itemColors?: Array<Color | null>\n /** Per-item icons of a list state, aligned with the items. */\n itemIcons?: Array<IconName | null>\n /** Per-item links of a relationship list (`tags.name` with a `url()` closure). */\n itemUrls?: Array<string | null>\n prose?: boolean\n}\n\nexport interface IconEntrySchema extends BaseEntry {\n type: 'IconEntry'\n icon?: IconName\n color?: Color\n size?: Size | string\n}\n\nexport interface ImageEntrySchema extends BaseEntry, ImageStackProps {\n type: 'ImageEntry'\n /** HTML attributes for every `<img>` (`extraImgAttributes()`). */\n extraImgAttributes?: Attributes\n state?: string[]\n circular?: boolean\n square?: boolean\n size?: number | string\n height?: number | string\n width?: number | string\n stacked?: boolean\n limit?: number\n /** `limitedRemainingText(false)` hides the \"+N\" of images past `limit` (shown by default). */\n limitedRemainingText?: boolean\n /** Text size of the \"+N\" (`limitedRemainingText(size:)`). */\n limitedRemainingTextSize?: 'xs' | 'sm' | 'md' | 'lg'\n /** Alternative text shared by every image. */\n alt?: string\n /** Alternative text per image, aligned with `state`, when a closure gives different texts. */\n alts?: Array<string | null>\n}\n\n/** Highlighted read-only code. Array state arrives as pretty-printed JSON. */\nexport interface CodeEntrySchema extends BaseEntry {\n type: 'CodeEntry'\n state?: string | null\n /** Highlighting grammar (`json`, `php`, `js`…); unknown grammars render as plain code. */\n grammar?: string\n /** Theme names exposed to CSS as `data-light-theme` / `data-dark-theme`. */\n lightTheme?: string\n darkTheme?: string\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows. */\n copyMessageDuration?: number\n}\n\nexport interface ColorEntrySchema extends BaseEntry, TextStyleProps {\n type: 'ColorEntry'\n state?: string | string[] | null\n}\n\nexport interface KeyValueEntrySchema extends BaseEntry {\n type: 'KeyValueEntry'\n state?: Record<string, unknown>\n keyLabel: string\n valueLabel: string\n}\n\nexport interface RepeatableEntrySchema extends BaseEntry {\n type: 'RepeatableEntry'\n items: SchemaComponent[][]\n contained: boolean\n grid?: Breakpoints\n /** Render items as table rows: one column per item entry, in schema order. */\n table?: TableColumnSchema[]\n}\n\n/** An entry rendered by an application component registered under `component`. */\nexport interface ViewEntrySchema extends BaseEntry {\n type: 'ViewEntry'\n component?: string\n props?: Record<string, unknown>\n}\n\nexport type EntrySchema =\n | ViewEntrySchema\n | TextEntrySchema\n | IconEntrySchema\n | ImageEntrySchema\n | CodeEntrySchema\n | ColorEntrySchema\n | KeyValueEntrySchema\n | RepeatableEntrySchema\n\nexport type SchemaComponent =\n FieldSchema | LayoutSchema | EntrySchema | (BaseComponent & { type: string })\n\nexport type { Alignment }\n"],"mappings":";AAwqBA,MAAa,cAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;AACF;AAEA,SAAgB,QAAQ,WAAsD;CAC5E,OACE,eAAe,aACf,OAAQ,UAAwB,cAAc,YAC7C,YAAkC,SAAS,UAAU,IAAI;AAE9D"}
|
|
1
|
+
{"version":3,"file":"components.js","names":[],"sources":["../../src/schema/components.ts"],"sourcesContent":["import type { ActionSchema, AnyActionSchema } from './actions'\nimport type {\n BuilderSchema,\n CodeEditorSchema,\n ModalTableSelectSchema,\n SliderSchema,\n ToggleButtonsSchema,\n} from './advanced-fields'\nimport type {\n Alignment,\n Attributes,\n Breakpoints,\n Color,\n ColumnSpanValue,\n IconName,\n IconPosition,\n Operation,\n OptionOrGroup,\n Size,\n VirtualizeSchema,\n} from './common'\nimport type { FileManagerPickerSchema } from './file-manager'\nimport type { IconPickerSchema } from './icon-picker'\n\n/** Properties every schema component carries. */\nexport interface BaseComponent {\n type: string\n key: string\n id?: string\n label?: string | null\n disabled?: boolean\n columns?: Breakpoints\n columnSpan?: Breakpoints<ColumnSpanValue>\n columnStart?: Breakpoints<number | string | null>\n /** `columnOrder()`: CSS `order` in the parent grid, per breakpoint. */\n columnOrder?: Breakpoints<number | null>\n extraAttributes?: Attributes\n meta?: Record<string, unknown>\n /** `false` keeps the component at its natural width inside a `Flex`. */\n grow?: boolean\n /** Child components (layout containers). */\n schema?: SchemaComponent[]\n /** `dense()`: half the gap between the children (layout containers). */\n dense?: boolean\n /** `gap(false)`: no gap between the children (layout containers). */\n gap?: false\n /** `exposeContext()`: what a custom frontend component may read about its schema. */\n context?: SchemaComponentContext\n /**\n * `deferLoading()`: sent without its children on the page's first response; the\n * renderer loads them from `schemaDeferred` once the placeholder is in view.\n */\n deferred?: boolean\n /** State paths of the fields inside a deferred component (loaded early on errors). */\n deferredPaths?: string[]\n}\n\n/** Server-provided context of a component (`exposeContext()`), read with the renderers' context helper. */\nexport interface SchemaComponentContext {\n operation?: Operation | null\n recordKey?: string | number | null\n /** The record attributes listed in `exposeContext(record: [...])`. */\n record?: Record<string, unknown> | null\n /** `exposeContext(data: [...])`. */\n data?: Record<string, unknown> | null\n /** The state path of the component's container (e.g. `items.0` in a repeater item); relative `get()` paths start here. */\n basePath?: string | null\n}\n\nexport interface LiveConfig {\n onBlur: boolean\n debounce: number | null\n}\n\n/**\n * Actions attached to a field or entry: before (`prefixActions`) and after\n * (`suffixActions`) the control, and next to the label (`hintActions`). They run as field\n * actions (`field:{schema}::{key}`, see `fieldActionContext()`).\n */\nexport interface FieldActions {\n prefixActions?: ActionSchema[]\n suffixActions?: ActionSchema[]\n hintActions?: ActionSchema[]\n}\n\n/**\n * Content slots of a field or entry (`aboveLabel()`, `afterContent()`…). The error message\n * slots exist on fields only and show while the field has a validation error.\n */\nexport type ContentSlotName =\n | 'aboveLabel'\n | 'beforeLabel'\n | 'afterLabel'\n | 'belowLabel'\n | 'aboveContent'\n | 'beforeContent'\n | 'afterContent'\n | 'belowContent'\n | 'aboveErrorMessage'\n | 'belowErrorMessage'\n\n/**\n * One item of a content slot: a schema component (strings arrive as `Text`, `Htmlable`\n * values as `Html`) or an action / action group, run as a field action.\n */\nexport type ContentSlotItem =\n { component: SchemaComponent; action?: never } | { action: AnyActionSchema; component?: never }\n\nexport interface ContentSlotSchema {\n items: ContentSlotItem[]\n /** `afterLabel` defaults to `end`, every other slot to `start`. */\n alignment: 'start' | 'end' | 'between'\n}\n\nexport interface ContentSlots {\n slots?: Partial<Record<ContentSlotName, ContentSlotSchema>>\n}\n\n/** Properties every form field carries. */\nexport interface BaseField extends BaseComponent, FieldActions, ContentSlots {\n name: string\n statePath: string\n required?: boolean\n readOnly?: boolean\n autofocus?: boolean\n placeholder?: string\n helperText?: string\n /** HTML: plain strings are escaped by the server, `Htmlable` values are sent as is. */\n hint?: string\n hintIcon?: IconName\n hintColor?: Color\n /** `inlineLabel()`: the label sits beside the control from the `sm` breakpoint up. */\n inlineLabel?: boolean\n live?: LiveConfig\n extraInputAttributes?: Attributes\n /** Attributes for the `data-slot=\"field\"` wrapper, merged with `extraAttributes`. */\n extraFieldWrapperAttributes?: Attributes\n /** `allowHtmlValidationMessages()`: the error message is rendered as HTML. */\n allowHtmlValidationMessages?: boolean\n /**\n * `->translatable()`: the state is a `{ [locale code]: value }` object and the renderer\n * shows one input per language (see `translatableLocaleField()`).\n */\n translatable?: TranslatableSchema\n}\n\n/** A language of a translatable field. */\nexport interface TranslatableLocaleSchema {\n code: string\n /** BCP 47 tag for the `lang` attribute. */\n tag: string\n /** The language's own name. */\n label: string\n direction: 'ltr' | 'rtl'\n /** Must be filled when the field is required. */\n required?: boolean | null\n}\n\nexport interface TranslatableSchema {\n locales: TranslatableLocaleSchema[]\n defaultLocale: string\n}\n\nexport interface Affixes {\n prefix?: string\n suffix?: string\n prefixIcon?: IconName\n suffixIcon?: IconName\n prefixIconColor?: Color\n suffixIconColor?: Color\n}\n\n// ---------------------------------------------------------------- Fields\n\nexport interface TextInputSchema extends BaseField, Affixes {\n type: 'TextInput'\n inputType: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | (string & {})\n revealable?: boolean\n minLength?: number\n maxLength?: number\n min?: number\n max?: number\n step?: number | string\n mask?: string\n /** `autocomplete(false)` arrives as `off`. */\n autocomplete?: string\n inputMode?: string\n datalist?: string[]\n /** HTML `autocapitalize` hint (`on`, `off`, `none`, `sentences`, `words`, `characters`). */\n autocapitalize?: 'on' | 'off' | 'none' | 'sentences' | 'words' | 'characters' | (string & {})\n /** `copyable()`: a button in the input copies its value. */\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copied confirmation stays visible. */\n copyMessageDuration?: number\n}\n\nexport interface TextareaSchema extends BaseField {\n type: 'Textarea'\n rows?: number\n cols?: number\n minLength?: number\n maxLength?: number\n autosize?: boolean\n}\n\nexport interface HiddenSchema extends BaseField {\n type: 'Hidden'\n}\n\n/** `OneTimeCodeInput`: a numeric code with `autocomplete=\"one-time-code\"`. */\nexport interface OneTimeCodeInputSchema extends BaseField {\n type: 'OneTimeCodeInput'\n /** Number of digits. */\n length: number\n /** `submitOnCompletion()`: submit the form once every digit is entered. */\n submitOnCompletion?: boolean\n}\n\nexport interface CheckboxSchema extends BaseField {\n type: 'Checkbox'\n inline: boolean\n}\n\nexport interface ToggleSchema extends BaseField {\n type: 'Toggle'\n inline: boolean\n onIcon?: IconName\n offIcon?: IconName\n onColor?: Color\n offColor?: Color\n}\n\nexport interface SelectSchema extends BaseField, Affixes {\n type: 'Select'\n options: OptionOrGroup[]\n /** Labels for the currently selected values of a searchable select. */\n selectedLabels?: Record<string, string>\n multiple?: boolean\n searchable?: boolean\n native?: boolean\n selectablePlaceholder: boolean\n searchDebounce?: number\n noSearchResultsMessage?: string\n searchPrompt?: string\n loadingMessage?: string\n /** Shown when the select has no options at all. */\n noOptionsMessage?: string\n /** Shown while search results load. */\n searchingMessage?: string\n /** Option labels are HTML (sanitised by the server). */\n allowHtml?: boolean\n /** `false`: long option labels are truncated instead of wrapping. */\n wrapOptionLabels?: false\n maxItems?: number\n minItems?: number\n /** `reorderable()` on a multi-select: chosen chips can be reordered (drag or keyboard). */\n reorderable?: boolean\n}\n\nexport interface CheckboxListSchema extends BaseField {\n type: 'CheckboxList'\n options: OptionOrGroup[]\n searchable?: boolean\n /** `noSearchResultsMessage()`: shown when the search matches no option. */\n noSearchResultsMessage?: string\n /** `searchPrompt()`: placeholder of the search input. */\n searchPrompt?: string\n /** `searchDebounce()`: milliseconds to wait after typing before filtering. */\n searchDebounce?: number\n bulkToggleable?: boolean\n inline?: boolean\n gridColumns?: number\n /** `column` fills the grid column by column; row by row otherwise. */\n gridDirection?: OptionsGridDirection\n /** Option labels are HTML (sanitised by the server). */\n allowHtml?: boolean\n /** Customised bulk toggle links (`selectAllAction()` / `deselectAllAction()`). */\n selectAllAction?: BulkToggleActionSchema\n deselectAllAction?: BulkToggleActionSchema\n}\n\nexport type OptionsGridDirection = 'row' | 'column'\n\nexport interface BulkToggleActionSchema {\n label?: string\n icon?: IconName\n hidden?: boolean\n}\n\nexport interface RadioSchema extends BaseField {\n type: 'Radio'\n options: OptionOrGroup[]\n inline?: boolean\n}\n\nexport interface DatePickerSchema extends BaseField, Affixes {\n type: 'DatePicker' | 'DateTimePicker' | 'TimePicker'\n /** PHP date format of the stored value. */\n format: string\n displayFormat?: string\n hasDate: boolean\n hasTime: boolean\n hasSeconds?: boolean\n minDate?: string\n maxDate?: string\n disabledDates?: string[]\n native: boolean\n timezone: string\n firstDayOfWeek: number\n closeOnDateSelection: boolean\n /** Steps of the time inputs (`hoursStep()`, `minutesStep()`, `secondsStep()`). */\n hoursStep?: number\n minutesStep?: number\n secondsStep?: number\n /** The month the calendar opens on while empty, in the storage format. */\n defaultFocusedDate?: string\n /** `locale()`: BCP 47 tag for this picker's names and display format (the panel's otherwise). */\n locale?: string\n /** `datalist()`: suggested values in the storage format (native pickers only). */\n datalist?: string[]\n}\n\nexport interface MoneyInputSchema extends BaseField, Affixes {\n type: 'MoneyInput'\n /** ISO 4217 code. */\n currency: string\n /** Minor-unit digits of the currency (USD 2, BHD 3, JPY 0). */\n decimals: number\n min?: number\n max?: number\n}\n\nexport interface ColorPickerSchema extends BaseField {\n type: 'ColorPicker'\n format: 'hex' | 'rgb' | 'rgba' | 'hsl'\n}\n\nexport interface TagsInputSchema extends BaseField {\n type: 'TagsInput'\n suggestions?: string[]\n splitKeys: string[]\n color?: Color\n reorderable?: boolean\n tagPrefix?: string\n tagSuffix?: string\n}\n\nexport interface KeyValueSchema extends BaseField {\n type: 'KeyValue'\n keyLabel: string\n valueLabel: string\n keyPlaceholder?: string\n valuePlaceholder?: string\n addActionLabel: string\n addable: boolean\n deletable: boolean\n reorderable: boolean\n editableKeys: boolean\n editableValues: boolean\n /** `addAction()`, `deleteAction()`, `reorderAction()`; null = hidden. */\n itemActions?: Partial<Record<'add' | 'delete' | 'reorder', ItemActionSchema | null>>\n}\n\nexport interface UploadedFile {\n path: string\n name: string\n url?: string\n /** `getOpenableFileUrlUsing()`: where \"open\" links to, when not `url`. */\n openUrl?: string\n /** `getDownloadableFileUrlUsing()`: where \"download\" links to, when not `url`. */\n downloadUrl?: string\n /** `fetchFileInformation()`: the stored file no longer exists on its disk. */\n missing?: boolean\n temporary?: boolean\n size?: number\n}\n\n/** Logical sides of a file upload's controls (`removeUploadedFileButtonPosition()`…). */\nexport interface FileUploadPositions {\n removeButton?: 'start' | 'end'\n progressIndicator?: 'start' | 'end'\n uploadButton?: 'start' | 'center' | 'end'\n}\n\nexport interface FileUploadSchema extends BaseField {\n type: 'FileUpload'\n multiple?: boolean\n image?: boolean\n avatar?: boolean\n acceptedFileTypes?: string[]\n maxSize?: number\n minSize?: number\n /** Encrypted limits sent with each upload so the endpoint applies the field's `maxSize()`. */\n uploadPolicy?: string | null\n maxFiles?: number\n minFiles?: number\n downloadable?: boolean\n openable?: boolean\n previewable: boolean\n reorderable?: boolean\n deletable: boolean\n panelLayout: 'compact' | 'grid' | 'integrated' | 'circle' | (string & {})\n /** `panelAspectRatio()`: aspect ratio of the drop zone, e.g. `'2:1'`. */\n panelAspectRatio?: string\n imagePreviewHeight?: number | string\n /** `maxParallelUploads()`: files of one selection uploading at once (default 1). */\n maxParallelUploads?: number\n /** `appendFiles(false)`: new uploads go before the existing files. */\n appendFiles?: boolean\n /** `mimeTypeMap()`: extension → MIME type, for extensions browsers don't recognise. */\n mimeTypeMap?: Record<string, string>\n positions?: FileUploadPositions\n /** Images are cropped/resized in the browser before upload with these options. */\n imageCropAspectRatio?: string\n imageResizeMode?: 'cover' | 'contain' | 'force' | (string & {})\n imageResizeTargetWidth?: number\n imageResizeTargetHeight?: number\n uploadingMessage?: string\n /** `imageEditor()`: crop / rotate / flip each image before it is uploaded. */\n imageEditor?: FileUploadImageEditorSchema | null\n /** `imageAspectRatio()`: ratios the server accepts (checked on the file's pixels). */\n imageAspectRatio?: string[] | null\n /** `imageDimensions()`: pixel limits the server checks. */\n imageDimensions?: {\n minWidth?: number\n minHeight?: number\n maxWidth?: number\n maxHeight?: number\n } | null\n /** Re-encode JPEGs upright in the browser (sent only when the server can't do it). */\n orientImagesFromExif?: boolean | null\n /** `pasteable()`: accept files pasted while the drop zone has focus. */\n pasteable?: boolean\n files: UploadedFile[]\n}\n\nexport interface FileUploadImageEditorSchema {\n /** `'16:9'`-style ratios; `null` is free cropping. The first one is selected. */\n aspectRatios: Array<string | null>\n /** `circleCropper()`: a round viewport (the output stays square). */\n circle: boolean\n /** `imageEditorMode()` (Cropper.js `viewMode`): `0` lets the crop leave the image. */\n mode?: 0 | 1 | 2 | 3\n /** `imageEditorEmptyFillColor()`: colour of the empty space around the image. */\n emptyFillColor?: string | null\n /** `imageEditorViewportWidth()/Height()`: the crop ratio the editor opens with. */\n viewportWidth?: number | null\n viewportHeight?: number | null\n}\n\n/** A custom block a RichEditor can insert (`RichEditor::blocks()`). */\nexport interface RichEditorCustomBlockSchema {\n id: string\n label: string\n icon?: IconName\n /** The panel group (`customBlocks(['Marketing' => [...]])`). */\n group?: string\n /**\n * The field action (`customBlock:{id}`) that inserts the block: with a modal when the\n * block has a configuration form. It returns `{ id, config, preview }`.\n */\n action: ActionSchema\n}\n\n/** A mention trigger (`RichEditor::mentions()`). */\nexport interface RichEditorMentionSchema {\n /** The character that starts a mention, e.g. `@` or `#`. */\n trigger: string\n /** Static items; omitted when the server searches them (`getSearchResultsUsing`). */\n items?: Array<{ id: string; label: string }>\n /** Search on the server through the options endpoint as the user types. */\n searchable?: boolean\n searchDebounce?: number\n}\n\n/** A merge tag (`RichEditor::mergeTags()`), stored as `{{ id }}`. */\nexport interface RichEditorMergeTagSchema {\n id: string\n label: string\n}\n\n/** A toolbar dropdown (`ToolbarButtonGroup::make()`), referenced as `group:{n}` in a toolbar. */\nexport interface RichEditorToolbarGroupSchema {\n label: string\n /** Fixed trigger icon; without one the trigger shows the active (or first) button's icon. */\n icon?: IconName\n buttons: string[]\n /** `textualButtons()`: list the buttons with their labels. */\n textual?: boolean\n}\n\n/** A toolbar button from a rich content plugin (`RichEditorTool`). */\nexport interface RichEditorToolSchema {\n name: string\n label: string\n icon?: IconName\n /** Tiptap chain commands run on click: `[name, ...args]` each. */\n commands?: Array<[string, ...unknown[]]>\n /**\n * The plugin's editor action (opened with `editorSelection` and `attributes` arguments).\n * It may return `{ editorCommands, editorSelection }` (`RichEditor::runCommands()`).\n */\n action?: ActionSchema\n /** Pressed while this mark or node (with these attributes) is active. */\n active?: { name: string; attributes?: Record<string, unknown> }\n}\n\nexport interface RichEditorSchema extends BaseField {\n type: 'RichEditor' | 'MarkdownEditor'\n /** Button names, `'|'` separators and `group:{n}` dropdowns (see `toolbarButtonGroups`). */\n toolbarButtons: string[]\n toolbarButtonGroups?: Record<string, RichEditorToolbarGroupSchema> | null\n /**\n * `floatingToolbars()`: buttons shown next to the selection, keyed by node name\n * (`paragraph`, `heading`, `table`, `image`, …).\n */\n floatingToolbars?: Record<string, string[]> | null\n stickyToolbar?: boolean | null\n stickyPanels?: boolean | null\n /** CSS length; null measures the panel's sticky topbar. */\n stickyOffset?: string | null\n /** `resizableImages()`: drag handles; the width is stored on the image. */\n resizableImages?: boolean | null\n minimalCustomBlockControls?: boolean | null\n customBlocksGrid?: boolean | null\n searchableCustomBlocks?: boolean | null\n /** The panel open on load (`activePanel()`). */\n activePanel?: 'customBlocks' | 'mergeTags' | null\n /** Plugin toolbar buttons, usable by name in the toolbars. */\n editorTools?: RichEditorToolSchema[] | null\n /** Registry keys of plugin Tiptap extensions (`createAlfakit({ richEditorExtensions })`). */\n extensions?: string[] | null\n fileAttachments: {\n disk: string\n directory: string | null\n /** MIME types an inserted image may have; the server checks them on save. */\n acceptedFileTypes?: string[]\n /** Kilobytes. */\n maxSize?: number\n /** Encrypted limits sent with each upload (size and types of attachments). */\n uploadPolicy?: string | null\n }\n /** The `textColor` button's palette (`textColors()`); only sent with that button. */\n textColors?: Array<{ value: string; label: string }> | null\n /** `customTextColors()`: also offer a free colour picker. */\n customTextColors?: boolean | null\n minHeight?: number\n maxHeight?: number\n /**\n * `linkProtocols()`: URL schemes links may use (relative links always can); null keeps\n * the defaults. The server drops other links when the content is saved.\n */\n linkProtocols?: string[] | null\n /**\n * MarkdownEditor: the Markdown state rendered as HTML, which is what the editor loads.\n * A translatable editor gets one document per language code (see\n * `translatableLocaleField()`, which picks the current one).\n */\n html?: string | Record<string, string | null> | null\n /** RichEditor: the state is a Tiptap JSON document instead of HTML. */\n json?: boolean\n customBlocks?: RichEditorCustomBlockSchema[]\n mentions?: RichEditorMentionSchema[]\n mergeTags?: RichEditorMergeTagSchema[]\n}\n\n/** A column of a Repeater or RepeatableEntry shown as a table (`->table([...])`). */\nexport interface TableColumnSchema {\n label: string\n /** The item component the column shows: a field's relative state path or an entry's name. */\n name?: string\n hiddenLabel?: boolean\n required?: boolean\n /** CSS width, e.g. `200px` or `30%`. */\n width?: string\n alignment?: 'start' | 'center' | 'end'\n wrapHeader?: boolean\n}\n\n/** Built-in actions of a Repeater, Builder or KeyValue (`deleteAction(fn ($a) => …)`). */\nexport type ItemActionName =\n | 'add'\n | 'delete'\n | 'clone'\n | 'reorder'\n | 'moveUp'\n | 'moveDown'\n | 'collapse'\n | 'expand'\n | 'collapseAll'\n | 'expandAll'\n\n/**\n * A built-in item action. Without `server` the renderer applies it in the browser; with\n * it (customised with a modal, handler or hooks) it runs through the field action\n * endpoint with `arguments.item` (`items` for reorder, `block` for a Builder's add).\n */\nexport interface ItemActionSchema extends ActionSchema {\n server?: boolean\n}\n\n/** Customised built-in actions by name; null = hidden. Absent names use the renderer's default. */\nexport type ItemActionsSchema = Partial<Record<ItemActionName, ItemActionSchema | null>>\n\n/** Item action props shared by Repeater and Builder. */\nexport interface ItemActionsProps {\n /** Field-level built-in actions (item actions evaluated without an item). */\n itemActions?: ItemActionsSchema\n /**\n * `extraItemActions()` evaluated without an item (`$arguments['item']` null), for items\n * the browser added since the last response; server-rendered items carry their own.\n */\n extraItemActions?: ActionSchema[]\n /** `reorderableWithButtons(false)`: no move up / down buttons. */\n reorderableWithButtons?: boolean\n /** `reorderableWithDragAndDrop(false)`: no drag handle. */\n reorderableWithDragAndDrop?: boolean\n addActionAlignment?: Alignment\n itemNumbers?: boolean\n}\n\n/** Per-item action props: customised built-ins for this item, `extraItemActions()`. */\nexport interface ItemActionsItemProps {\n itemActions?: ItemActionsSchema\n actions?: ActionSchema[]\n}\n\nexport interface RepeaterItemSchema extends ItemActionsItemProps {\n key: string\n label?: string | null\n schema: SchemaComponent[]\n}\n\nexport interface RepeaterSchema extends BaseField, ItemActionsProps {\n type: 'Repeater'\n items: RepeaterItemSchema[]\n /** Blank item schema; `__INDEX__` placeholders must be replaced with the new index. */\n template: SchemaComponent[]\n templateState: Record<string, unknown>\n simple?: boolean\n minItems?: number\n maxItems?: number\n addable: boolean\n deletable: boolean\n reorderable: boolean\n cloneable?: boolean\n collapsible?: boolean\n collapsed?: boolean\n addActionLabel: string\n grid?: Breakpoints\n /** Render items as table rows: one column per item field, in schema order. */\n table?: TableColumnSchema[]\n /** `compact()`: a table layout with tighter cells. */\n compact?: boolean\n /** Render only the visible items above a threshold (`virtualize()`, on by default). */\n virtualize?: VirtualizeSchema\n}\n\nexport type FieldSchema =\n | TextInputSchema\n | TextareaSchema\n | HiddenSchema\n | OneTimeCodeInputSchema\n | CheckboxSchema\n | ToggleSchema\n | SelectSchema\n | CheckboxListSchema\n | RadioSchema\n | DatePickerSchema\n | MoneyInputSchema\n | ColorPickerSchema\n | TagsInputSchema\n | KeyValueSchema\n | FileUploadSchema\n | RichEditorSchema\n | RepeaterSchema\n | BuilderSchema\n | ToggleButtonsSchema\n | SliderSchema\n | CodeEditorSchema\n | ModalTableSelectSchema\n | IconPickerSchema\n | FileManagerPickerSchema\n\nexport const FIELD_TYPES = [\n 'TextInput',\n 'Textarea',\n 'Hidden',\n 'OneTimeCodeInput',\n 'Checkbox',\n 'Toggle',\n 'Select',\n 'CheckboxList',\n 'Radio',\n 'DatePicker',\n 'DateTimePicker',\n 'MoneyInput',\n 'TimePicker',\n 'ColorPicker',\n 'TagsInput',\n 'KeyValue',\n 'FileUpload',\n 'RichEditor',\n 'MarkdownEditor',\n 'Repeater',\n 'Builder',\n 'ToggleButtons',\n 'Slider',\n 'CodeEditor',\n 'ModalTableSelect',\n 'IconPicker',\n // alfasix/alfakit-file-manager\n 'FileManagerPicker',\n] as const\n\nexport function isField(component: SchemaComponent): component is FieldSchema {\n return (\n 'statePath' in component &&\n typeof (component as BaseField).statePath === 'string' &&\n (FIELD_TYPES as readonly string[]).includes(component.type)\n )\n}\n\n// ---------------------------------------------------------------- Layout\n\nexport interface GridSchema extends BaseComponent {\n type: 'Grid'\n}\n\nexport interface GroupSchema extends BaseComponent {\n type: 'Group'\n}\n\n/**\n * Fields fused into one control (shared border, no gaps). Child labels become\n * screen-reader text and their errors are listed below the group.\n */\nexport interface FusedGroupSchema extends BaseComponent {\n type: 'FusedGroup'\n}\n\nexport interface SectionSchema extends BaseComponent {\n type: 'Section'\n heading?: string\n /** The heading's level (`2` = `h2`): `rootHeadingLevel()` plus the nesting depth. */\n headingLevel?: number\n description?: string\n icon?: IconName\n collapsible?: boolean\n collapsed?: boolean\n /** `persistCollapsed()`: the local storage key the collapsed state is kept under. */\n persistCollapsed?: string\n compact?: boolean\n aside?: boolean\n secondary?: boolean\n headerActions?: AnyActionSchema[]\n /** `afterHeader()`: actions and components at the end of the header. */\n afterHeader?: ContentSlotItem[]\n footerActions?: AnyActionSchema[]\n /** `footerActionsAlignment()`: alignment of `footerActions` (default `start`). */\n footerActionsAlignment?: Alignment\n /** `footer()`: actions and components in the footer, after `footerActions`. */\n footer?: ContentSlotItem[]\n}\n\nexport interface FieldsetSchema extends BaseComponent {\n type: 'Fieldset'\n /** `contained(false)`: no border or padding around the fields. */\n contained?: false\n}\n\nexport interface TabSchema extends BaseComponent {\n type: 'Tab'\n /**\n * The tab's readable value in the query string when its tabs `persistTabInQueryString()`:\n * its `id()`, explicit `key()` or label slug (`?tab=billing-address`).\n */\n queryValue?: string\n icon?: IconName\n iconPosition?: IconPosition\n badge?: string | number\n badgeColor?: Color\n /** `Tab::badgeTooltip()`: shown on hover (title) of the badge. */\n badgeTooltip?: string\n /** `deferBadge()`: the badge is loaded from `schemaDeferred` after the page renders. */\n badgeDeferred?: boolean\n}\n\n/** What `schemaDeferred` returns for a `Tab::deferBadge()` tab. */\nexport interface DeferredBadgeSchema {\n badge?: string | number | null\n badgeColor?: Color | null\n badgeTooltip?: string | null\n}\n\nexport interface TabsSchema extends BaseComponent {\n type: 'Tabs'\n schema: TabSchema[]\n activeTab: number\n contained?: boolean\n vertical?: boolean\n queryStringKey?: string\n /** `scrollable(false)`: the tab list wraps instead of scrolling sideways. */\n scrollable?: false\n /** `persistTab()`: where the active tab is remembered in the browser. */\n persistTab?: { key: string; storage: 'local' | 'session' }\n}\n\nexport interface StepSchema extends BaseComponent {\n type: 'Step'\n description?: string\n icon?: IconName\n /** Icon once the step is completed (falls back to the wizard's, then a check mark). */\n completedIcon?: IconName\n}\n\nexport interface WizardSchema extends BaseComponent {\n type: 'Wizard'\n schema: StepSchema[]\n startStep: number\n skippable?: boolean\n submitActionLabel?: string\n /** `submitAction(Action)`: rendered on the last step, runs through the action endpoint. */\n submitAction?: ActionSchema\n /** `submitAction(Htmlable)`: markup rendered on the last step. */\n submitActionHtml?: string\n nextActionLabel: string\n previousActionLabel: string\n /**\n * `nextAction(fn)` / `previousAction(fn)`: the button's appearance; `false` hides it.\n * Absent when not customised (the default buttons render).\n */\n nextAction?: ActionSchema | false\n previousAction?: ActionSchema | false\n completedIcon?: IconName\n /** Query-string key the current step is kept under (`true` from older servers = `step`). */\n persistStepInQueryString?: string | boolean\n /**\n * `goToStep()`: the server asked the wizard to show the step with this key. `id` is new\n * on every response, so the same step can be requested again.\n */\n goToStep?: { step: string; id: string }\n}\n\nexport interface PlaceholderSchema extends BaseComponent {\n type: 'Placeholder'\n content?: string\n helperText?: string\n}\n\nexport interface HtmlSchema extends BaseComponent {\n type: 'Html'\n content: string\n}\n\nexport interface TextSchema extends BaseComponent {\n type: 'Text'\n content: string\n color?: Color\n icon?: IconName\n size?: string\n weight?: string\n badge?: boolean\n /** `sans`, `serif` or `mono`. */\n fontFamily?: string\n tooltip?: string\n /** `copyable()`: a button copies `content` to the clipboard. */\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows. */\n copyMessageDuration?: number\n}\n\n/** A custom frontend component registered in the renderer. */\nexport interface ViewSchema extends BaseComponent {\n type: 'View'\n component: string\n props?: Record<string, unknown>\n}\n\n/** Children side by side, stacked below the `from` breakpoint. */\nexport interface FlexSchema extends BaseComponent {\n type: 'Flex'\n from: 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n verticalAlignment?: 'start' | 'center' | 'end'\n /** `alignment()`: horizontal alignment of the children (`justify` spreads them like `between`). */\n alignment?: Alignment\n}\n\n/** A highlighted message box. `description` is HTML (plain strings escaped by the server). */\nexport interface CalloutSchema extends BaseComponent {\n type: 'Callout'\n heading?: string\n description?: string\n icon?: IconName\n /** `iconSize()`: `sm`, `md` or `lg` (default). */\n iconSize?: Size\n color?: Color\n /**\n * `status()` / `danger()`…: kept after `color(null)` so the icon keeps its status colour\n * and danger/warning callouts keep `role=\"alert\"`.\n */\n status?: Color\n /** `iconColor()`: overrides the icon's colour. */\n iconColor?: Color\n actions?: AnyActionSchema[]\n /** `footerActionsAlignment()`: alignment of `actions` (default `start`). */\n footerActionsAlignment?: Alignment\n /** `controls()` and `controlActions()`: shown in the top end corner. */\n controls?: ContentSlotItem[]\n /** `footer()`: actions and components under the description. */\n footer?: ContentSlotItem[]\n}\n\n/**\n * A row of action buttons placed freely in a form or infolist. The actions run in the\n * component's field context (`field:{schema}::{key}`), like a field's suffix actions.\n */\nexport interface ActionsComponentSchema extends BaseComponent {\n type: 'Actions'\n actions: AnyActionSchema[]\n alignment?: Alignment\n verticalAlignment?: 'start' | 'center' | 'end'\n fullWidth?: boolean\n}\n\n/** Placeholder for missing content. `description` is HTML (escaped by the server). */\nexport interface EmptyStateComponentSchema extends BaseComponent {\n type: 'EmptyState'\n heading?: string\n description?: string\n icon?: IconName\n color?: Color\n contained: boolean\n actions?: AnyActionSchema[]\n /** `footer()`: actions and components under the description (after `actions`). */\n footer?: ContentSlotItem[]\n}\n\nexport interface IconSchema extends BaseComponent {\n type: 'Icon'\n icon: IconName\n color?: Color\n size?: Size | string\n tooltip?: string\n}\n\nexport interface ImageSchema extends BaseComponent {\n type: 'Image'\n url: string\n alt: string\n /** CSS lengths. */\n imageWidth?: string\n imageHeight?: string\n alignment?: Alignment\n circular?: boolean\n tooltip?: string\n}\n\n/** A bulleted list; every child component is one item. */\nexport interface UnorderedListSchema extends BaseComponent {\n type: 'UnorderedList'\n size?: Size | string\n}\n\nexport type LayoutSchema =\n | FlexSchema\n | CalloutSchema\n | ActionsComponentSchema\n | EmptyStateComponentSchema\n | IconSchema\n | ImageSchema\n | UnorderedListSchema\n | GridSchema\n | GroupSchema\n | FusedGroupSchema\n | SectionSchema\n | FieldsetSchema\n | TabsSchema\n | TabSchema\n | WizardSchema\n | StepSchema\n | PlaceholderSchema\n | HtmlSchema\n | TextSchema\n | ViewSchema\n\n// ---------------------------------------------------------------- Infolist entries\n\nexport interface BaseEntry extends BaseComponent, FieldActions, ContentSlots {\n name: string\n state?: unknown\n url?: string\n openUrlInNewTab?: boolean\n tooltip?: string\n helperText?: string\n /** HTML: plain strings are escaped by the server, `Htmlable` values are sent as is. */\n hint?: string\n hintIcon?: IconName\n hintColor?: Color\n placeholder?: string\n /** `inlineLabel()`: the label sits beside the value from the `sm` breakpoint up. */\n inlineLabel?: boolean\n /**\n * Attributes for the `data-slot=\"entry\"` wrapper. `extraAttributes` go on the value\n * (`data-slot=\"entry-value\"`).\n */\n extraEntryWrapperAttributes?: Attributes\n /** `alignment()`: horizontal alignment of the value. */\n alignment?: Alignment\n}\n\nexport interface TextStyleProps {\n size?: string\n weight?: string\n fontFamily?: string\n lineClamp?: number\n badge?: boolean\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows (`copyMessageDuration()`, default 1500). */\n copyMessageDuration?: number\n wrap?: boolean\n}\n\nexport interface FormattedStateProps {\n html?: boolean\n listWithLineBreaks?: boolean\n bulleted?: boolean\n placeholder?: string\n boolean?: boolean\n /**\n * `limitList()` + `expandableLimitedList()`: every item is sent; the first `listLimit`\n * show with a \"+N more\" toggle for the rest.\n */\n expandableLimitedList?: boolean\n listLimit?: number\n}\n\n/** `ring()` / `overlap()` / `extraImgAttributes()` of image columns and entries. */\nexport interface ImageStackProps {\n /** Ring width in pixels around stacked images (0–8, default 2). */\n ring?: number\n /** Overlap of stacked images in quarter rems (0–8, default 2). */\n overlap?: number\n}\n\nexport interface TextEntrySchema extends BaseEntry, TextStyleProps, FormattedStateProps {\n type: 'TextEntry'\n state?: string | number | boolean | Array<string | number> | null\n color?: Color\n icon?: IconName\n iconPosition?: IconPosition\n iconColor?: Color\n /** Per-item colours of a list state (enums whose items differ), aligned with the items. */\n itemColors?: Array<Color | null>\n /** Per-item icons of a list state, aligned with the items. */\n itemIcons?: Array<IconName | null>\n /** Per-item links of a relationship list (`tags.name` with a `url()` closure). */\n itemUrls?: Array<string | null>\n prose?: boolean\n}\n\nexport interface IconEntrySchema extends BaseEntry {\n type: 'IconEntry'\n icon?: IconName\n color?: Color\n size?: Size | string\n}\n\nexport interface ImageEntrySchema extends BaseEntry, ImageStackProps {\n type: 'ImageEntry'\n /** HTML attributes for every `<img>` (`extraImgAttributes()`). */\n extraImgAttributes?: Attributes\n state?: string[]\n circular?: boolean\n square?: boolean\n size?: number | string\n height?: number | string\n width?: number | string\n stacked?: boolean\n limit?: number\n /** `limitedRemainingText(false)` hides the \"+N\" of images past `limit` (shown by default). */\n limitedRemainingText?: boolean\n /** Text size of the \"+N\" (`limitedRemainingText(size:)`). */\n limitedRemainingTextSize?: 'xs' | 'sm' | 'md' | 'lg'\n /** Alternative text shared by every image. */\n alt?: string\n /** Alternative text per image, aligned with `state`, when a closure gives different texts. */\n alts?: Array<string | null>\n}\n\n/** Highlighted read-only code. Array state arrives as pretty-printed JSON. */\nexport interface CodeEntrySchema extends BaseEntry {\n type: 'CodeEntry'\n state?: string | null\n /** Highlighting grammar (`json`, `php`, `js`…); unknown grammars render as plain code. */\n grammar?: string\n /** Theme names exposed to CSS as `data-light-theme` / `data-dark-theme`. */\n lightTheme?: string\n darkTheme?: string\n copyable?: boolean\n copyMessage?: string\n /** Milliseconds the copy confirmation shows. */\n copyMessageDuration?: number\n}\n\nexport interface ColorEntrySchema extends BaseEntry, TextStyleProps {\n type: 'ColorEntry'\n state?: string | string[] | null\n}\n\nexport interface KeyValueEntrySchema extends BaseEntry {\n type: 'KeyValueEntry'\n state?: Record<string, unknown>\n keyLabel: string\n valueLabel: string\n}\n\nexport interface RepeatableEntrySchema extends BaseEntry {\n type: 'RepeatableEntry'\n items: SchemaComponent[][]\n contained: boolean\n grid?: Breakpoints\n /** Render items as table rows: one column per item entry, in schema order. */\n table?: TableColumnSchema[]\n}\n\n/** An entry rendered by an application component registered under `component`. */\nexport interface ViewEntrySchema extends BaseEntry {\n type: 'ViewEntry'\n component?: string\n props?: Record<string, unknown>\n}\n\nexport type EntrySchema =\n | ViewEntrySchema\n | TextEntrySchema\n | IconEntrySchema\n | ImageEntrySchema\n | CodeEntrySchema\n | ColorEntrySchema\n | KeyValueEntrySchema\n | RepeatableEntrySchema\n\nexport type SchemaComponent =\n FieldSchema | LayoutSchema | EntrySchema | (BaseComponent & { type: string })\n\nexport type { Alignment }\n"],"mappings":";AA6qBA,MAAa,cAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;AACF;AAEA,SAAgB,QAAQ,WAAsD;CAC5E,OACE,eAAe,aACf,OAAQ,UAAwB,cAAc,YAC7C,YAAkC,SAAS,UAAU,IAAI;AAE9D"}
|
package/dist/schema/form.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export interface InfolistBlock {
|
|
|
55
55
|
type: 'Infolist';
|
|
56
56
|
key: string;
|
|
57
57
|
components: SchemaComponent[];
|
|
58
|
+
/** The infolist's `columns()` (one column on the profile page's security part). */
|
|
59
|
+
columns?: Breakpoints;
|
|
58
60
|
}
|
|
59
61
|
export interface SchemaBlock {
|
|
60
62
|
type: 'Schema';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","names":[],"sources":["../../src/schema/form.ts"],"mappings":";;;;;;iBAMiB;EACf,YAAY;EACZ,OAAO;EACP,UAAU;;;;;;EAMV,eAAe;;;iBAIA;EACf;EACA,WAAW;;;iBAII;EACf;EACA,SAAS;EACT,cAAc;EACd,UAAU;;EAEV,OAAO;EACP;;EAEA;;;iBAIe,kBAAkB;EACjC;EACA;;EAEA;EACA,SAAS;EACT,YAAY;;;;;EAKZ;;;;;EAKA;;iBAGe;EACf;EACA;EACA,YAAY;;
|
|
1
|
+
{"version":3,"file":"form.d.ts","names":[],"sources":["../../src/schema/form.ts"],"mappings":";;;;;;iBAMiB;EACf,YAAY;EACZ,OAAO;EACP,UAAU;;;;;;EAMV,eAAe;;;iBAIA;EACf;EACA,WAAW;;;iBAII;EACf;EACA,SAAS;EACT,cAAc;EACd,UAAU;;EAEV,OAAO;EACP;;EAEA;;;iBAIe,kBAAkB;EACjC;EACA;;EAEA;EACA,SAAS;EACT,YAAY;;;;;EAKZ;;;;;EAKA;;iBAGe;EACf;EACA;EACA,YAAY;;EAEZ,UAAU;;iBAGK;EACf;EACA;EACA,YAAY;;iBAGG;EACf;EACA;EACA,OAAO;IAAQ;IAAe;;;;YAIpB,wBAAwB,cAAc;wBAElC,qBACd,SAAS,wBACR,WAAW;;iBAKG;EACf;EACA;EACA;EACA;;EAEA;;EAEA,OAAO;;EAEP,gBAAgB;;;;;;;iBAQD;EACf;EACA,gBAAgB;;iBAGD;EACf,UAAU;IAAQ;IAAe;;EACjC,SAAS"}
|
package/dist/schema/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","names":[],"sources":["../../src/schema/form.ts"],"sourcesContent":["import type { ActionSchema } from './actions'\nimport type { Breakpoints, Operation } from './common'\nimport type { SchemaComponent } from './components'\nimport type { NotificationSchema } from './notifications'\n\n/** `Schema::toPayload()` — a component tree plus its state. */\nexport interface FormPayload {\n components: SchemaComponent[]\n state: Record<string, unknown>\n columns?: Breakpoints\n /**\n * Component fingerprints (index path → `own:subtree` hashes), sent for forms with live\n * fields or field actions. The store sends them back so a refresh answers with only\n * what changed (`PartialFormPayload`).\n */\n fingerprints?: Record<string, string>\n}\n\n/** A component replaced by a partial refresh, at its index path (`0.2` = `components[0].schema[2]`). */\nexport interface SchemaPatch {\n path: string\n component: SchemaComponent\n}\n\n/** A refresh answered with only the components and state keys that changed. */\nexport interface PartialFormPayload {\n partial: true\n patches: SchemaPatch[]\n fingerprints: Record<string, string>\n columns?: Breakpoints\n /** With `partialState`, only the top-level keys that differ from the state that was sent. */\n state: Record<string, unknown> | unknown[]\n partialState?: boolean\n /** Top-level keys that were sent but no longer exist (fields that became hidden). */\n removedState?: string[]\n}\n\n/** A page-level form block, including its submit actions. */\nexport interface FormBlock extends FormPayload {\n type: 'Form'\n key: string\n /** Context component name used by internal endpoints (`form`). */\n component: string\n actions: ActionSchema[]\n operation?: Operation\n /**\n * Dashboard filters with `live()` fields: the server stores the filters during the live\n * refresh, and the renderer reloads the page's widgets once it is merged.\n */\n liveFilters?: boolean\n /**\n * The form is a wizard (`HasWizard` Create pages): its buttons show on the wizard's last\n * step only.\n */\n wizard?: boolean\n}\n\nexport interface InfolistBlock {\n type: 'Infolist'\n key: string\n components: SchemaComponent[]\n}\n\nexport interface SchemaBlock {\n type: 'Schema'\n key: string\n components: SchemaComponent[]\n}\n\nexport interface LinksBlock {\n type: 'Links'\n key: string\n links: Array<{ label: string; url: string }>\n}\n\n/** Response of the schema refresh endpoint. */\nexport type SchemaRefreshResponse = FormPayload | PartialFormPayload\n\nexport function isPartialFormPayload(\n payload: SchemaRefreshResponse,\n): payload is PartialFormPayload {\n return (payload as PartialFormPayload).partial === true\n}\n\n/** Response of the action endpoint for a field action. */\nexport interface FieldActionResponse {\n status: 'success' | 'halted' | 'cancelled'\n result?: unknown\n closeModal?: boolean\n redirect?: string | null\n /** A file the handler returned: a signed, one-time link to save it from. */\n download?: string | null\n /** The owning form after the action ran (partial when fingerprints were sent). */\n form?: SchemaRefreshResponse\n /** Notifications the action sent (field actions answer with JSON, not a page visit). */\n notifications?: NotificationSchema[]\n}\n\n/**\n * Response of the step validation endpoint when a step hook halted (`throw new Halt`):\n * the wizard stays on the step and shows the notifications the hook sent. Steps that\n * pass answer 204 (no body).\n */\nexport interface StepValidationHaltedResponse {\n halted: true\n notifications?: NotificationSchema[]\n}\n\nexport interface SelectOptionsResponse {\n options?: Array<{ value: string; label: string }>\n labels?: Record<string, string>\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"form.js","names":[],"sources":["../../src/schema/form.ts"],"sourcesContent":["import type { ActionSchema } from './actions'\nimport type { Breakpoints, Operation } from './common'\nimport type { SchemaComponent } from './components'\nimport type { NotificationSchema } from './notifications'\n\n/** `Schema::toPayload()` — a component tree plus its state. */\nexport interface FormPayload {\n components: SchemaComponent[]\n state: Record<string, unknown>\n columns?: Breakpoints\n /**\n * Component fingerprints (index path → `own:subtree` hashes), sent for forms with live\n * fields or field actions. The store sends them back so a refresh answers with only\n * what changed (`PartialFormPayload`).\n */\n fingerprints?: Record<string, string>\n}\n\n/** A component replaced by a partial refresh, at its index path (`0.2` = `components[0].schema[2]`). */\nexport interface SchemaPatch {\n path: string\n component: SchemaComponent\n}\n\n/** A refresh answered with only the components and state keys that changed. */\nexport interface PartialFormPayload {\n partial: true\n patches: SchemaPatch[]\n fingerprints: Record<string, string>\n columns?: Breakpoints\n /** With `partialState`, only the top-level keys that differ from the state that was sent. */\n state: Record<string, unknown> | unknown[]\n partialState?: boolean\n /** Top-level keys that were sent but no longer exist (fields that became hidden). */\n removedState?: string[]\n}\n\n/** A page-level form block, including its submit actions. */\nexport interface FormBlock extends FormPayload {\n type: 'Form'\n key: string\n /** Context component name used by internal endpoints (`form`). */\n component: string\n actions: ActionSchema[]\n operation?: Operation\n /**\n * Dashboard filters with `live()` fields: the server stores the filters during the live\n * refresh, and the renderer reloads the page's widgets once it is merged.\n */\n liveFilters?: boolean\n /**\n * The form is a wizard (`HasWizard` Create pages): its buttons show on the wizard's last\n * step only.\n */\n wizard?: boolean\n}\n\nexport interface InfolistBlock {\n type: 'Infolist'\n key: string\n components: SchemaComponent[]\n /** The infolist's `columns()` (one column on the profile page's security part). */\n columns?: Breakpoints\n}\n\nexport interface SchemaBlock {\n type: 'Schema'\n key: string\n components: SchemaComponent[]\n}\n\nexport interface LinksBlock {\n type: 'Links'\n key: string\n links: Array<{ label: string; url: string }>\n}\n\n/** Response of the schema refresh endpoint. */\nexport type SchemaRefreshResponse = FormPayload | PartialFormPayload\n\nexport function isPartialFormPayload(\n payload: SchemaRefreshResponse,\n): payload is PartialFormPayload {\n return (payload as PartialFormPayload).partial === true\n}\n\n/** Response of the action endpoint for a field action. */\nexport interface FieldActionResponse {\n status: 'success' | 'halted' | 'cancelled'\n result?: unknown\n closeModal?: boolean\n redirect?: string | null\n /** A file the handler returned: a signed, one-time link to save it from. */\n download?: string | null\n /** The owning form after the action ran (partial when fingerprints were sent). */\n form?: SchemaRefreshResponse\n /** Notifications the action sent (field actions answer with JSON, not a page visit). */\n notifications?: NotificationSchema[]\n}\n\n/**\n * Response of the step validation endpoint when a step hook halted (`throw new Halt`):\n * the wizard stays on the step and shows the notifications the hook sent. Steps that\n * pass answer 204 (no body).\n */\nexport interface StepValidationHaltedResponse {\n halted: true\n notifications?: NotificationSchema[]\n}\n\nexport interface SelectOptionsResponse {\n options?: Array<{ value: string; label: string }>\n labels?: Record<string, string>\n}\n"],"mappings":";AAgFA,SAAgB,qBACd,SAC+B;CAC/B,OAAQ,QAA+B,YAAY;AACrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-kit.d.ts","names":[],"sources":["../src/starter-kit.ts"],"mappings":";;;;;;;;;;;;;;qBAmCa;;wBAGG,kBACd,OAAO,KAAK;;iBAMG;EACf;EACA;;;;;;;;wBASc,wBACd,aAAa,wCACZ;;;;;;;;wBAsBa,yBAAyB;wBAMzB,+BAA+B,iBAAiB;;;;;wBAUhD,sBAAsB,iBAAiB;;;;;wBAUvC,yBAAyB;;;;;;wBAWzB,6BAA6B;EAAY;GACvD,SAAS,KACT,iBACC;;;;;wBAWa,qBACd,gBACA,mBACC;;;;;iBAcc;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;;iBAGK;EACf;EACA;EACA;EACA,OAAO;;;
|
|
1
|
+
{"version":3,"file":"starter-kit.d.ts","names":[],"sources":["../src/starter-kit.ts"],"mappings":";;;;;;;;;;;;;;qBAmCa;;wBAGG,kBACd,OAAO,KAAK;;iBAMG;EACf;EACA;;;;;;;;wBASc,wBACd,aAAa,wCACZ;;;;;;;;wBAsBa,yBAAyB;wBAMzB,+BAA+B,iBAAiB;;;;;wBAUhD,sBAAsB,iBAAiB;;;;;wBAUvC,yBAAyB;;;;;;wBAWzB,6BAA6B;EAAY;GACvD,SAAS,KACT,iBACC;;;;;wBAWa,qBACd,gBACA,mBACC;;;;;iBAcc;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;;iBAGK;EACf;EACA;EACA;EACA,OAAO;;;wBAqCO,sBACd,QAAQ,6CACP;;;;;;iBAkBc;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;;;wBAIc,0BACd,OAAO,sCACN;;;;;;wBA2Ba,gBACd,WAAW,4CACX,WAAW,6CACV;;;;;wBA6Ba,mBAAmB,OAAO,QAAQ;;wBAalC,0BAA0B;;;;;;;;wBAW1B,yBACd,OAAO,cAAc,6BACrB,IAAI,aAAa,eAAe,iCAAiC"}
|
package/dist/starter-kit.js
CHANGED
|
@@ -99,9 +99,24 @@ function toNavItem(item, key) {
|
|
|
99
99
|
badge: item.badge ?? void 0,
|
|
100
100
|
badgeColor: item.badgeColor ?? void 0,
|
|
101
101
|
badgeTooltip: item.badgeTooltip ?? void 0,
|
|
102
|
-
children: (item.children ?? []
|
|
102
|
+
children: toNavItems(item.children ?? [], key)
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Items keyed by their URL (positional only without one, or for a repeated URL), so a keyed
|
|
107
|
+
* list keeps each sidebar link with its own entry when the labels and their order change,
|
|
108
|
+
* e.g. after a language switch; a reused Inertia `<Link>` kept navigating to the URL of the
|
|
109
|
+
* entry it was created for (W-S4-08).
|
|
110
|
+
*/
|
|
111
|
+
function toNavItems(items, parentKey) {
|
|
112
|
+
const seen = /* @__PURE__ */ new Set();
|
|
113
|
+
return items.map((item, index) => {
|
|
114
|
+
const url = item.url ? `url:${item.url}` : null;
|
|
115
|
+
const key = url && !seen.has(url) ? url : `${parentKey}.${index}`;
|
|
116
|
+
seen.add(key);
|
|
117
|
+
return toNavItem(item, key);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
105
120
|
/** A panel's navigation groups as plain items for the host's sidebar primitives. */
|
|
106
121
|
function toStarterKitNavGroups(groups) {
|
|
107
122
|
return (groups ?? []).map((group, index) => {
|
|
@@ -110,7 +125,7 @@ function toStarterKitNavGroups(groups) {
|
|
|
110
125
|
key,
|
|
111
126
|
label: group.label ?? null,
|
|
112
127
|
icon: group.icon ?? void 0,
|
|
113
|
-
items: group.items
|
|
128
|
+
items: toNavItems(group.items, key)
|
|
114
129
|
};
|
|
115
130
|
});
|
|
116
131
|
}
|
package/dist/starter-kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-kit.js","names":[],"sources":["../src/starter-kit.ts"],"sourcesContent":["import { debugRecorder } from './debug'\nimport {\n effectiveErrorNotifications,\n installErrorNotifications,\n resolveRequestErrorNotification,\n setRequestErrorReporter,\n} from './error-notifications'\nimport { reloadOnExpiredPage } from './http'\nimport { navigationItemText } from './navigation'\nimport { installPrefetchInvalidation } from './prefetch'\nimport type { NotificationSchema } from './schema/notifications'\nimport type {\n AlfakitPageProps,\n BreadcrumbSchema,\n ErrorNotificationsSchema,\n MenuItemSchema,\n NavigationGroupSchema,\n NavigationItemSchema,\n PanelSchema,\n StarterKitNavigationSchema,\n} from './schema/panel'\nimport { installSpaUrlExceptions } from './spa'\n\n/**\n * Starter kit mode (`Panel::starterKit()`): Alfakit pages render inside an application made\n * from Laravel's React, Vue or Svelte starter kit, in the host's own layout. These helpers are\n * shared by the three renderers; the host's sidebar reads the navigation through each\n * renderer's `useAlfakitNavigation()`.\n */\n\n/**\n * The sonner toaster Alfakit renders in starter kit mode. The host layout mounts its own\n * id-less `<Toaster />`; giving Alfakit's an id keeps each toast in one toaster even when the\n * host and Alfakit resolve the same sonner instance.\n */\nexport const STARTER_KIT_TOASTER_ID = 'alfakit'\n\n/** Whether the panel runs inside a starter kit application (`Panel::starterKit()`). */\nexport function isStarterKitPanel(\n panel: Pick<PanelSchema, 'starterKit'> | null | undefined,\n): boolean {\n return panel?.starterKit === true\n}\n\n/** A breadcrumb as the starter kits' `AppLayout` takes it (`BreadcrumbItem`). */\nexport interface StarterKitBreadcrumb {\n title: string\n href: string\n}\n\n/**\n * The page's breadcrumbs in the starter kits' shape: `{ title, href }` instead of\n * `{ label, url }`. The kits render the last crumb (the current page) as plain text and key\n * the list by `href`, so every `href` is unique: the last crumb without a URL keeps an empty\n * one, other crumbs without one (or repeating one) get a `#index` fragment.\n */\nexport function toStarterKitBreadcrumbs(\n breadcrumbs: BreadcrumbSchema[] | null | undefined,\n): StarterKitBreadcrumb[] {\n const list = breadcrumbs ?? []\n const seen = new Set<string>()\n\n return list.map((crumb, index) => {\n let href = crumb.url ?? (index === list.length - 1 ? '' : `#${index}`)\n\n if (seen.has(href)) href = `${href}#${index}`\n\n seen.add(href)\n\n return { title: crumb.label, href }\n })\n}\n\n/** The breadcrumbs of an Alfakit page from its Inertia props (`props.page.breadcrumbs`). */\n/**\n * Whether an Alfakit page renders inside the host layout (`createStarterKitPage({ layout })`).\n * Pages with the `auth` layout (sign-in, registration, password reset, multi-factor\n * challenge, email verification, `->login()` brought back after `starterKit()`) stand on\n * their own, like the host's auth pages: the host layout expects a signed-in user.\n */\nexport function usesStarterKitHostLayout(props: unknown): boolean {\n const page = (props as { page?: { layout?: string } } | null | undefined)?.page\n\n return page?.layout !== 'auth'\n}\n\nexport function starterKitBreadcrumbsFromProps(props: unknown): StarterKitBreadcrumb[] {\n const page = (props as { page?: { breadcrumbs?: BreadcrumbSchema[] } } | null | undefined)?.page\n\n return toStarterKitBreadcrumbs(page?.breadcrumbs)\n}\n\n/**\n * The shared `alfakitNavigation` prop of a page: one entry per `starterKit()` panel, or none\n * for guests and pages of other panels.\n */\nexport function starterKitNavigations(props: unknown): StarterKitNavigationSchema[] {\n const value = (props as { alfakitNavigation?: unknown } | null | undefined)?.alfakitNavigation\n\n return Array.isArray(value) ? (value as StarterKitNavigationSchema[]) : []\n}\n\n/**\n * The panel of the open AlfaKit page (`props.alfakit.id`), or undefined on the host's own\n * pages. With several `starterKit()` panels, components without a `panel` follow it.\n */\nexport function currentStarterKitPanelId(props: unknown): string | undefined {\n const id = (props as { alfakit?: { id?: unknown } } | null | undefined)?.alfakit?.id\n\n return typeof id === 'string' ? id : undefined\n}\n\n/**\n * Order panel entries for components without a `panel` id: the open AlfaKit page's panel\n * first (an `/app` page of a second `starterKit()` panel shows that panel's navigation and\n * tenant menu), then the others in registration order.\n */\nexport function preferCurrentStarterKitPanel<T extends { id: string }>(\n entries: T[],\n props: unknown,\n): T[] {\n const current = currentStarterKitPanelId(props)\n const index = current === undefined ? -1 : entries.findIndex((entry) => entry.id === current)\n\n return index <= 0 ? entries : [entries[index]!, ...entries.filter((_, i) => i !== index)]\n}\n\n/**\n * One panel's navigation, or null. Without an id: the open AlfaKit page's panel, else the\n * first starter kit panel.\n */\nexport function starterKitNavigation(\n props: unknown,\n panelId?: string,\n): StarterKitNavigationSchema | null {\n const navigations = starterKitNavigations(props)\n\n return (\n (panelId === undefined\n ? preferCurrentStarterKitPanel(navigations, props)[0]\n : navigations.find((navigation) => navigation.id === panelId)) ?? null\n )\n}\n\n/**\n * A navigation item flattened for a starter kit sidebar: the label as text and the item's\n * nested children. `title`/`href` match the kits' `NavItem` so the host can reuse its types.\n */\nexport interface StarterKitNavItem {\n key: string\n title: string\n href: string\n icon?: string\n isActive: boolean\n openInNewTab: boolean\n badge?: string | number\n badgeColor?: string\n badgeTooltip?: string\n children: StarterKitNavItem[]\n}\n\nexport interface StarterKitNavGroup {\n key: string\n label: string | null\n icon?: string\n items: StarterKitNavItem[]\n}\n\nfunction toNavItem(item: NavigationItemSchema, key: string): StarterKitNavItem {\n return {\n key,\n title: navigationItemText(item),\n href: item.url ?? '',\n icon: item.icon ?? undefined,\n isActive: item.active === true,\n openInNewTab: item.openInNewTab === true,\n badge: item.badge ?? undefined,\n badgeColor: item.badgeColor ?? undefined,\n badgeTooltip: item.badgeTooltip ?? undefined,\n children: (item.children ?? []).map((child, index) => toNavItem(child, `${key}.${index}`)),\n }\n}\n\n/** A panel's navigation groups as plain items for the host's sidebar primitives. */\nexport function toStarterKitNavGroups(\n groups: NavigationGroupSchema[] | null | undefined,\n): StarterKitNavGroup[] {\n return (groups ?? []).map((group, index) => {\n const key = `${index}:${group.label ?? ''}`\n\n return {\n key,\n label: group.label ?? null,\n icon: group.icon ?? undefined,\n items: group.items.map((item, itemIndex) => toNavItem(item, `${key}.${itemIndex}`)),\n }\n })\n}\n\n/**\n * A user menu entry of a `starterKit()` panel for the kit's own dropdown items\n * (`<AlfakitUserMenuItems />`). `group` changes where a separator goes; `method: 'post'`\n * links are sent as POST (like the kit's Log out).\n */\nexport interface StarterKitUserMenuItem {\n key: string\n title: string\n href: string\n icon?: string\n openInNewTab: boolean\n method?: 'post'\n group: number\n /** Whether a separator goes before this entry (it starts a new group). */\n startsGroup: boolean\n}\n\n/** A panel's shared user menu links as plain items for the host's dropdown primitives. */\nexport function toStarterKitUserMenuItems(\n items: MenuItemSchema[] | null | undefined,\n): StarterKitUserMenuItem[] {\n const links = (items ?? []).filter(\n (item): item is MenuItemSchema & { url: string } =>\n typeof item.url === 'string' && item.url !== '' && item.action === undefined,\n )\n\n return links.map((item, index) => {\n const group = item.group ?? 0\n\n return {\n key: `${index}:${item.label ?? ''}`,\n title: item.label ?? item.url,\n href: item.url,\n icon: item.icon ?? undefined,\n openInNewTab: item.openInNewTab === true,\n method: item.method,\n group,\n startsGroup: index > 0 && group !== (links[index - 1]!.group ?? 0),\n }\n })\n}\n\n/**\n * The props of a custom page component (`Page::$component`) rendered by `Alfakit/Page` (a\n * starter kit resolves only that page): its view data, with the page's live top-level props\n * of the same names, so a partial reload (`reloadProps('items')`) reaches the component.\n */\nexport function customPageProps(\n viewProps: Record<string, unknown> | null | undefined,\n pageProps: Record<string, unknown> | null | undefined,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...(viewProps ?? {}) }\n\n for (const key of Object.keys(merged)) {\n if (pageProps && Object.prototype.hasOwnProperty.call(pageProps, key)) {\n merged[key] = pageProps[key]\n }\n }\n\n return merged\n}\n\n// ---------------------------------------------------------------- Browser runtime\n\n/**\n * What the browser-wide listeners of starter kit mode read: the open Alfakit page's panel\n * and error notifications, or nothing while a page of the host application is open (its\n * errors keep Inertia's default handling).\n */\nconst runtime: {\n panel: PanelSchema | null\n errorNotifications: ErrorNotificationsSchema | false | undefined\n installed: boolean\n} = { panel: null, errorNotifications: undefined, installed: false }\n\n/**\n * Record the Alfakit page being rendered (called by each renderer's starter kit root while\n * it renders); `null` once the root unmounts, when a host page opens.\n */\nexport function syncStarterKitPage(props: Partial<AlfakitPageProps> | null): void {\n const panel = props?.alfakit ?? null\n\n runtime.panel = panel\n runtime.errorNotifications = panel ? effectiveErrorNotifications(panel, props?.page) : undefined\n\n if (typeof window !== 'undefined') {\n // Internal requests and form stores are recorded only while the page carries the debug prop.\n debugRecorder.setEnabled(props?.alfakitDebug !== undefined)\n }\n}\n\n/** The panel of the open Alfakit page in starter kit mode, or null on host pages. */\nexport function currentStarterKitPanel(): PanelSchema | null {\n return runtime.panel\n}\n\n/**\n * The listeners `createAlfakit()` installs, once per page load, for starter kit mode: reload\n * on an expired CSRF token (419), the panel's error notifications instead of Inertia's error\n * modal, a notification for failed internal requests, the panel's SPA URL exceptions, and\n * dropping prefetched pages after a save (and reloading pages Back restores after one).\n * Returns false when they were already installed (or on the server).\n */\nexport function installStarterKitRuntime(\n show: (notification: NotificationSchema) => void,\n t: (key: string, replacements?: Record<string, string | number>, fallback?: string) => string,\n): boolean {\n if (typeof window === 'undefined' || runtime.installed) return false\n\n runtime.installed = true\n\n reloadOnExpiredPage()\n installPrefetchInvalidation()\n installSpaUrlExceptions(() => runtime.panel)\n installErrorNotifications(() => ({ errorNotifications: runtime.errorNotifications }), show)\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(error, runtime.errorNotifications, t)\n\n if (notification) show(notification)\n })\n\n return true\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"starter-kit.js","names":[],"sources":["../src/starter-kit.ts"],"sourcesContent":["import { debugRecorder } from './debug'\nimport {\n effectiveErrorNotifications,\n installErrorNotifications,\n resolveRequestErrorNotification,\n setRequestErrorReporter,\n} from './error-notifications'\nimport { reloadOnExpiredPage } from './http'\nimport { navigationItemText } from './navigation'\nimport { installPrefetchInvalidation } from './prefetch'\nimport type { NotificationSchema } from './schema/notifications'\nimport type {\n AlfakitPageProps,\n BreadcrumbSchema,\n ErrorNotificationsSchema,\n MenuItemSchema,\n NavigationGroupSchema,\n NavigationItemSchema,\n PanelSchema,\n StarterKitNavigationSchema,\n} from './schema/panel'\nimport { installSpaUrlExceptions } from './spa'\n\n/**\n * Starter kit mode (`Panel::starterKit()`): Alfakit pages render inside an application made\n * from Laravel's React, Vue or Svelte starter kit, in the host's own layout. These helpers are\n * shared by the three renderers; the host's sidebar reads the navigation through each\n * renderer's `useAlfakitNavigation()`.\n */\n\n/**\n * The sonner toaster Alfakit renders in starter kit mode. The host layout mounts its own\n * id-less `<Toaster />`; giving Alfakit's an id keeps each toast in one toaster even when the\n * host and Alfakit resolve the same sonner instance.\n */\nexport const STARTER_KIT_TOASTER_ID = 'alfakit'\n\n/** Whether the panel runs inside a starter kit application (`Panel::starterKit()`). */\nexport function isStarterKitPanel(\n panel: Pick<PanelSchema, 'starterKit'> | null | undefined,\n): boolean {\n return panel?.starterKit === true\n}\n\n/** A breadcrumb as the starter kits' `AppLayout` takes it (`BreadcrumbItem`). */\nexport interface StarterKitBreadcrumb {\n title: string\n href: string\n}\n\n/**\n * The page's breadcrumbs in the starter kits' shape: `{ title, href }` instead of\n * `{ label, url }`. The kits render the last crumb (the current page) as plain text and key\n * the list by `href`, so every `href` is unique: the last crumb without a URL keeps an empty\n * one, other crumbs without one (or repeating one) get a `#index` fragment.\n */\nexport function toStarterKitBreadcrumbs(\n breadcrumbs: BreadcrumbSchema[] | null | undefined,\n): StarterKitBreadcrumb[] {\n const list = breadcrumbs ?? []\n const seen = new Set<string>()\n\n return list.map((crumb, index) => {\n let href = crumb.url ?? (index === list.length - 1 ? '' : `#${index}`)\n\n if (seen.has(href)) href = `${href}#${index}`\n\n seen.add(href)\n\n return { title: crumb.label, href }\n })\n}\n\n/** The breadcrumbs of an Alfakit page from its Inertia props (`props.page.breadcrumbs`). */\n/**\n * Whether an Alfakit page renders inside the host layout (`createStarterKitPage({ layout })`).\n * Pages with the `auth` layout (sign-in, registration, password reset, multi-factor\n * challenge, email verification, `->login()` brought back after `starterKit()`) stand on\n * their own, like the host's auth pages: the host layout expects a signed-in user.\n */\nexport function usesStarterKitHostLayout(props: unknown): boolean {\n const page = (props as { page?: { layout?: string } } | null | undefined)?.page\n\n return page?.layout !== 'auth'\n}\n\nexport function starterKitBreadcrumbsFromProps(props: unknown): StarterKitBreadcrumb[] {\n const page = (props as { page?: { breadcrumbs?: BreadcrumbSchema[] } } | null | undefined)?.page\n\n return toStarterKitBreadcrumbs(page?.breadcrumbs)\n}\n\n/**\n * The shared `alfakitNavigation` prop of a page: one entry per `starterKit()` panel, or none\n * for guests and pages of other panels.\n */\nexport function starterKitNavigations(props: unknown): StarterKitNavigationSchema[] {\n const value = (props as { alfakitNavigation?: unknown } | null | undefined)?.alfakitNavigation\n\n return Array.isArray(value) ? (value as StarterKitNavigationSchema[]) : []\n}\n\n/**\n * The panel of the open AlfaKit page (`props.alfakit.id`), or undefined on the host's own\n * pages. With several `starterKit()` panels, components without a `panel` follow it.\n */\nexport function currentStarterKitPanelId(props: unknown): string | undefined {\n const id = (props as { alfakit?: { id?: unknown } } | null | undefined)?.alfakit?.id\n\n return typeof id === 'string' ? id : undefined\n}\n\n/**\n * Order panel entries for components without a `panel` id: the open AlfaKit page's panel\n * first (an `/app` page of a second `starterKit()` panel shows that panel's navigation and\n * tenant menu), then the others in registration order.\n */\nexport function preferCurrentStarterKitPanel<T extends { id: string }>(\n entries: T[],\n props: unknown,\n): T[] {\n const current = currentStarterKitPanelId(props)\n const index = current === undefined ? -1 : entries.findIndex((entry) => entry.id === current)\n\n return index <= 0 ? entries : [entries[index]!, ...entries.filter((_, i) => i !== index)]\n}\n\n/**\n * One panel's navigation, or null. Without an id: the open AlfaKit page's panel, else the\n * first starter kit panel.\n */\nexport function starterKitNavigation(\n props: unknown,\n panelId?: string,\n): StarterKitNavigationSchema | null {\n const navigations = starterKitNavigations(props)\n\n return (\n (panelId === undefined\n ? preferCurrentStarterKitPanel(navigations, props)[0]\n : navigations.find((navigation) => navigation.id === panelId)) ?? null\n )\n}\n\n/**\n * A navigation item flattened for a starter kit sidebar: the label as text and the item's\n * nested children. `title`/`href` match the kits' `NavItem` so the host can reuse its types.\n */\nexport interface StarterKitNavItem {\n key: string\n title: string\n href: string\n icon?: string\n isActive: boolean\n openInNewTab: boolean\n badge?: string | number\n badgeColor?: string\n badgeTooltip?: string\n children: StarterKitNavItem[]\n}\n\nexport interface StarterKitNavGroup {\n key: string\n label: string | null\n icon?: string\n items: StarterKitNavItem[]\n}\n\nfunction toNavItem(item: NavigationItemSchema, key: string): StarterKitNavItem {\n return {\n key,\n title: navigationItemText(item),\n href: item.url ?? '',\n icon: item.icon ?? undefined,\n isActive: item.active === true,\n openInNewTab: item.openInNewTab === true,\n badge: item.badge ?? undefined,\n badgeColor: item.badgeColor ?? undefined,\n badgeTooltip: item.badgeTooltip ?? undefined,\n children: toNavItems(item.children ?? [], key),\n }\n}\n\n/**\n * Items keyed by their URL (positional only without one, or for a repeated URL), so a keyed\n * list keeps each sidebar link with its own entry when the labels and their order change,\n * e.g. after a language switch; a reused Inertia `<Link>` kept navigating to the URL of the\n * entry it was created for (W-S4-08).\n */\nfunction toNavItems(items: NavigationItemSchema[], parentKey: string): StarterKitNavItem[] {\n const seen = new Set<string>()\n\n return items.map((item, index) => {\n const url = item.url ? `url:${item.url}` : null\n const key = url && !seen.has(url) ? url : `${parentKey}.${index}`\n seen.add(key)\n\n return toNavItem(item, key)\n })\n}\n\n/** A panel's navigation groups as plain items for the host's sidebar primitives. */\nexport function toStarterKitNavGroups(\n groups: NavigationGroupSchema[] | null | undefined,\n): StarterKitNavGroup[] {\n return (groups ?? []).map((group, index) => {\n const key = `${index}:${group.label ?? ''}`\n\n return {\n key,\n label: group.label ?? null,\n icon: group.icon ?? undefined,\n items: toNavItems(group.items, key),\n }\n })\n}\n\n/**\n * A user menu entry of a `starterKit()` panel for the kit's own dropdown items\n * (`<AlfakitUserMenuItems />`). `group` changes where a separator goes; `method: 'post'`\n * links are sent as POST (like the kit's Log out).\n */\nexport interface StarterKitUserMenuItem {\n key: string\n title: string\n href: string\n icon?: string\n openInNewTab: boolean\n method?: 'post'\n group: number\n /** Whether a separator goes before this entry (it starts a new group). */\n startsGroup: boolean\n}\n\n/** A panel's shared user menu links as plain items for the host's dropdown primitives. */\nexport function toStarterKitUserMenuItems(\n items: MenuItemSchema[] | null | undefined,\n): StarterKitUserMenuItem[] {\n const links = (items ?? []).filter(\n (item): item is MenuItemSchema & { url: string } =>\n typeof item.url === 'string' && item.url !== '' && item.action === undefined,\n )\n\n return links.map((item, index) => {\n const group = item.group ?? 0\n\n return {\n key: `${index}:${item.label ?? ''}`,\n title: item.label ?? item.url,\n href: item.url,\n icon: item.icon ?? undefined,\n openInNewTab: item.openInNewTab === true,\n method: item.method,\n group,\n startsGroup: index > 0 && group !== (links[index - 1]!.group ?? 0),\n }\n })\n}\n\n/**\n * The props of a custom page component (`Page::$component`) rendered by `Alfakit/Page` (a\n * starter kit resolves only that page): its view data, with the page's live top-level props\n * of the same names, so a partial reload (`reloadProps('items')`) reaches the component.\n */\nexport function customPageProps(\n viewProps: Record<string, unknown> | null | undefined,\n pageProps: Record<string, unknown> | null | undefined,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...(viewProps ?? {}) }\n\n for (const key of Object.keys(merged)) {\n if (pageProps && Object.prototype.hasOwnProperty.call(pageProps, key)) {\n merged[key] = pageProps[key]\n }\n }\n\n return merged\n}\n\n// ---------------------------------------------------------------- Browser runtime\n\n/**\n * What the browser-wide listeners of starter kit mode read: the open Alfakit page's panel\n * and error notifications, or nothing while a page of the host application is open (its\n * errors keep Inertia's default handling).\n */\nconst runtime: {\n panel: PanelSchema | null\n errorNotifications: ErrorNotificationsSchema | false | undefined\n installed: boolean\n} = { panel: null, errorNotifications: undefined, installed: false }\n\n/**\n * Record the Alfakit page being rendered (called by each renderer's starter kit root while\n * it renders); `null` once the root unmounts, when a host page opens.\n */\nexport function syncStarterKitPage(props: Partial<AlfakitPageProps> | null): void {\n const panel = props?.alfakit ?? null\n\n runtime.panel = panel\n runtime.errorNotifications = panel ? effectiveErrorNotifications(panel, props?.page) : undefined\n\n if (typeof window !== 'undefined') {\n // Internal requests and form stores are recorded only while the page carries the debug prop.\n debugRecorder.setEnabled(props?.alfakitDebug !== undefined)\n }\n}\n\n/** The panel of the open Alfakit page in starter kit mode, or null on host pages. */\nexport function currentStarterKitPanel(): PanelSchema | null {\n return runtime.panel\n}\n\n/**\n * The listeners `createAlfakit()` installs, once per page load, for starter kit mode: reload\n * on an expired CSRF token (419), the panel's error notifications instead of Inertia's error\n * modal, a notification for failed internal requests, the panel's SPA URL exceptions, and\n * dropping prefetched pages after a save (and reloading pages Back restores after one).\n * Returns false when they were already installed (or on the server).\n */\nexport function installStarterKitRuntime(\n show: (notification: NotificationSchema) => void,\n t: (key: string, replacements?: Record<string, string | number>, fallback?: string) => string,\n): boolean {\n if (typeof window === 'undefined' || runtime.installed) return false\n\n runtime.installed = true\n\n reloadOnExpiredPage()\n installPrefetchInvalidation()\n installSpaUrlExceptions(() => runtime.panel)\n installErrorNotifications(() => ({ errorNotifications: runtime.errorNotifications }), show)\n setRequestErrorReporter((error) => {\n const notification = resolveRequestErrorNotification(error, runtime.errorNotifications, t)\n\n if (notification) show(notification)\n })\n\n return true\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfakit/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Framework-agnostic schema types and state management for Alfakit, the Laravel admin panel builder by Alfa Six.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alfa Six (https://alfasixbh.com)",
|