@miethe/ui 0.3.0 → 0.6.0
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 +51 -0
- package/README.md +776 -9
- package/dist/components/content-viewer/ArticleViewer.d.ts +42 -0
- package/dist/components/content-viewer/ArticleViewer.d.ts.map +1 -0
- package/dist/components/content-viewer/ArticleViewer.js +321 -0
- package/dist/components/content-viewer/ArticleViewer.js.map +1 -0
- package/dist/components/content-viewer/FrontmatterHeader.d.ts +32 -0
- package/dist/components/content-viewer/FrontmatterHeader.d.ts.map +1 -0
- package/dist/components/content-viewer/FrontmatterHeader.js +95 -0
- package/dist/components/content-viewer/FrontmatterHeader.js.map +1 -0
- package/dist/components/content-viewer/callouts/Callout.d.ts +43 -0
- package/dist/components/content-viewer/callouts/Callout.d.ts.map +1 -0
- package/dist/components/content-viewer/callouts/Callout.js +86 -0
- package/dist/components/content-viewer/callouts/Callout.js.map +1 -0
- package/dist/components/content-viewer/callouts/index.d.ts +2 -0
- package/dist/components/content-viewer/callouts/index.d.ts.map +1 -0
- package/dist/components/content-viewer/callouts/index.js +2 -0
- package/dist/components/content-viewer/callouts/index.js.map +1 -0
- package/dist/components/content-viewer/index.d.ts +21 -0
- package/dist/components/content-viewer/index.d.ts.map +1 -0
- package/dist/components/content-viewer/index.js +29 -0
- package/dist/components/content-viewer/index.js.map +1 -0
- package/dist/components/content-viewer/plugins/index.d.ts +5 -0
- package/dist/components/content-viewer/plugins/index.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/index.js +5 -0
- package/dist/components/content-viewer/plugins/index.js.map +1 -0
- package/dist/components/content-viewer/plugins/lowlightLoader.d.ts +63 -0
- package/dist/components/content-viewer/plugins/lowlightLoader.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/lowlightLoader.js +120 -0
- package/dist/components/content-viewer/plugins/lowlightLoader.js.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeCodeHighlight.d.ts +44 -0
- package/dist/components/content-viewer/plugins/rehypeCodeHighlight.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeCodeHighlight.js +122 -0
- package/dist/components/content-viewer/plugins/rehypeCodeHighlight.js.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeExternalLinks.d.ts +59 -0
- package/dist/components/content-viewer/plugins/rehypeExternalLinks.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeExternalLinks.js +79 -0
- package/dist/components/content-viewer/plugins/rehypeExternalLinks.js.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeHeadingIds.d.ts +37 -0
- package/dist/components/content-viewer/plugins/rehypeHeadingIds.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/rehypeHeadingIds.js +82 -0
- package/dist/components/content-viewer/plugins/rehypeHeadingIds.js.map +1 -0
- package/dist/components/content-viewer/plugins/remarkCallouts.d.ts +39 -0
- package/dist/components/content-viewer/plugins/remarkCallouts.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/remarkCallouts.js +77 -0
- package/dist/components/content-viewer/plugins/remarkCallouts.js.map +1 -0
- package/dist/components/content-viewer/plugins/slugify.d.ts +24 -0
- package/dist/components/content-viewer/plugins/slugify.d.ts.map +1 -0
- package/dist/components/content-viewer/plugins/slugify.js +31 -0
- package/dist/components/content-viewer/plugins/slugify.js.map +1 -0
- package/dist/components/content-viewer/sanitize.d.ts +75 -0
- package/dist/components/content-viewer/sanitize.d.ts.map +1 -0
- package/dist/components/content-viewer/sanitize.js +252 -0
- package/dist/components/content-viewer/sanitize.js.map +1 -0
- package/dist/components/content-viewer/types.d.ts +315 -0
- package/dist/components/content-viewer/types.d.ts.map +1 -0
- package/dist/components/content-viewer/types.js +8 -0
- package/dist/components/content-viewer/types.js.map +1 -0
- package/dist/components/content-viewer/variants.d.ts +71 -0
- package/dist/components/content-viewer/variants.d.ts.map +1 -0
- package/dist/components/content-viewer/variants.js +105 -0
- package/dist/components/content-viewer/variants.js.map +1 -0
- package/dist/content-viewer/ContentPane.d.ts +44 -1
- package/dist/content-viewer/ContentPane.d.ts.map +1 -1
- package/dist/content-viewer/ContentPane.js +139 -5
- package/dist/content-viewer/ContentPane.js.map +1 -1
- package/dist/content-viewer/FileTree.d.ts +23 -1
- package/dist/content-viewer/FileTree.d.ts.map +1 -1
- package/dist/content-viewer/FileTree.js +20 -5
- package/dist/content-viewer/FileTree.js.map +1 -1
- package/dist/content-viewer/index.d.ts +2 -0
- package/dist/content-viewer/index.d.ts.map +1 -1
- package/dist/content-viewer/index.js +2 -0
- package/dist/content-viewer/index.js.map +1 -1
- package/dist/diff/DiffViewer.js +3 -3
- package/dist/diff/DiffViewer.js.map +1 -1
- package/dist/discovery/discovery-card.d.ts +25 -0
- package/dist/discovery/discovery-card.d.ts.map +1 -0
- package/dist/discovery/discovery-card.js +265 -0
- package/dist/discovery/discovery-card.js.map +1 -0
- package/dist/discovery/index.d.ts +3 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +3 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/display/ContextInfoCard.d.ts +61 -0
- package/dist/display/ContextInfoCard.d.ts.map +1 -0
- package/dist/display/ContextInfoCard.js +45 -0
- package/dist/display/ContextInfoCard.js.map +1 -0
- package/dist/display/index.d.ts +2 -0
- package/dist/display/index.d.ts.map +1 -1
- package/dist/display/index.js +1 -0
- package/dist/display/index.js.map +1 -1
- package/dist/editor/CodeEditor.d.ts +39 -0
- package/dist/editor/CodeEditor.d.ts.map +1 -0
- package/dist/editor/CodeEditor.js +114 -0
- package/dist/editor/CodeEditor.js.map +1 -0
- package/dist/editor/MarkdownEditor.d.ts +3 -2
- package/dist/editor/MarkdownEditor.d.ts.map +1 -1
- package/dist/editor/MarkdownEditor.js +32 -80
- package/dist/editor/MarkdownEditor.js.map +1 -1
- package/dist/editor/SplitPreview.d.ts +10 -1
- package/dist/editor/SplitPreview.d.ts.map +1 -1
- package/dist/editor/SplitPreview.js +4 -2
- package/dist/editor/SplitPreview.js.map +1 -1
- package/dist/editor/codeLanguages.d.ts +28 -0
- package/dist/editor/codeLanguages.d.ts.map +1 -0
- package/dist/editor/codeLanguages.js +54 -0
- package/dist/editor/codeLanguages.js.map +1 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +6 -0
- package/dist/editor/index.js.map +1 -1
- package/dist/editor/theme.d.ts +16 -0
- package/dist/editor/theme.d.ts.map +1 -0
- package/dist/editor/theme.js +82 -0
- package/dist/editor/theme.js.map +1 -0
- package/dist/filters/filter-bar.d.ts +14 -0
- package/dist/filters/filter-bar.d.ts.map +1 -0
- package/dist/filters/filter-bar.js +47 -0
- package/dist/filters/filter-bar.js.map +1 -0
- package/dist/filters/filter-slot-config.d.ts +239 -0
- package/dist/filters/filter-slot-config.d.ts.map +1 -0
- package/dist/filters/filter-slot-config.js +24 -0
- package/dist/filters/filter-slot-config.js.map +1 -0
- package/dist/filters/index.d.ts +2 -0
- package/dist/filters/index.d.ts.map +1 -1
- package/dist/filters/index.js +1 -0
- package/dist/filters/index.js.map +1 -1
- package/dist/primitives/Card.d.ts +28 -0
- package/dist/primitives/Card.d.ts.map +1 -0
- package/dist/primitives/Card.js +30 -0
- package/dist/primitives/Card.js.map +1 -0
- package/dist/primitives/CollectionPicker.d.ts +47 -0
- package/dist/primitives/CollectionPicker.d.ts.map +1 -0
- package/dist/primitives/CollectionPicker.js +105 -0
- package/dist/primitives/CollectionPicker.js.map +1 -0
- package/dist/primitives/CreateEntityDialog.d.ts +144 -0
- package/dist/primitives/CreateEntityDialog.d.ts.map +1 -0
- package/dist/primitives/CreateEntityDialog.js +379 -0
- package/dist/primitives/CreateEntityDialog.js.map +1 -0
- package/dist/primitives/FormField.d.ts +29 -0
- package/dist/primitives/FormField.d.ts.map +1 -0
- package/dist/primitives/FormField.js +27 -0
- package/dist/primitives/FormField.js.map +1 -0
- package/dist/primitives/Label.d.ts +20 -0
- package/dist/primitives/Label.d.ts.map +1 -0
- package/dist/primitives/Label.js +21 -0
- package/dist/primitives/Label.js.map +1 -0
- package/dist/primitives/SecretField.d.ts +28 -0
- package/dist/primitives/SecretField.d.ts.map +1 -0
- package/dist/primitives/SecretField.js +65 -0
- package/dist/primitives/SecretField.js.map +1 -0
- package/dist/primitives/Spinner.d.ts +16 -0
- package/dist/primitives/Spinner.d.ts.map +1 -0
- package/dist/primitives/Spinner.js +34 -0
- package/dist/primitives/Spinner.js.map +1 -0
- package/dist/primitives/Switch.d.ts +32 -0
- package/dist/primitives/Switch.d.ts.map +1 -0
- package/dist/primitives/Switch.js +43 -0
- package/dist/primitives/Switch.js.map +1 -0
- package/dist/primitives/index.d.ts +16 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +9 -0
- package/dist/primitives/index.js.map +1 -1
- package/dist/utils/type-colors.d.ts.map +1 -1
- package/dist/utils/type-colors.js +4 -0
- package/dist/utils/type-colors.js.map +1 -1
- package/package.json +40 -6
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* CollectionPicker — @miethe/ui primitive
|
|
5
|
+
*
|
|
6
|
+
* A self-contained collection selection control for use inside creation
|
|
7
|
+
* dialogs. Renders a searchable combobox to pick which collection an artifact
|
|
8
|
+
* belongs to, with optional collapsible wrapping and auto-select when only one
|
|
9
|
+
* collection is available.
|
|
10
|
+
*
|
|
11
|
+
* The component is purely presentational: it accepts a pre-fetched `collections`
|
|
12
|
+
* list and delegates selection state upward via `onChange`. Pre-filling from the
|
|
13
|
+
* active collection context is the consumer's responsibility (pass the resolved
|
|
14
|
+
* ID as `defaultCollectionId`).
|
|
15
|
+
*
|
|
16
|
+
* @example Basic usage
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <CollectionPicker
|
|
19
|
+
* config={{ enabled: true, required: true, collapsible: true }}
|
|
20
|
+
* collections={collections}
|
|
21
|
+
* value={selectedId}
|
|
22
|
+
* onChange={setSelectedId}
|
|
23
|
+
* defaultCollectionId={currentCollectionId}
|
|
24
|
+
* />
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import * as React from 'react';
|
|
28
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
29
|
+
import { ChevronDown, ChevronRight, Library } from 'lucide-react';
|
|
30
|
+
import { SearchableCombobox } from './SearchableCombobox';
|
|
31
|
+
import { cn } from './utils';
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Internal helpers
|
|
34
|
+
// ============================================================================
|
|
35
|
+
/** Filter collections by a search query (case-insensitive name/description match) */
|
|
36
|
+
function filterCollections(items, query) {
|
|
37
|
+
if (!query.trim())
|
|
38
|
+
return items;
|
|
39
|
+
const lower = query.toLowerCase();
|
|
40
|
+
return items.filter((c) => c.name.toLowerCase().includes(lower) ||
|
|
41
|
+
(c.description?.toLowerCase().includes(lower) ?? false));
|
|
42
|
+
}
|
|
43
|
+
function CollectionCombobox({ collections, value, onChange, required, disabled, labelId, }) {
|
|
44
|
+
const [query, setQuery] = React.useState('');
|
|
45
|
+
const filtered = React.useMemo(() => filterCollections(collections, query), [collections, query]);
|
|
46
|
+
const selectedCollection = value ? collections.find((c) => c.id === value) : undefined;
|
|
47
|
+
return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [selectedCollection && (_jsxs("div", { className: cn('flex items-center gap-2 rounded-md border border-border bg-muted/40 px-3 py-2', 'text-sm text-foreground'), "aria-live": "polite", children: [_jsx(Library, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { className: "truncate font-medium", children: selectedCollection.name }), selectedCollection.description && (_jsxs("span", { className: "truncate text-muted-foreground", children: ["\u2014 ", selectedCollection.description] })), !disabled && (_jsx("button", { type: "button", onClick: () => {
|
|
48
|
+
onChange('');
|
|
49
|
+
setQuery('');
|
|
50
|
+
}, className: cn('ml-auto shrink-0 rounded-sm text-muted-foreground', 'hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'), "aria-label": "Clear collection selection", children: _jsx("span", { "aria-hidden": "true", className: "text-xs leading-none", children: "\u00D7" }) }))] })), !disabled && (_jsx(SearchableCombobox, { items: filtered, onSearch: setQuery, onSelect: (item) => {
|
|
51
|
+
onChange(item.id);
|
|
52
|
+
setQuery('');
|
|
53
|
+
}, renderItem: (item) => (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "font-medium", children: item.name }), item.description && (_jsx("span", { className: "text-xs text-muted-foreground", children: item.description }))] })), getItemKey: (item) => item.id, placeholder: "Search collections\u2026", emptyMessage: "No matching collections", "aria-label": "Select collection", "aria-required": required, "aria-labelledby": labelId })), disabled && !selectedCollection && (_jsx("p", { className: "text-xs text-muted-foreground", children: "No collections available." }))] }));
|
|
54
|
+
}
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// CollectionPicker
|
|
57
|
+
// ============================================================================
|
|
58
|
+
export function CollectionPicker({ config, value, onChange, defaultCollectionId, collections, className, }) {
|
|
59
|
+
const required = config.required ?? true;
|
|
60
|
+
const collapsible = config.collapsible ?? true;
|
|
61
|
+
// Auto-select: apply defaultCollectionId on first render if no value is set
|
|
62
|
+
const hasAppliedDefault = React.useRef(false);
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (!hasAppliedDefault.current && !value && defaultCollectionId) {
|
|
65
|
+
const match = collections.find((c) => c.id === defaultCollectionId);
|
|
66
|
+
if (match) {
|
|
67
|
+
onChange(defaultCollectionId);
|
|
68
|
+
}
|
|
69
|
+
hasAppliedDefault.current = true;
|
|
70
|
+
}
|
|
71
|
+
}, [value, defaultCollectionId, collections, onChange]);
|
|
72
|
+
// When only one collection exists, auto-select and render read-only
|
|
73
|
+
const isSingleCollection = collections.length === 1;
|
|
74
|
+
React.useEffect(() => {
|
|
75
|
+
if (isSingleCollection && !value && collections[0]) {
|
|
76
|
+
onChange(collections[0].id);
|
|
77
|
+
}
|
|
78
|
+
}, [isSingleCollection, value, collections, onChange]);
|
|
79
|
+
// Collapsible open state — starts open when a value is already set
|
|
80
|
+
const [isOpen, setIsOpen] = React.useState(() => !collapsible || Boolean(value));
|
|
81
|
+
React.useEffect(() => {
|
|
82
|
+
// Open automatically if a default gets applied
|
|
83
|
+
if (value && collapsible && !isOpen) {
|
|
84
|
+
setIsOpen(true);
|
|
85
|
+
}
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
+
}, [value]);
|
|
88
|
+
// Stable ID for aria-labelledby wiring
|
|
89
|
+
const labelId = React.useId();
|
|
90
|
+
const combobox = (_jsx(CollectionCombobox, { collections: collections, value: value, onChange: onChange, required: required, disabled: isSingleCollection, labelId: labelId }));
|
|
91
|
+
// ── Non-collapsible layout ──────────────────────────────────────────────────
|
|
92
|
+
if (!collapsible) {
|
|
93
|
+
return (_jsxs("section", { className: cn('flex flex-col gap-2 rounded-lg border border-border p-4', className), "aria-label": "Collection selection", children: [_jsx(SectionLabel, { id: labelId, required: required }), combobox] }));
|
|
94
|
+
}
|
|
95
|
+
// ── Collapsible layout ──────────────────────────────────────────────────────
|
|
96
|
+
return (_jsxs(CollapsiblePrimitive.Root, { open: isOpen, onOpenChange: setIsOpen, className: cn('rounded-lg border border-border', className), children: [_jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsxs("button", { type: "button", className: cn('flex w-full items-center justify-between px-4 py-3 text-sm font-medium', 'rounded-t-lg text-left', 'hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring', 'transition-colors', !isOpen && 'rounded-b-lg'), "aria-expanded": isOpen, "aria-controls": `${labelId}-content`, children: [_jsx(SectionLabel, { id: labelId, required: required, asSpan: true }), isOpen ? (_jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" })) : (_jsx(ChevronRight, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }))] }) }), _jsx(CollapsiblePrimitive.Content, { id: `${labelId}-content`, className: cn('overflow-hidden px-4 pb-4 pt-1', 'data-[state=open]:animate-collapsible-down', 'data-[state=closed]:animate-collapsible-up'), children: combobox })] }));
|
|
97
|
+
}
|
|
98
|
+
function SectionLabel({ id, required, asSpan = false }) {
|
|
99
|
+
const content = (_jsxs(_Fragment, { children: [_jsx(Library, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": "true" }), _jsxs("span", { children: ["Collection", required && (_jsx("span", { className: "ml-1 text-destructive", "aria-hidden": "true", children: "*" })), required && _jsx("span", { className: "sr-only", children: "(required)" })] })] }));
|
|
100
|
+
if (asSpan) {
|
|
101
|
+
return (_jsx("span", { id: id, className: "flex items-center gap-2 font-medium", children: content }));
|
|
102
|
+
}
|
|
103
|
+
return (_jsx("label", { id: id, className: "flex items-center gap-2 text-sm font-medium", children: content }));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=CollectionPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CollectionPicker.js","sourceRoot":"","sources":["../../src/primitives/CollectionPicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CreateEntityDialog — @miethe/ui primitive
|
|
3
|
+
*
|
|
4
|
+
* A schema-driven creation dialog for any entity type.
|
|
5
|
+
* Dynamically renders form fields from an `EntityFormSchema` definition using
|
|
6
|
+
* react-hook-form for state management and per-field validation.
|
|
7
|
+
*
|
|
8
|
+
* Only the `simple` mode is fully implemented here. `tabs` and `composite`
|
|
9
|
+
* modes render a placeholder until PRIM-003 / PRIM-004 are complete.
|
|
10
|
+
*
|
|
11
|
+
* @example Simple usage
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <CreateEntityDialog
|
|
14
|
+
* open={isOpen}
|
|
15
|
+
* onOpenChange={setIsOpen}
|
|
16
|
+
* schema={{
|
|
17
|
+
* mode: 'simple',
|
|
18
|
+
* fields: [
|
|
19
|
+
* { name: 'name', label: 'Name', type: 'text', required: true },
|
|
20
|
+
* { name: 'description', label: 'Description', type: 'textarea' },
|
|
21
|
+
* ],
|
|
22
|
+
* }}
|
|
23
|
+
* onSubmit={async (values) => { await create(values); }}
|
|
24
|
+
* title="Create Skill"
|
|
25
|
+
* description="Add a new skill to your collection"
|
|
26
|
+
* />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import * as React from 'react';
|
|
30
|
+
import { type UseFormReturn } from 'react-hook-form';
|
|
31
|
+
export interface FieldOption {
|
|
32
|
+
label: string;
|
|
33
|
+
value: string;
|
|
34
|
+
}
|
|
35
|
+
export type FieldType = 'text' | 'textarea' | 'select' | 'multiselect' | 'number' | 'boolean' | 'tags';
|
|
36
|
+
export interface FieldDef {
|
|
37
|
+
name: string;
|
|
38
|
+
label: string;
|
|
39
|
+
type: FieldType;
|
|
40
|
+
required?: boolean;
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
options?: FieldOption[];
|
|
44
|
+
defaultValue?: unknown;
|
|
45
|
+
/** Optional Zod schema — used for `.parse()` based validation when provided */
|
|
46
|
+
validation?: {
|
|
47
|
+
safeParse: (v: unknown) => {
|
|
48
|
+
success: boolean;
|
|
49
|
+
error?: {
|
|
50
|
+
issues: Array<{
|
|
51
|
+
message: string;
|
|
52
|
+
}>;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface CollectionPickerConfig {
|
|
58
|
+
enabled: boolean;
|
|
59
|
+
required?: boolean;
|
|
60
|
+
collapsible?: boolean;
|
|
61
|
+
defaultCollectionId?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface SimpleFormSchema {
|
|
64
|
+
mode: 'simple';
|
|
65
|
+
fields: FieldDef[];
|
|
66
|
+
collection?: CollectionPickerConfig;
|
|
67
|
+
}
|
|
68
|
+
export interface TabDef {
|
|
69
|
+
id: string;
|
|
70
|
+
label: string;
|
|
71
|
+
/** Optional Lucide-compatible icon component */
|
|
72
|
+
icon?: React.ComponentType<{
|
|
73
|
+
className?: string;
|
|
74
|
+
}>;
|
|
75
|
+
fields: FieldDef[];
|
|
76
|
+
/** Escape hatch: when provided, bypasses field-list rendering for this tab */
|
|
77
|
+
renderTabContent?: (form: UseFormReturn<Record<string, unknown>>) => React.ReactNode;
|
|
78
|
+
}
|
|
79
|
+
export interface TabsFormSchema {
|
|
80
|
+
mode: 'tabs';
|
|
81
|
+
tabs: TabDef[];
|
|
82
|
+
collection?: CollectionPickerConfig;
|
|
83
|
+
}
|
|
84
|
+
export interface MemberPickerConfig {
|
|
85
|
+
entityType: string;
|
|
86
|
+
label: string;
|
|
87
|
+
validateMin?: number;
|
|
88
|
+
validateMax?: number;
|
|
89
|
+
}
|
|
90
|
+
export interface CompositeFormSchema {
|
|
91
|
+
mode: 'composite';
|
|
92
|
+
tabs: TabDef[];
|
|
93
|
+
members: MemberPickerConfig;
|
|
94
|
+
/**
|
|
95
|
+
* Optional custom review step rendered as the final tab.
|
|
96
|
+
* When omitted, a default summary of fields + selected members is shown.
|
|
97
|
+
*/
|
|
98
|
+
renderReviewStep?: (ctx: {
|
|
99
|
+
values: Record<string, unknown>;
|
|
100
|
+
memberIds: string[];
|
|
101
|
+
}) => React.ReactNode;
|
|
102
|
+
collection?: CollectionPickerConfig;
|
|
103
|
+
}
|
|
104
|
+
export type EntityFormSchema = SimpleFormSchema | TabsFormSchema | CompositeFormSchema;
|
|
105
|
+
export interface CollectionItem {
|
|
106
|
+
id: string;
|
|
107
|
+
name: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
}
|
|
110
|
+
export interface CreateEntityDialogProps {
|
|
111
|
+
/** Whether the dialog is open */
|
|
112
|
+
open: boolean;
|
|
113
|
+
/** Called when the dialog open state changes */
|
|
114
|
+
onOpenChange: (open: boolean) => void;
|
|
115
|
+
/** Schema that drives field rendering and validation */
|
|
116
|
+
schema: EntityFormSchema;
|
|
117
|
+
/** Called with form values on submit */
|
|
118
|
+
onSubmit: (values: Record<string, unknown>) => void | Promise<void>;
|
|
119
|
+
/** Dialog title */
|
|
120
|
+
title: string;
|
|
121
|
+
/** Optional subtitle shown below the title */
|
|
122
|
+
description?: string;
|
|
123
|
+
/** Label for the submit button (default: "Create") */
|
|
124
|
+
submitLabel?: string;
|
|
125
|
+
/** When true, submit button shows loading state */
|
|
126
|
+
isSubmitting?: boolean;
|
|
127
|
+
/** Inline error message shown as an alert banner */
|
|
128
|
+
error?: string;
|
|
129
|
+
/** Available collections for the collection picker */
|
|
130
|
+
collections?: CollectionItem[];
|
|
131
|
+
/** Pre-selected collection ID */
|
|
132
|
+
defaultCollectionId?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Controlled member IDs for composite mode.
|
|
135
|
+
* When provided, the composite member picker uses this as the initial value.
|
|
136
|
+
*/
|
|
137
|
+
memberIds?: string[];
|
|
138
|
+
/**
|
|
139
|
+
* Called when the member IDs change in composite mode.
|
|
140
|
+
*/
|
|
141
|
+
onMemberIdsChange?: (ids: string[]) => void;
|
|
142
|
+
}
|
|
143
|
+
export declare function CreateEntityDialog({ open, onOpenChange, schema, onSubmit, title, description, submitLabel, isSubmitting, error, collections, defaultCollectionId, memberIds: controlledMemberIds, onMemberIdsChange: onControlledMemberIdsChange, }: CreateEntityDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
144
|
+
//# sourceMappingURL=CreateEntityDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateEntityDialog.d.ts","sourceRoot":"","sources":["../../src/primitives/CreateEntityDialog.tsx"],"names":[],"mappings":"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"}
|