create-obsidian-arrow 0.4.1 → 0.5.1
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/package.json +1 -1
- package/template/AGENTS.md +52 -17
- package/template/README.md +12 -14
- package/template/_gitignore +3 -0
- package/template/docs/prompts/agent-setup.md +2 -0
- package/template/docs/workflow.md +13 -7
- package/template/package.json +9 -2
- package/template/pnpm-lock.yaml +3 -0
- package/template/porting.config.example.json +6 -0
- package/template/scripts/check-orphaned-css.mjs +62 -0
- package/template/scripts/check-scope-classes.mjs +77 -0
- package/template/scripts/check-view-imports.mjs +133 -0
- package/template/scripts/component-hash.mjs +12 -1
- package/template/scripts/create-component.mjs +101 -0
- package/template/scripts/create-view.mjs +75 -0
- package/template/scripts/port-css.mjs +118 -0
- package/template/src/components/EmptyState/EmptyState.css +30 -0
- package/template/src/components/EmptyState/EmptyState.ts +35 -0
- package/template/src/components/LoadingState.ts +12 -0
- package/template/src/components/icons.ts +17 -0
- package/template/src/utilities.css +101 -1
- package/template/stories/components/EmptyState.stories.ts +25 -0
- package/template/stories/components/LoadingState.stories.ts +11 -0
- package/template/test/viewer-derive.test.mjs +6 -0
- package/template/test/viewer-stories.test.mjs +26 -0
- package/template/tools/router/client.ts +14 -3
- package/template/tools/router/routeToPage.ts +14 -2
- package/template/tools/sandbox/sandbox.css +13 -0
- package/template/tools/viewer/StoryPage.ts +35 -16
- package/template/tools/viewer/discovery.ts +6 -0
- package/template/tools/viewer/stories.ts +16 -0
|
@@ -3,7 +3,6 @@ import type { ArrowExpression } from "@arrow-js/core";
|
|
|
3
3
|
import type { DiscoveredStory } from "./discovery";
|
|
4
4
|
import { findStory } from "./discovery";
|
|
5
5
|
|
|
6
|
-
/** Copy to clipboard, best-effort (clipboard API needs a secure context). */
|
|
7
6
|
export function copyText(text: string): void {
|
|
8
7
|
void navigator.clipboard?.writeText(text);
|
|
9
8
|
}
|
|
@@ -18,18 +17,23 @@ function pathRow(label: string, path: string): ArrowExpression {
|
|
|
18
17
|
`;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
/** Metadata panel: title, status, variant tabs, notes, paths, children.
|
|
21
|
+
* No rendered component — used for kind: "component" left panel. */
|
|
22
|
+
export function StoryPageDetails(story: DiscoveredStory, variantName: string): ArrowExpression {
|
|
23
23
|
const variantNames = Object.keys(story.variants);
|
|
24
|
-
const
|
|
25
|
-
story.status === "live"
|
|
26
|
-
? html`<span class="oas-badge is-live">live</span>`
|
|
27
|
-
: html`<span class="oas-badge is-draft">draft</span>`;
|
|
24
|
+
const variant = story.variants[variantName];
|
|
28
25
|
return html`
|
|
29
26
|
<div class="oas-story">
|
|
30
27
|
<div class="setting-item setting-item-heading">
|
|
31
28
|
<div class="setting-item-info">
|
|
32
|
-
<div class="setting-item-name"
|
|
29
|
+
<div class="setting-item-name">
|
|
30
|
+
${story.title}
|
|
31
|
+
${
|
|
32
|
+
story.status === "live"
|
|
33
|
+
? html`<span class="oas-badge is-live">live</span>`
|
|
34
|
+
: html`<span class="oas-badge is-draft">draft</span>`
|
|
35
|
+
}
|
|
36
|
+
</div>
|
|
33
37
|
${
|
|
34
38
|
story.description
|
|
35
39
|
? html`<div class="setting-item-description">${story.description}</div>`
|
|
@@ -54,20 +58,35 @@ export function StoryPage(story: DiscoveredStory, variantName: string): ArrowExp
|
|
|
54
58
|
? html`<div class="oas-story-children">
|
|
55
59
|
${story.children.map((slug) => {
|
|
56
60
|
const child = findStory(slug);
|
|
61
|
+
const childHref = `/components/${slug}`;
|
|
57
62
|
return child
|
|
58
|
-
? html`<a class="oas-child" href="${
|
|
63
|
+
? html`<a class="oas-child" href="${childHref}">${child.title} →</a>`
|
|
59
64
|
: html`<span class="oas-child-missing">${slug} (missing story)</span>`;
|
|
60
65
|
})}
|
|
61
66
|
</div>`
|
|
62
67
|
: ""
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
</div>
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Rendered component only — decorator applied if present.
|
|
74
|
+
* Used for kind: "component" canvas area. */
|
|
75
|
+
export function StoryPageCanvas(story: DiscoveredStory, variantName: string): ArrowExpression {
|
|
76
|
+
const variant = story.variants[variantName];
|
|
77
|
+
const rendered = variant
|
|
78
|
+
? variant.render()
|
|
79
|
+
: html`<div class="oas-story-missing">No variant "${variantName}" — pick one above.</div>`;
|
|
80
|
+
return story.decorator ? story.decorator(rendered) : rendered;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Full story page: details + canvas together.
|
|
84
|
+
* Used for kind: "view" — StoryPageDetails provides the .oas-story wrapper. */
|
|
85
|
+
export function StoryPageView(story: DiscoveredStory, variantName: string): ArrowExpression {
|
|
86
|
+
return html`
|
|
87
|
+
${StoryPageDetails(story, variantName)}
|
|
88
|
+
<div class="oas-story-canvas">
|
|
89
|
+
${StoryPageCanvas(story, variantName)}
|
|
71
90
|
</div>
|
|
72
91
|
`;
|
|
73
92
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ArrowExpression } from "@arrow-js/core";
|
|
1
2
|
import { buildStoryTree, storyMetaFromGlobKey, titleFromSlug } from "./derive";
|
|
2
3
|
import type { StoryDef, StoryVariant } from "./stories";
|
|
3
4
|
import { normalizeVariants, validateStoryDef } from "./stories";
|
|
@@ -19,6 +20,8 @@ export interface DiscoveredStory {
|
|
|
19
20
|
variants: Record<string, StoryVariant>;
|
|
20
21
|
children: string[];
|
|
21
22
|
status: "live" | "draft";
|
|
23
|
+
kind: "view" | "component";
|
|
24
|
+
decorator?: (content: ArrowExpression) => ArrowExpression;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export interface InvalidStory {
|
|
@@ -43,6 +46,7 @@ for (const [globKey, mod] of Object.entries(modules)) {
|
|
|
43
46
|
continue;
|
|
44
47
|
}
|
|
45
48
|
const def = mod.default as StoryDef;
|
|
49
|
+
const autoKind = meta.storiesPath.startsWith("stories/views/") ? "view" : "component";
|
|
46
50
|
stories.push({
|
|
47
51
|
slug: meta.slug,
|
|
48
52
|
title: def.title ?? titleFromSlug(meta.slug),
|
|
@@ -52,6 +56,8 @@ for (const [globKey, mod] of Object.entries(modules)) {
|
|
|
52
56
|
variants: normalizeVariants(def.variants),
|
|
53
57
|
children: def.children ?? [],
|
|
54
58
|
status: def.status ?? "draft",
|
|
59
|
+
kind: def.kind ?? autoKind,
|
|
60
|
+
decorator: def.decorator,
|
|
55
61
|
});
|
|
56
62
|
}
|
|
57
63
|
|
|
@@ -21,6 +21,12 @@ export interface StoryDef {
|
|
|
21
21
|
/** Repo-relative override for where the component lives (e.g. a subcomponent
|
|
22
22
|
* defined inside its parent's file). Defaults to the stories path minus `.stories`. */
|
|
23
23
|
componentPath?: string;
|
|
24
|
+
/** "view" = full pane frame. "component" = centered canvas with separate details panel.
|
|
25
|
+
* Auto-detected from stories/ path if omitted. */
|
|
26
|
+
kind?: "view" | "component";
|
|
27
|
+
/** Wraps the rendered variant — use for ancestor class context.
|
|
28
|
+
* Example: (content) => html`<div class="my-shell">${content}</div>` */
|
|
29
|
+
decorator?: (content: ArrowExpression) => ArrowExpression;
|
|
24
30
|
/** Named variants; keys are human strings ("default", "dev mode off"). */
|
|
25
31
|
variants: Record<string, VariantInput>;
|
|
26
32
|
/** Slugs of subcomponent stories for drill-in nesting. */
|
|
@@ -69,6 +75,16 @@ export function validateStoryDef(def: unknown): ValidationResult {
|
|
|
69
75
|
return { ok: false, reason: '"status" must be "live" or "draft"' };
|
|
70
76
|
}
|
|
71
77
|
}
|
|
78
|
+
if ("kind" in def) {
|
|
79
|
+
if (def.kind !== "view" && def.kind !== "component") {
|
|
80
|
+
return { ok: false, reason: '"kind" must be "view" or "component"' };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if ("decorator" in def) {
|
|
84
|
+
if (typeof def.decorator !== "function") {
|
|
85
|
+
return { ok: false, reason: '"decorator" must be a function' };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
72
88
|
return { ok: true };
|
|
73
89
|
}
|
|
74
90
|
|