mdx-artifacts 0.1.2 → 0.2.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/README.md +211 -59
- package/README.zh-CN.md +299 -42
- package/agents/AGENTS.snippet.md +21 -10
- package/artifact-docs/examples/commentable-feedback.mdx +76 -70
- package/artifact-docs/examples/decision-matrix.mdx +122 -50
- package/artifact-docs/examples/layout-composition.mdx +106 -128
- package/artifact-docs/examples/streamlit-style-mixed.mdx +100 -85
- package/dist/lib/cli/{build.js → commands/build.js} +2 -2
- package/dist/lib/cli/{components.js → commands/components.js} +19 -3
- package/dist/lib/cli/{dev.js → commands/dev.js} +2 -2
- package/dist/lib/cli/commands/interactions.d.ts +2 -0
- package/dist/lib/cli/commands/interactions.js +280 -0
- package/dist/lib/cli/commands/review.d.ts +1 -0
- package/dist/lib/cli/commands/review.js +171 -0
- package/dist/lib/cli/commands/scaffold.d.ts +16 -0
- package/dist/lib/cli/commands/scaffold.js +440 -0
- package/dist/lib/cli/commands/validate.d.ts +18 -0
- package/dist/lib/cli/commands/validate.js +311 -0
- package/dist/lib/cli/config/config.d.ts +2 -0
- package/dist/lib/cli/{config.js → config/config.js} +3 -2
- package/dist/lib/cli/{types.d.ts → config/types.d.ts} +2 -1
- package/dist/lib/cli/{vite-artifact.d.ts → dev-server/vite-artifact.d.ts} +3 -3
- package/dist/lib/cli/{vite-artifact.js → dev-server/vite-artifact.js} +170 -10
- package/dist/lib/cli/diagnostics/diagnostics.d.ts +11 -0
- package/dist/lib/cli/diagnostics/diagnostics.js +1 -0
- package/dist/lib/cli/index.js +39 -18
- package/dist/lib/cli/mdx/sortable-list.d.ts +14 -0
- package/dist/lib/cli/mdx/sortable-list.js +520 -0
- package/dist/lib/cli/resources/resource-policy.d.ts +15 -0
- package/dist/lib/cli/resources/resource-policy.js +46 -0
- package/dist/lib/cli/resources/safe-path.d.ts +13 -0
- package/dist/lib/cli/resources/safe-path.js +55 -0
- package/dist/lib/cli/services/interaction-service.d.ts +40 -0
- package/dist/lib/cli/services/interaction-service.js +226 -0
- package/dist/lib/cli/services/review.d.ts +43 -0
- package/dist/lib/cli/{review.js → services/review.js} +34 -172
- package/dist/lib/react/{components → composites/comparison-set}/ComparisonSet.d.ts +1 -1
- package/dist/lib/react/{components → composites/comparison-set}/ComparisonSet.js +3 -3
- package/dist/lib/react/composites/comparison-set/index.d.ts +2 -0
- package/dist/lib/react/composites/comparison-set/index.js +1 -0
- package/dist/lib/react/composites/content-set/ContentItem.d.ts +37 -0
- package/dist/lib/react/composites/content-set/ContentItem.js +49 -0
- package/dist/lib/react/composites/content-set/index.d.ts +2 -0
- package/dist/lib/react/composites/content-set/index.js +1 -0
- package/dist/lib/react/{components → composites/export-panel}/ExportPanel.js +2 -2
- package/dist/lib/react/composites/export-panel/index.d.ts +2 -0
- package/dist/lib/react/composites/export-panel/index.js +1 -0
- package/dist/lib/react/{components → composites/section}/Section.js +1 -1
- package/dist/lib/react/composites/section/index.d.ts +2 -0
- package/dist/lib/react/composites/section/index.js +1 -0
- package/dist/lib/react/index.d.ts +36 -31
- package/dist/lib/react/index.js +18 -15
- package/dist/lib/react/interactions/artifact-state/index.d.ts +1 -0
- package/dist/lib/react/interactions/artifact-state/index.js +1 -0
- package/dist/lib/react/{components → interactions/comments}/Comments.d.ts +2 -2
- package/dist/lib/react/{components → interactions/comments}/Comments.js +3 -3
- package/dist/lib/react/interactions/comments/index.d.ts +1 -0
- package/dist/lib/react/interactions/comments/index.js +1 -0
- package/dist/lib/react/interactions/sortable-list/SortableList.d.ts +29 -0
- package/dist/lib/react/interactions/sortable-list/SortableList.js +282 -0
- package/dist/lib/react/interactions/sortable-list/index.d.ts +1 -0
- package/dist/lib/react/interactions/sortable-list/index.js +1 -0
- package/dist/lib/react/layout/layout-primitives/index.d.ts +2 -0
- package/dist/lib/react/layout/layout-primitives/index.js +1 -0
- package/dist/lib/react/legacy/LegacyContentComponents.d.ts +65 -0
- package/dist/lib/react/legacy/LegacyContentComponents.js +26 -0
- package/dist/lib/react/mdx-components.d.ts +5 -0
- package/dist/lib/react/mdx-components.js +38 -0
- package/dist/lib/react/{components → primitives/annotated-code}/AnnotatedCode.d.ts +1 -1
- package/dist/lib/react/{components → primitives/annotated-code}/AnnotatedCode.js +5 -5
- package/dist/lib/react/primitives/annotated-code/index.d.ts +2 -0
- package/dist/lib/react/primitives/annotated-code/index.js +1 -0
- package/dist/lib/react/primitives/callout/Callout.d.ts +11 -0
- package/dist/lib/react/{components → primitives/callout}/Callout.js +9 -6
- package/dist/lib/react/primitives/callout/index.d.ts +2 -0
- package/dist/lib/react/primitives/callout/index.js +1 -0
- package/dist/lib/react/primitives/code-block/CodeBlock.d.ts +20 -0
- package/dist/lib/react/primitives/code-block/CodeBlock.js +32 -0
- package/dist/lib/react/primitives/code-block/index.d.ts +2 -0
- package/dist/lib/react/primitives/code-block/index.js +1 -0
- package/dist/lib/react/primitives/code-surface/CodeSurface.d.ts +11 -0
- package/dist/lib/react/primitives/code-surface/CodeSurface.js +34 -0
- package/dist/lib/react/primitives/code-surface/index.d.ts +2 -0
- package/dist/lib/react/primitives/code-surface/index.js +1 -0
- package/dist/lib/react/primitives/diff-block/DiffBlock.js +25 -0
- package/dist/lib/react/primitives/diff-block/index.d.ts +2 -0
- package/dist/lib/react/primitives/diff-block/index.js +1 -0
- package/dist/lib/react/{components → primitives/inline-text}/InlineText.d.ts +4 -2
- package/dist/lib/react/primitives/inline-text/InlineText.js +28 -0
- package/dist/lib/react/primitives/inline-text/index.d.ts +2 -0
- package/dist/lib/react/primitives/inline-text/index.js +1 -0
- package/dist/lib/react/primitives/markdown-body/MarkdownBody.d.ts +9 -0
- package/dist/lib/react/primitives/markdown-body/MarkdownBody.js +49 -0
- package/dist/lib/react/primitives/markdown-body/index.d.ts +2 -0
- package/dist/lib/react/primitives/markdown-body/index.js +1 -0
- package/dist/lib/react/primitives/severity-badge/index.d.ts +2 -0
- package/dist/lib/react/primitives/severity-badge/index.js +1 -0
- package/dist/lib/react/registry.d.ts +10 -0
- package/dist/lib/react/registry.js +505 -210
- package/dist/lib/react/styles.css +490 -38
- package/docs/cli-structure.md +141 -0
- package/docs/component-protocol.md +199 -33
- package/docs/component-taxonomy.md +40 -4
- package/docs/design.md +42 -21
- package/docs/design.zh-CN.md +41 -21
- package/docs/naming.md +17 -7
- package/docs/releasing.md +132 -0
- package/docs/testing.md +35 -10
- package/package.json +9 -7
- package/dist/lib/cli/config.d.ts +0 -2
- package/dist/lib/cli/review.d.ts +0 -33
- package/dist/lib/cli/scaffold.d.ts +0 -1
- package/dist/lib/cli/scaffold.js +0 -56
- package/dist/lib/cli/validate.d.ts +0 -6
- package/dist/lib/cli/validate.js +0 -79
- package/dist/lib/react/components/Callout.d.ts +0 -9
- package/dist/lib/react/components/CodeBlock.d.ts +0 -10
- package/dist/lib/react/components/CodeBlock.js +0 -28
- package/dist/lib/react/components/DecisionMatrix.d.ts +0 -16
- package/dist/lib/react/components/DecisionMatrix.js +0 -27
- package/dist/lib/react/components/DiffBlock.js +0 -24
- package/dist/lib/react/components/InlineText.js +0 -18
- package/dist/lib/react/components/MarkdownBody.d.ts +0 -7
- package/dist/lib/react/components/MarkdownBody.js +0 -36
- package/dist/lib/react/components/OptionGrid.d.ts +0 -13
- package/dist/lib/react/components/OptionGrid.js +0 -21
- /package/dist/lib/cli/{build.d.ts → commands/build.d.ts} +0 -0
- /package/dist/lib/cli/{components.d.ts → commands/components.d.ts} +0 -0
- /package/dist/lib/cli/{dev.d.ts → commands/dev.d.ts} +0 -0
- /package/dist/lib/cli/{types.js → config/types.js} +0 -0
- /package/dist/lib/cli/{artifact-state.d.ts → state/artifact-state.d.ts} +0 -0
- /package/dist/lib/cli/{artifact-state.js → state/artifact-state.js} +0 -0
- /package/dist/lib/react/{components → composites/export-panel}/ExportPanel.d.ts +0 -0
- /package/dist/lib/react/{components → composites/section}/Section.d.ts +0 -0
- /package/dist/lib/react/{components → interactions/artifact-state}/ArtifactState.d.ts +0 -0
- /package/dist/lib/react/{components → interactions/artifact-state}/ArtifactState.js +0 -0
- /package/dist/lib/react/{components → layout/layout-primitives}/Layout.d.ts +0 -0
- /package/dist/lib/react/{components → layout/layout-primitives}/Layout.js +0 -0
- /package/dist/lib/react/{components → primitives/diff-block}/DiffBlock.d.ts +0 -0
- /package/dist/lib/react/{components → primitives/severity-badge}/SeverityBadge.d.ts +0 -0
- /package/dist/lib/react/{components → primitives/severity-badge}/SeverityBadge.js +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type ContentItemTone = "neutral" | "info" | "positive" | "warning" | "danger" | "accent";
|
|
3
|
+
export type ContentItemEmphasis = "default" | "primary" | "subtle";
|
|
4
|
+
export type ContentSetLayout = "grid" | "stack";
|
|
5
|
+
export type ContentSetColumns = 2 | 3 | 4 | 5;
|
|
6
|
+
export type ContentSetSurface = "plain" | "subtle" | "outlined";
|
|
7
|
+
export type ContentItemProps = {
|
|
8
|
+
id?: string;
|
|
9
|
+
title: string;
|
|
10
|
+
badge?: string;
|
|
11
|
+
summary?: string;
|
|
12
|
+
icon?: ReactNode;
|
|
13
|
+
tone?: ContentItemTone;
|
|
14
|
+
emphasis?: ContentItemEmphasis;
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
};
|
|
18
|
+
export type ContentSetProps = {
|
|
19
|
+
id?: string;
|
|
20
|
+
title: string;
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
icon?: ReactNode;
|
|
23
|
+
layout?: ContentSetLayout;
|
|
24
|
+
columns?: ContentSetColumns;
|
|
25
|
+
surface?: ContentSetSurface;
|
|
26
|
+
tone?: ContentItemTone;
|
|
27
|
+
emphasis?: ContentItemEmphasis;
|
|
28
|
+
className?: string;
|
|
29
|
+
};
|
|
30
|
+
export type ContentSetItemProps = ContentItemProps;
|
|
31
|
+
export declare function ContentItem({ id, title, badge, summary, icon, tone, emphasis, children, className }: ContentItemProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
declare function ContentSetRoot({ id, title, children, icon, layout, columns, surface, tone, emphasis, className }: ContentSetProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
declare function ContentSetItem({ id, title, badge, summary, icon, tone, emphasis, children, className }: ContentSetItemProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export declare const ContentSet: typeof ContentSetRoot & {
|
|
35
|
+
Item: typeof ContentSetItem;
|
|
36
|
+
};
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
import { CommentTarget } from "../../interactions/comments/Comments.js";
|
|
4
|
+
import { InlineText } from "../../primitives/inline-text/InlineText.js";
|
|
5
|
+
const ContentSetContext = createContext(null);
|
|
6
|
+
export function ContentItem({ id, title, badge, summary, icon, tone = "neutral", emphasis = "default", children, className }) {
|
|
7
|
+
return (_jsx(ContentItemCard, { badge: badge, className: className, description: "ContentItem component", emphasis: emphasis, icon: icon, summary: summary, targetId: id ?? `content:${slugify(title)}`, title: title, tone: tone, children: children }));
|
|
8
|
+
}
|
|
9
|
+
function ContentSetRoot({ id, title, children, icon, layout = "grid", columns = 3, surface = "plain", tone, emphasis, className }) {
|
|
10
|
+
const targetId = id ?? `content-set:${slugify(title)}`;
|
|
11
|
+
return (_jsx(CommentTarget, { className: classNames("ak-comment-target-section", className), description: "ContentSet component", targetId: targetId, title: title, children: _jsxs("section", { className: classNames("ak-section", "ak-content-set", `ak-content-set-${layout}`, `ak-content-set-surface-${surface}`), children: [_jsxs("div", { className: "ak-section-header", children: [_jsx("p", { className: "ak-eyebrow", children: "Content Set" }), _jsxs("div", { className: "ak-content-set-title-row", children: [icon ? (_jsx("span", { "aria-hidden": "true", className: "ak-content-set-icon", children: icon })) : null, _jsx(InlineText, { as: "h2", variant: "title", children: title })] })] }), _jsx("div", { className: classNames("ak-content-set-items", `ak-content-set-items-${layout}`), style: cssVars({ "--ak-content-set-columns": String(columns) }), children: _jsx(ContentSetContext.Provider, { value: { id, title, tone, emphasis }, children: children }) })] }) }));
|
|
12
|
+
}
|
|
13
|
+
function ContentSetItem({ id, title, badge, summary, icon, tone, emphasis, children, className }) {
|
|
14
|
+
const context = useContext(ContentSetContext);
|
|
15
|
+
const resolvedTone = tone ?? context?.tone ?? "neutral";
|
|
16
|
+
const resolvedEmphasis = emphasis ?? context?.emphasis ?? "default";
|
|
17
|
+
const targetId = createItemTargetId(context?.id, context?.title, id, title);
|
|
18
|
+
return (_jsx(ContentItemCard, { badge: badge, className: className, description: context ? `ContentSet item in ${context.title}` : "ContentSet item", emphasis: resolvedEmphasis, icon: icon, summary: summary, targetId: targetId, title: title, tone: resolvedTone, children: children }));
|
|
19
|
+
}
|
|
20
|
+
function ContentItemCard({ badge, children, className, description, emphasis, icon, summary, targetId, title, tone }) {
|
|
21
|
+
return (_jsx(CommentTarget, { className: classNames("ak-comment-target-card", className), description: description, targetId: targetId, title: title, children: _jsxs("article", { className: classNames("ak-content-item", `ak-content-item-tone-${tone}`, `ak-content-item-emphasis-${emphasis}`), children: [_jsxs("div", { className: "ak-content-item-header", children: [_jsxs("div", { className: "ak-content-item-title-row", children: [icon ? (_jsx("span", { "aria-hidden": "true", className: "ak-content-item-icon", children: icon })) : null, _jsx(InlineText, { as: "h3", variant: "subtitle", children: title })] }), badge ? _jsx("span", { className: "ak-content-item-badge", children: badge }) : null] }), summary ? (_jsx(InlineText, { as: "p", className: "ak-content-item-summary", children: summary })) : null, children ? _jsx("div", { className: "ak-content-item-body", children: children }) : null] }) }));
|
|
22
|
+
}
|
|
23
|
+
export const ContentSet = Object.assign(ContentSetRoot, {
|
|
24
|
+
Item: ContentSetItem
|
|
25
|
+
});
|
|
26
|
+
function createItemTargetId(parentId, parentTitle, itemId, itemTitle) {
|
|
27
|
+
if (parentId) {
|
|
28
|
+
return `${parentId}.${itemId ?? slugify(itemTitle)}`;
|
|
29
|
+
}
|
|
30
|
+
if (parentTitle) {
|
|
31
|
+
return itemId ?? `content-set:${slugify(parentTitle)}:${slugify(itemTitle)}`;
|
|
32
|
+
}
|
|
33
|
+
return itemId ?? `content:${slugify(itemTitle)}`;
|
|
34
|
+
}
|
|
35
|
+
function cssVars(values) {
|
|
36
|
+
return values;
|
|
37
|
+
}
|
|
38
|
+
function classNames(...values) {
|
|
39
|
+
return values.filter(Boolean).join(" ");
|
|
40
|
+
}
|
|
41
|
+
function slugify(value) {
|
|
42
|
+
const slug = value
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/[`*_~[\]()]/g, "")
|
|
45
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
46
|
+
.replace(/^-+|-+$/g, "")
|
|
47
|
+
.slice(0, 64);
|
|
48
|
+
return slug || "item";
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ContentItem, ContentSet } from "./ContentItem.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as Tabs from "@radix-ui/react-tabs";
|
|
3
3
|
import { useMemo, useState } from "react";
|
|
4
|
-
import { serializeCommentsToMarkdown, useOptionalCommentExportValue } from "
|
|
5
|
-
import { InlineText } from "
|
|
4
|
+
import { serializeCommentsToMarkdown, useOptionalCommentExportValue } from "../../interactions/comments/Comments.js";
|
|
5
|
+
import { InlineText } from "../../primitives/inline-text/InlineText.js";
|
|
6
6
|
export function ExportPanel({ title = "Export Result", formats = ["markdown", "json"], value }) {
|
|
7
7
|
const [format, setFormat] = useState(formats[0] ?? "markdown");
|
|
8
8
|
const [source, setSource] = useState("result");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ExportPanel } from "./ExportPanel.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Children, isValidElement } from "react";
|
|
3
|
-
import { CommentTarget } from "
|
|
3
|
+
import { CommentTarget } from "../../interactions/comments/Comments.js";
|
|
4
4
|
export function Section({ id, children, className }) {
|
|
5
5
|
const title = getFirstHeadingText(children) ?? id;
|
|
6
6
|
return (_jsx(CommentTarget, { className: classNames("ak-comment-target-section", className), targetId: id, title: title, children: _jsx("div", { className: "ak-section ak-content-section", children: children }) }));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Section } from "./Section.js";
|
|
@@ -1,33 +1,38 @@
|
|
|
1
|
-
export { AnnotatedCode } from "./
|
|
2
|
-
export type { AnnotatedCodeProps, CodeAnnotation } from "./
|
|
3
|
-
export { ArtifactStateProvider, createArtifactCommentsFromState, createArtifactStateFromComments, useOptionalArtifactState } from "./
|
|
4
|
-
export type { ArtifactStateComment, ArtifactStateMessage, ArtifactStateMeta, ArtifactStateProviderProps, ArtifactStateStatus, ArtifactStateThread, ArtifactStateValue } from "./
|
|
5
|
-
export { Callout } from "./
|
|
6
|
-
export type { CalloutProps, CalloutTone } from "./
|
|
7
|
-
export { ComparisonSet } from "./
|
|
8
|
-
export type { ComparisonSetItemProps, ComparisonSetProps } from "./
|
|
9
|
-
export {
|
|
10
|
-
export type {
|
|
11
|
-
export {
|
|
12
|
-
export type {
|
|
13
|
-
export {
|
|
14
|
-
export type {
|
|
15
|
-
export {
|
|
16
|
-
export type {
|
|
17
|
-
export {
|
|
18
|
-
export type {
|
|
19
|
-
export {
|
|
20
|
-
export type {
|
|
21
|
-
export {
|
|
22
|
-
export type {
|
|
23
|
-
export {
|
|
24
|
-
export type {
|
|
25
|
-
export {
|
|
26
|
-
export type {
|
|
27
|
-
export {
|
|
28
|
-
export type {
|
|
29
|
-
export {
|
|
30
|
-
export
|
|
1
|
+
export { AnnotatedCode } from "./primitives/annotated-code/AnnotatedCode";
|
|
2
|
+
export type { AnnotatedCodeProps, CodeAnnotation } from "./primitives/annotated-code/AnnotatedCode";
|
|
3
|
+
export { ArtifactStateProvider, createArtifactCommentsFromState, createArtifactStateFromComments, useOptionalArtifactState } from "./interactions/artifact-state/ArtifactState";
|
|
4
|
+
export type { ArtifactStateComment, ArtifactStateMessage, ArtifactStateMeta, ArtifactStateProviderProps, ArtifactStateStatus, ArtifactStateThread, ArtifactStateValue } from "./interactions/artifact-state/ArtifactState";
|
|
5
|
+
export { Callout } from "./primitives/callout/Callout";
|
|
6
|
+
export type { CalloutProps, CalloutTone } from "./primitives/callout/Callout";
|
|
7
|
+
export { ComparisonSet } from "./composites/comparison-set/ComparisonSet";
|
|
8
|
+
export type { ComparisonSetItemProps, ComparisonSetProps } from "./composites/comparison-set/ComparisonSet";
|
|
9
|
+
export { ContentItem, ContentSet } from "./composites/content-set/ContentItem";
|
|
10
|
+
export type { ContentItemEmphasis, ContentItemProps, ContentItemTone, ContentSetColumns, ContentSetItemProps, ContentSetLayout, ContentSetSurface, ContentSetProps } from "./composites/content-set/ContentItem";
|
|
11
|
+
export { DecisionMatrix, OptionGrid } from "./legacy/LegacyContentComponents";
|
|
12
|
+
export type { DecisionMatrixOptionProps, DecisionMatrixProps, OptionGridItemProps, OptionGridProps } from "./legacy/LegacyContentComponents";
|
|
13
|
+
export { CodeBlock, CodeBlockView } from "./primitives/code-block/CodeBlock";
|
|
14
|
+
export type { CodeBlockProps, CodeBlockViewProps } from "./primitives/code-block/CodeBlock";
|
|
15
|
+
export { CodeSurface } from "./primitives/code-surface/CodeSurface";
|
|
16
|
+
export type { CodeSurfaceProps } from "./primitives/code-surface/CodeSurface";
|
|
17
|
+
export { CommentableBlock, CommentExport, CommentLayer, CommentTarget, serializeCommentsToMarkdown, useOptionalCommentExportValue } from "./interactions/comments/Comments";
|
|
18
|
+
export type { ArtifactComment, CommentableBlockProps, CommentExportFormat, CommentExportProps, CommentExportValue, CommentLayerProps, CommentTargetProps } from "./interactions/comments/Comments";
|
|
19
|
+
export { DiffBlock } from "./primitives/diff-block/DiffBlock";
|
|
20
|
+
export type { DiffBlockProps, DiffLine, DiffLineType } from "./primitives/diff-block/DiffBlock";
|
|
21
|
+
export { ExportPanel } from "./composites/export-panel/ExportPanel";
|
|
22
|
+
export type { ExportFormat, ExportPanelProps } from "./composites/export-panel/ExportPanel";
|
|
23
|
+
export { InlineText } from "./primitives/inline-text/InlineText";
|
|
24
|
+
export type { InlineTextAs, InlineTextProps, InlineTextVariant } from "./primitives/inline-text/InlineText";
|
|
25
|
+
export { Columns, Frame, Grid, SplitPane, Stack } from "./layout/layout-primitives/Layout";
|
|
26
|
+
export type { AkCollapseAt, AkGap, AkSurface, ColumnsProps, ColumnsRatio, FrameProps, GridProps, SplitPaneProps, SplitPaneRatio, StackProps } from "./layout/layout-primitives/Layout";
|
|
27
|
+
export { MarkdownBody } from "./primitives/markdown-body/MarkdownBody";
|
|
28
|
+
export type { MarkdownBodyProps, MarkdownBodyVariant } from "./primitives/markdown-body/MarkdownBody";
|
|
29
|
+
export { artifactMdxComponents, ArtifactCodePre } from "./mdx-components";
|
|
30
|
+
export { Section } from "./composites/section/Section";
|
|
31
|
+
export type { SectionProps } from "./composites/section/Section";
|
|
32
|
+
export { SeverityBadge } from "./primitives/severity-badge/SeverityBadge";
|
|
33
|
+
export type { SeverityBadgeProps, SeverityLevel } from "./primitives/severity-badge/SeverityBadge";
|
|
34
|
+
export { SortableList, createSortableListInteraction, reorderIds, resolveSortableListOrder } from "./interactions/sortable-list/SortableList";
|
|
35
|
+
export type { SortableListInteraction, SortableListItem, SortableListProps, SortableListSurface } from "./interactions/sortable-list/SortableList";
|
|
31
36
|
export { componentRegistry, findComponentMeta } from "./registry";
|
|
32
37
|
export type { ComponentMeta, ComponentPropMeta } from "./registry";
|
|
33
|
-
export type {
|
|
38
|
+
export type { MdxArtifactsConfig } from "../cli/config/types";
|
package/dist/lib/react/index.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
export { AnnotatedCode } from "./
|
|
2
|
-
export { ArtifactStateProvider, createArtifactCommentsFromState, createArtifactStateFromComments, useOptionalArtifactState } from "./
|
|
3
|
-
export { Callout } from "./
|
|
4
|
-
export { ComparisonSet } from "./
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
1
|
+
export { AnnotatedCode } from "./primitives/annotated-code/AnnotatedCode.js";
|
|
2
|
+
export { ArtifactStateProvider, createArtifactCommentsFromState, createArtifactStateFromComments, useOptionalArtifactState } from "./interactions/artifact-state/ArtifactState.js";
|
|
3
|
+
export { Callout } from "./primitives/callout/Callout.js";
|
|
4
|
+
export { ComparisonSet } from "./composites/comparison-set/ComparisonSet.js";
|
|
5
|
+
export { ContentItem, ContentSet } from "./composites/content-set/ContentItem.js";
|
|
6
|
+
export { DecisionMatrix, OptionGrid } from "./legacy/LegacyContentComponents.js";
|
|
7
|
+
export { CodeBlock, CodeBlockView } from "./primitives/code-block/CodeBlock.js";
|
|
8
|
+
export { CodeSurface } from "./primitives/code-surface/CodeSurface.js";
|
|
9
|
+
export { CommentableBlock, CommentExport, CommentLayer, CommentTarget, serializeCommentsToMarkdown, useOptionalCommentExportValue } from "./interactions/comments/Comments.js";
|
|
10
|
+
export { DiffBlock } from "./primitives/diff-block/DiffBlock.js";
|
|
11
|
+
export { ExportPanel } from "./composites/export-panel/ExportPanel.js";
|
|
12
|
+
export { InlineText } from "./primitives/inline-text/InlineText.js";
|
|
13
|
+
export { Columns, Frame, Grid, SplitPane, Stack } from "./layout/layout-primitives/Layout.js";
|
|
14
|
+
export { MarkdownBody } from "./primitives/markdown-body/MarkdownBody.js";
|
|
15
|
+
export { artifactMdxComponents, ArtifactCodePre } from "./mdx-components.js";
|
|
16
|
+
export { Section } from "./composites/section/Section.js";
|
|
17
|
+
export { SeverityBadge } from "./primitives/severity-badge/SeverityBadge.js";
|
|
18
|
+
export { SortableList, createSortableListInteraction, reorderIds, resolveSortableListOrder } from "./interactions/sortable-list/SortableList.js";
|
|
16
19
|
export { componentRegistry, findComponentMeta } from "./registry.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ArtifactState";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ArtifactState.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import { type ArtifactStateMessage, type ArtifactStateReviewThread } from "
|
|
3
|
-
export { createArtifactCommentsFromState, createArtifactThreadsFromState } from "
|
|
2
|
+
import { type ArtifactStateMessage, type ArtifactStateReviewThread } from "../artifact-state/ArtifactState";
|
|
3
|
+
export { createArtifactCommentsFromState, createArtifactThreadsFromState } from "../artifact-state/ArtifactState";
|
|
4
4
|
export type ArtifactComment = {
|
|
5
5
|
id: string;
|
|
6
6
|
blockId: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import * as Tabs from "@radix-ui/react-tabs";
|
|
4
|
-
import { createArtifactThreadsFromState as createThreadsFromState, useOptionalArtifactState } from "
|
|
5
|
-
import { InlineText } from "
|
|
6
|
-
export { createArtifactCommentsFromState, createArtifactThreadsFromState } from "
|
|
4
|
+
import { createArtifactThreadsFromState as createThreadsFromState, useOptionalArtifactState } from "../artifact-state/ArtifactState.js";
|
|
5
|
+
import { InlineText } from "../../primitives/inline-text/InlineText.js";
|
|
6
|
+
export { createArtifactCommentsFromState, createArtifactThreadsFromState } from "../artifact-state/ArtifactState.js";
|
|
7
7
|
const CommentContext = createContext(null);
|
|
8
8
|
export function CommentLayer({ children }) {
|
|
9
9
|
const artifactState = useOptionalArtifactState();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Comments";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Comments.js";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type SortableListSurface = "plain" | "subtle" | "outlined";
|
|
2
|
+
export type SortableListItem = {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
summary?: string;
|
|
6
|
+
badge?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type SortableListInteraction = {
|
|
11
|
+
type: "sortable-list";
|
|
12
|
+
id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
orderedIds: string[];
|
|
15
|
+
orderedItems: SortableListItem[];
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
};
|
|
18
|
+
export type SortableListProps = {
|
|
19
|
+
id: string;
|
|
20
|
+
title: string;
|
|
21
|
+
summary?: string;
|
|
22
|
+
items: SortableListItem[];
|
|
23
|
+
surface?: SortableListSurface;
|
|
24
|
+
className?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function SortableList({ id, title, summary, items, surface, className }: SortableListProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export declare function createSortableListInteraction(id: string, title: string, orderedIds: string[], items: SortableListItem[]): SortableListInteraction;
|
|
28
|
+
export declare function resolveSortableListOrder(items: SortableListItem[], orderedIds: string[] | undefined): string[];
|
|
29
|
+
export declare function reorderIds(orderedIds: string[], activeId: string, targetId: string): string[];
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { useOptionalArtifactState } from "../artifact-state/ArtifactState.js";
|
|
4
|
+
import { CommentTarget } from "../comments/Comments.js";
|
|
5
|
+
import { InlineText } from "../../primitives/inline-text/InlineText.js";
|
|
6
|
+
export function SortableList({ id, title, summary, items, surface = "outlined", className }) {
|
|
7
|
+
const artifactState = useOptionalArtifactState();
|
|
8
|
+
const writable = artifactState?.meta.daemon?.writable === true;
|
|
9
|
+
const persistedInteraction = artifactState?.state?.interactions[id];
|
|
10
|
+
const persistedOrder = useMemo(() => getPersistedOrder(persistedInteraction), [persistedInteraction]);
|
|
11
|
+
const [currentItems, setCurrentItems] = useState(items);
|
|
12
|
+
const [orderedIds, setOrderedIds] = useState(() => resolveSortableListOrder(currentItems, persistedOrder));
|
|
13
|
+
const [draggingId, setDraggingId] = useState();
|
|
14
|
+
const [editorMode, setEditorMode] = useState();
|
|
15
|
+
const [editingItemId, setEditingItemId] = useState();
|
|
16
|
+
const [draft, setDraft] = useState(() => createEmptyDraft());
|
|
17
|
+
const [editorStatus, setEditorStatus] = useState("idle");
|
|
18
|
+
const [editorError, setEditorError] = useState();
|
|
19
|
+
const orderedItems = useMemo(() => orderItems(currentItems, orderedIds), [currentItems, orderedIds]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
setCurrentItems(items);
|
|
22
|
+
}, [items]);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setOrderedIds(resolveSortableListOrder(currentItems, persistedOrder));
|
|
25
|
+
}, [currentItems, persistedOrder]);
|
|
26
|
+
function commitOrder(nextOrderedIds) {
|
|
27
|
+
setOrderedIds(nextOrderedIds);
|
|
28
|
+
if (!artifactState?.state) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const nextState = {
|
|
32
|
+
...artifactState.state,
|
|
33
|
+
interactions: {
|
|
34
|
+
...artifactState.state.interactions,
|
|
35
|
+
[id]: createSortableListInteraction(id, title, nextOrderedIds, currentItems)
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
void artifactState.actions.saveState(nextState);
|
|
39
|
+
}
|
|
40
|
+
function moveItem(activeId, targetId) {
|
|
41
|
+
const activeItem = currentItems.find((item) => item.id === activeId);
|
|
42
|
+
if (!activeItem || activeItem.disabled || activeId === targetId) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
commitOrder(reorderIds(orderedIds, activeId, targetId));
|
|
46
|
+
}
|
|
47
|
+
function moveByOffset(itemId, offset) {
|
|
48
|
+
const item = currentItems.find((candidate) => candidate.id === itemId);
|
|
49
|
+
if (!item || item.disabled) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const index = orderedIds.indexOf(itemId);
|
|
53
|
+
const targetId = orderedIds[index + offset];
|
|
54
|
+
if (!targetId) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const nextOrderedIds = [...orderedIds];
|
|
58
|
+
nextOrderedIds.splice(index, 1);
|
|
59
|
+
nextOrderedIds.splice(index + offset, 0, itemId);
|
|
60
|
+
commitOrder(nextOrderedIds);
|
|
61
|
+
}
|
|
62
|
+
function handleDragStart(event, itemId) {
|
|
63
|
+
setDraggingId(itemId);
|
|
64
|
+
event.dataTransfer.effectAllowed = "move";
|
|
65
|
+
event.dataTransfer.setData("text/plain", itemId);
|
|
66
|
+
}
|
|
67
|
+
function handleDragOver(event, targetId) {
|
|
68
|
+
const activeId = draggingId ?? event.dataTransfer.getData("text/plain");
|
|
69
|
+
if (!activeId || activeId === targetId) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
event.dataTransfer.dropEffect = "move";
|
|
74
|
+
}
|
|
75
|
+
function handleDrop(event, targetId) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
const activeId = event.dataTransfer.getData("text/plain") || draggingId;
|
|
78
|
+
if (activeId) {
|
|
79
|
+
moveItem(activeId, targetId);
|
|
80
|
+
}
|
|
81
|
+
setDraggingId(undefined);
|
|
82
|
+
}
|
|
83
|
+
function startAddItem() {
|
|
84
|
+
setEditorMode("add");
|
|
85
|
+
setEditingItemId(undefined);
|
|
86
|
+
setDraft(createEmptyDraft());
|
|
87
|
+
setEditorStatus("idle");
|
|
88
|
+
setEditorError(undefined);
|
|
89
|
+
}
|
|
90
|
+
function startEditItem(item) {
|
|
91
|
+
setEditorMode("edit");
|
|
92
|
+
setEditingItemId(item.id);
|
|
93
|
+
setDraft(createDraftFromItem(item));
|
|
94
|
+
setEditorStatus("idle");
|
|
95
|
+
setEditorError(undefined);
|
|
96
|
+
}
|
|
97
|
+
function cancelEdit() {
|
|
98
|
+
setEditorMode(undefined);
|
|
99
|
+
setEditingItemId(undefined);
|
|
100
|
+
setDraft(createEmptyDraft());
|
|
101
|
+
setEditorStatus("idle");
|
|
102
|
+
setEditorError(undefined);
|
|
103
|
+
}
|
|
104
|
+
async function saveDraft() {
|
|
105
|
+
if (!editorMode || editorStatus === "saving") {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const nextItem = createItemFromDraft(draft);
|
|
109
|
+
if (!nextItem.id || !nextItem.title) {
|
|
110
|
+
setEditorStatus("error");
|
|
111
|
+
setEditorError("Item id and title are required.");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
setEditorStatus("saving");
|
|
116
|
+
setEditorError(undefined);
|
|
117
|
+
if (editorMode === "add") {
|
|
118
|
+
await postInteraction("/__artifact/interactions/add-item", {
|
|
119
|
+
id,
|
|
120
|
+
item: nextItem,
|
|
121
|
+
afterId: orderedIds[orderedIds.length - 1]
|
|
122
|
+
});
|
|
123
|
+
const nextItems = [...currentItems, nextItem];
|
|
124
|
+
setCurrentItems(nextItems);
|
|
125
|
+
setOrderedIds(resolveSortableListOrder(nextItems, [...orderedIds, nextItem.id]));
|
|
126
|
+
}
|
|
127
|
+
else if (editingItemId) {
|
|
128
|
+
const patch = createPatchFromDraft(draft);
|
|
129
|
+
await postInteraction("/__artifact/interactions/update-item", {
|
|
130
|
+
id,
|
|
131
|
+
itemId: editingItemId,
|
|
132
|
+
patch: createPatchPayloadFromDraft(draft)
|
|
133
|
+
});
|
|
134
|
+
const nextItems = currentItems.map((item) => (item.id === editingItemId ? { ...item, ...patch } : item));
|
|
135
|
+
setCurrentItems(nextItems);
|
|
136
|
+
}
|
|
137
|
+
cancelEdit();
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
setEditorStatus("error");
|
|
141
|
+
setEditorError(error instanceof Error ? error.message : String(error));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function deleteItem(item) {
|
|
145
|
+
if (!window.confirm(`Delete ${item.title}?`)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
await postInteraction("/__artifact/interactions/remove-item", {
|
|
150
|
+
id,
|
|
151
|
+
itemId: item.id
|
|
152
|
+
});
|
|
153
|
+
const nextItems = currentItems.filter((candidate) => candidate.id !== item.id);
|
|
154
|
+
setCurrentItems(nextItems);
|
|
155
|
+
setOrderedIds(orderedIds.filter((itemId) => itemId !== item.id));
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
setEditorStatus("error");
|
|
159
|
+
setEditorError(error instanceof Error ? error.message : String(error));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return (_jsx(CommentTarget, { className: classNames("ak-comment-target-section", className), description: "SortableList component", targetId: id, title: title, children: _jsxs("section", { className: classNames("ak-section", "ak-sortable-list", `ak-surface-${surface}`, "ak-padding-md"), children: [_jsxs("div", { className: "ak-section-header", children: [_jsx("p", { className: "ak-eyebrow", children: "Sortable List" }), _jsx(InlineText, { as: "h2", text: title, variant: "title" }), summary ? _jsx(InlineText, { as: "p", className: "ak-sortable-list-summary", text: summary }) : null, writable ? (_jsx("div", { className: "ak-sortable-list-editor-actions", children: _jsx("button", { className: "ak-sortable-list-control", onClick: startAddItem, type: "button", children: "Add item" }) })) : null] }), writable && editorMode ? (_jsx(SortableListEditor, { draft: draft, itemIdLocked: editorMode === "edit", onCancel: cancelEdit, onChange: setDraft, onSave: saveDraft, status: editorStatus })) : null, editorError ? _jsx("p", { className: "ak-sortable-list-editor-error", children: editorError }) : null, _jsx("ol", { className: "ak-sortable-list-items", children: orderedItems.map((item, index) => (_jsxs("li", { className: classNames("ak-sortable-list-item", item.disabled ? "ak-sortable-list-item-disabled" : undefined), draggable: !item.disabled, onDragEnd: () => setDraggingId(undefined), onDragOver: (event) => handleDragOver(event, item.id), onDragStart: (event) => handleDragStart(event, item.id), onDrop: (event) => handleDrop(event, item.id), children: [_jsx("div", { className: "ak-sortable-list-rank", children: index + 1 }), _jsxs("div", { className: "ak-sortable-list-content", children: [_jsxs("div", { className: "ak-sortable-list-item-header", children: [_jsx(InlineText, { as: "h3", text: item.title, variant: "subtitle" }), item.badge ? _jsx("span", { className: "ak-sortable-list-badge", children: item.badge }) : null] }), item.summary ? _jsx(InlineText, { as: "p", className: "ak-sortable-list-item-summary", text: item.summary }) : null, item.tags?.length ? (_jsx("div", { className: "ak-sortable-list-tags", "aria-label": `${item.title} tags`, children: item.tags.map((tag) => (_jsx("span", { className: "ak-sortable-list-tag", children: tag }, tag))) })) : null] }), _jsxs("div", { className: "ak-sortable-list-controls", children: [_jsx("button", { "aria-label": `Move ${item.title} up`, className: "ak-sortable-list-control", disabled: item.disabled || index === 0, onClick: () => moveByOffset(item.id, -1), type: "button", children: "Up" }), _jsx("button", { "aria-label": `Move ${item.title} down`, className: "ak-sortable-list-control", disabled: item.disabled || index === orderedItems.length - 1, onClick: () => moveByOffset(item.id, 1), type: "button", children: "Down" }), writable ? (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": `Edit ${item.title}`, className: "ak-sortable-list-control", onClick: () => startEditItem(item), type: "button", children: "Edit" }), _jsx("button", { "aria-label": `Delete ${item.title}`, className: "ak-sortable-list-control", onClick: () => void deleteItem(item), type: "button", children: "Delete" })] })) : null] })] }, item.id))) })] }) }));
|
|
163
|
+
}
|
|
164
|
+
function SortableListEditor({ draft, itemIdLocked, onCancel, onChange, onSave, status }) {
|
|
165
|
+
return (_jsxs("div", { className: "ak-sortable-list-editor", children: [_jsxs("label", { className: "ak-sortable-list-editor-field", children: [_jsx("span", { children: "Id" }), _jsx("input", { disabled: itemIdLocked, onChange: (event) => onChange({ ...draft, id: event.currentTarget.value }), value: draft.id })] }), _jsxs("label", { className: "ak-sortable-list-editor-field", children: [_jsx("span", { children: "Title" }), _jsx("input", { onChange: (event) => onChange({ ...draft, title: event.currentTarget.value }), value: draft.title })] }), _jsxs("label", { className: "ak-sortable-list-editor-field", children: [_jsx("span", { children: "Summary" }), _jsx("input", { onChange: (event) => onChange({ ...draft, summary: event.currentTarget.value }), value: draft.summary })] }), _jsxs("label", { className: "ak-sortable-list-editor-field", children: [_jsx("span", { children: "Badge" }), _jsx("input", { onChange: (event) => onChange({ ...draft, badge: event.currentTarget.value }), value: draft.badge })] }), _jsxs("label", { className: "ak-sortable-list-editor-field", children: [_jsx("span", { children: "Tags" }), _jsx("input", { onChange: (event) => onChange({ ...draft, tags: event.currentTarget.value }), value: draft.tags })] }), _jsxs("label", { className: "ak-sortable-list-editor-check", children: [_jsx("input", { checked: draft.disabled, onChange: (event) => onChange({ ...draft, disabled: event.currentTarget.checked }), type: "checkbox" }), _jsx("span", { children: "Disabled" })] }), _jsxs("div", { className: "ak-sortable-list-editor-buttons", children: [_jsx("button", { className: "ak-sortable-list-control", disabled: status === "saving", onClick: onSave, type: "button", children: "Save" }), _jsx("button", { className: "ak-sortable-list-control", onClick: onCancel, type: "button", children: "Cancel" })] })] }));
|
|
166
|
+
}
|
|
167
|
+
function createEmptyDraft() {
|
|
168
|
+
return {
|
|
169
|
+
id: "",
|
|
170
|
+
title: "",
|
|
171
|
+
summary: "",
|
|
172
|
+
badge: "",
|
|
173
|
+
tags: "",
|
|
174
|
+
disabled: false
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function createDraftFromItem(item) {
|
|
178
|
+
return {
|
|
179
|
+
id: item.id,
|
|
180
|
+
title: item.title,
|
|
181
|
+
summary: item.summary ?? "",
|
|
182
|
+
badge: item.badge ?? "",
|
|
183
|
+
tags: item.tags?.join(", ") ?? "",
|
|
184
|
+
disabled: item.disabled ?? false
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function createItemFromDraft(draft) {
|
|
188
|
+
return {
|
|
189
|
+
id: draft.id.trim(),
|
|
190
|
+
title: draft.title.trim(),
|
|
191
|
+
...createPatchFromDraft(draft)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function createPatchFromDraft(draft) {
|
|
195
|
+
return {
|
|
196
|
+
title: draft.title.trim(),
|
|
197
|
+
summary: draft.summary.trim() || undefined,
|
|
198
|
+
badge: draft.badge.trim() || undefined,
|
|
199
|
+
tags: parseTagDraft(draft.tags),
|
|
200
|
+
disabled: draft.disabled
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function createPatchPayloadFromDraft(draft) {
|
|
204
|
+
return {
|
|
205
|
+
title: draft.title.trim(),
|
|
206
|
+
summary: draft.summary.trim() || null,
|
|
207
|
+
badge: draft.badge.trim() || null,
|
|
208
|
+
tags: parseTagDraft(draft.tags) ?? null,
|
|
209
|
+
disabled: draft.disabled
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function parseTagDraft(value) {
|
|
213
|
+
const tags = value
|
|
214
|
+
.split(",")
|
|
215
|
+
.map((tag) => tag.trim())
|
|
216
|
+
.filter(Boolean);
|
|
217
|
+
return tags.length > 0 ? tags : undefined;
|
|
218
|
+
}
|
|
219
|
+
async function postInteraction(path, body) {
|
|
220
|
+
const response = await fetch(path, {
|
|
221
|
+
method: "POST",
|
|
222
|
+
headers: { "content-type": "application/json" },
|
|
223
|
+
body: JSON.stringify(body)
|
|
224
|
+
});
|
|
225
|
+
if (!response.ok) {
|
|
226
|
+
const payload = await response.json().catch(() => undefined);
|
|
227
|
+
throw new Error(isRecord(payload) && typeof payload.error === "string" ? payload.error : "Failed to save item.");
|
|
228
|
+
}
|
|
229
|
+
return response.json();
|
|
230
|
+
}
|
|
231
|
+
export function createSortableListInteraction(id, title, orderedIds, items) {
|
|
232
|
+
return {
|
|
233
|
+
type: "sortable-list",
|
|
234
|
+
id,
|
|
235
|
+
title,
|
|
236
|
+
orderedIds,
|
|
237
|
+
orderedItems: orderItems(items, orderedIds),
|
|
238
|
+
updatedAt: new Date().toISOString()
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
export function resolveSortableListOrder(items, orderedIds) {
|
|
242
|
+
const itemIds = items.map((item) => item.id);
|
|
243
|
+
if (!orderedIds) {
|
|
244
|
+
return itemIds;
|
|
245
|
+
}
|
|
246
|
+
const knownItemIds = new Set(itemIds);
|
|
247
|
+
const retainedIds = orderedIds.filter((itemId) => knownItemIds.has(itemId));
|
|
248
|
+
const retainedIdSet = new Set(retainedIds);
|
|
249
|
+
const appendedIds = itemIds.filter((itemId) => !retainedIdSet.has(itemId));
|
|
250
|
+
return [...retainedIds, ...appendedIds];
|
|
251
|
+
}
|
|
252
|
+
export function reorderIds(orderedIds, activeId, targetId) {
|
|
253
|
+
const activeIndex = orderedIds.indexOf(activeId);
|
|
254
|
+
const initialTargetIndex = orderedIds.indexOf(targetId);
|
|
255
|
+
if (activeIndex < 0 || initialTargetIndex < 0 || activeIndex === initialTargetIndex) {
|
|
256
|
+
return orderedIds;
|
|
257
|
+
}
|
|
258
|
+
const nextIds = orderedIds.filter((itemId) => itemId !== activeId);
|
|
259
|
+
const targetIndex = nextIds.indexOf(targetId);
|
|
260
|
+
nextIds.splice(targetIndex, 0, activeId);
|
|
261
|
+
return nextIds;
|
|
262
|
+
}
|
|
263
|
+
function orderItems(items, orderedIds) {
|
|
264
|
+
const itemsById = new Map(items.map((item) => [item.id, item]));
|
|
265
|
+
return orderedIds.flatMap((itemId) => {
|
|
266
|
+
const item = itemsById.get(itemId);
|
|
267
|
+
return item ? [item] : [];
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function getPersistedOrder(interaction) {
|
|
271
|
+
if (!isRecord(interaction) || !Array.isArray(interaction.orderedIds)) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
const orderedIds = interaction.orderedIds.filter((itemId) => typeof itemId === "string");
|
|
275
|
+
return orderedIds.length > 0 ? orderedIds : undefined;
|
|
276
|
+
}
|
|
277
|
+
function isRecord(value) {
|
|
278
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
279
|
+
}
|
|
280
|
+
function classNames(...values) {
|
|
281
|
+
return values.filter(Boolean).join(" ");
|
|
282
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./SortableList";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./SortableList.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Columns, Frame, Grid, SplitPane, Stack } from "./Layout.js";
|