@yadeck/slide-components-basic 0.0.0-stage → 0.1.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/src/flow.tsx ADDED
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import { RichText, type BlockOf } from "@yadeck/slide-core";
3
+
4
+ export const flowType = z.object({
5
+ steps: z
6
+ .array(
7
+ z.object({
8
+ label: z.string().describe("段の名前。見出しとして出す"),
9
+ via: z.string().optional().describe("この段に入ってくる矢印のラベル(変換や処理の名前)"),
10
+ phase: z.string().optional().describe("この段が属する段階の名前。見出しの横に小さく出す"),
11
+ detail: z.string().optional().describe("この段で起きることの一言。説明として出す"),
12
+ }),
13
+ )
14
+ .min(2)
15
+ .describe("流れの各段。順番どおり"),
16
+ focus: z
17
+ .union([z.number().int().min(1), z.array(z.number().int().min(1))])
18
+ .optional()
19
+ .describe("焦点にする段の番号(1 始まり)。配列で複数可。他の段は薄くなる"),
20
+ direction: z
21
+ .enum(["row", "column"])
22
+ .optional()
23
+ .describe("row: 左から右、column: 上から下(既定)。見せ方の種類は block の tags(flow / flow boxed / flow framed / flow grid)で選ぶ"),
24
+ });
25
+
26
+ type FlowProps = BlockOf<typeof flowType>;
27
+
28
+ /**
29
+ * 流れ(手順)。マークアップと CSS は https://www.ameamelog.com/css-flow/ の 5 パターンを移植したもので、
30
+ * 色をテーマトークンに、寸法をスライド向けに直している(CSS は styles.ts の .b-flow-*)。
31
+ * 構造は共通: ul.b-flow > li > .icon(番号) + dl > dt(見出し) / dd(説明)
32
+ */
33
+ function FlowList({ block, variant, numbered }: { block: FlowProps; variant: string; numbered: "step" | "plain" }) {
34
+ const focus = new Set(block.focus === undefined ? [] : Array.isArray(block.focus) ? block.focus : [block.focus]);
35
+ // boxed / framed は原型どおり番号を dt の中(見出しの上)に置く
36
+ const iconInTitle = variant === "boxed" || variant === "framed";
37
+ return (
38
+ <ul className={`b-flow b-flow-${variant} ${focus.size > 0 ? "has-focus" : ""}`}>
39
+ {block.steps.map((st, i) => {
40
+ const num = String(i + 1).padStart(2, "0");
41
+ const icon = <span className="icon">{numbered === "step" ? `STEP.${num}` : num}</span>;
42
+ return (
43
+ <li key={i} className={focus.has(i + 1) ? "is-focus" : ""}>
44
+ {!iconInTitle && icon}
45
+ {st.via && (
46
+ <span className="via">
47
+ <RichText text={st.via} />
48
+ </span>
49
+ )}
50
+ <dl>
51
+ <dt>
52
+ {iconInTitle && icon}
53
+ <RichText text={st.label} />
54
+ {st.phase && !iconInTitle && (
55
+ <span className="phase">
56
+ <RichText text={st.phase} />
57
+ </span>
58
+ )}
59
+ </dt>
60
+ {(st.detail || (st.phase && iconInTitle)) && (
61
+ <dd>
62
+ {st.phase && iconInTitle && (
63
+ <span className="phase">
64
+ <RichText text={st.phase} />
65
+ </span>
66
+ )}
67
+ {st.detail && <RichText text={st.detail} />}
68
+ </dd>
69
+ )}
70
+ </dl>
71
+ </li>
72
+ );
73
+ })}
74
+ </ul>
75
+ );
76
+ }
77
+
78
+ /** `flow`: 縦は 1 カラム構成(STEP ピル + レール + 点線)、横(direction: row)はポップ(吹き出し番号 + 枠カード + ›) */
79
+ export const FlowBlock = (block: FlowProps) =>
80
+ block.direction === "row" ? <FlowList block={block} variant="pop" numbered="plain" /> : <FlowList block={block} variant="rail" numbered="step" />;
81
+
82
+ /** `flow boxed`: 枠線を使ったデザイン。角丸の枠を縦に積み、点線と ▽ でつなぐ */
83
+ export const FlowBoxed = (block: FlowProps) => <FlowList block={block} variant="boxed" numbered="step" />;
84
+
85
+ /** `flow framed`: スタイリッシュ。全体を 1 つの枠で囲み、区切り線に ▽ の切り込み */
86
+ export const FlowFramed = (block: FlowProps) => <FlowList block={block} variant="framed" numbered="step" />;
87
+
88
+ /** `flow grid`: 2 カラム構成。右端が矢印の枠を 2 列に */
89
+ export const FlowGrid = (block: FlowProps) => <FlowList block={block} variant="grid" numbered="step" />;
package/src/index.ts ADDED
@@ -0,0 +1,91 @@
1
+ import { BlockLayout, DeckLayout, SlideLayout, definePlugin } from "@yadeck/slide-core";
2
+ import {
3
+ BodyBlock,
4
+ CardSlide,
5
+ CodeBlock,
6
+ DefaultBlock,
7
+ DefaultDeck,
8
+ HeaderSlide,
9
+ HeadingBlock,
10
+ ImageBlock,
11
+ ItemBlock,
12
+ ListBlock,
13
+ NoteBlock,
14
+ ProfileSlide,
15
+ QuoteBlock,
16
+ SectionHeaderSlide,
17
+ StatBlock,
18
+ TwoColumnSlide,
19
+ VideoBlock,
20
+ codeType,
21
+ headerType,
22
+ headingType,
23
+ imageType,
24
+ itemType,
25
+ listType,
26
+ profileType,
27
+ quoteType,
28
+ sectionHeaderType,
29
+ statType,
30
+ videoType,
31
+ } from "./layouts.js";
32
+ import { FlowBlock, FlowBoxed, FlowFramed, FlowGrid, flowType } from "./flow.js";
33
+ import { ColumnsSlide, DefaultSlide } from "./panes.js";
34
+ import { BASIC_CSS, DEFAULT_THEME } from "./styles.js";
35
+
36
+ export * from "./layouts.js";
37
+ export * from "./panes.js";
38
+ export * from "./flow.js";
39
+ export * from "./chrome.js";
40
+ export { BASIC_CSS, DEFAULT_THEME } from "./styles.js";
41
+
42
+ /**
43
+ * 最小 tag セット。全 Interface に tags: [] の fallback を持つので、
44
+ * これを先頭に置けばどんな tags でも必ず何かが描画される。
45
+ */
46
+ export const basic = definePlugin((c) => {
47
+ c.addStyle(DEFAULT_THEME);
48
+ c.addStyle(BASIC_CSS);
49
+ c.bind(DeckLayout, [], DefaultDeck, { description: "スライドを縦に並べる" });
50
+
51
+ c.bind(SlideLayout, [], DefaultSlide, {
52
+ description:
53
+ "汎用。テキスト(tags なし / body / list / quote / stat / item)は全部で 1 pane、code / image / video は 1 つずつ 1 pane に数え、1: 全面、2: 左右、3: ト型、4: 十字、5 以上: 左右 2 列に自動配置。テキストは 1 行なら中央に大きく、2 行以上なら箇条書き",
54
+ });
55
+ c.bind(SlideLayout, ["header"], HeaderSlide, { type: headerType, description: "表紙。title / subtitle を大きく、発表者情報を左下、イベント情報を右下、logo を右上" });
56
+ c.bind(SlideLayout, ["profile"], ProfileSlide, { type: profileType, description: "自己紹介。左に名前・肩書き・写真・アカウント、右に items" });
57
+ c.bind(SlideLayout, ["section-header"], SectionHeaderSlide, { type: sectionHeaderType, description: "章扉。number と heading、body だけを描く" });
58
+ c.bind(SlideLayout, ["two-column"], TwoColumnSlide, { description: "2 列の対比。left を付けた block を左列、right を右列、どちらも無い block は前置きとして列の上に置く。列の見出しは heading left / heading right" });
59
+ c.bind(SlideLayout, ["card"], CardSlide, { description: "item をカードにして並べる(3 枚までは 1 行、4 枚は 2×2、5 枚以上は 3 列)。他の block は前置きとして上に置く" });
60
+ c.bind(SlideLayout, ["columns"], ColumnsSlide, { description: "pane を横一列に等分する(4 まで。5 以上は 3 列 × 2 行)" });
61
+
62
+ c.bind(BlockLayout, [], DefaultBlock, { description: "本文 1 行。markdown 可" });
63
+ c.bind(BlockLayout, ["heading"], HeadingBlock, { type: headingType, description: "見出し。slide の上部に置かれる" });
64
+ c.bind(BlockLayout, ["body"], BodyBlock, { description: "本文。markdown 可。複数行は段落になる" });
65
+ c.bind(BlockLayout, ["list"], ListBlock, { type: listType, description: "行ごとの箇条書き" });
66
+ c.bind(BlockLayout, ["code"], CodeBlock, { type: codeType, description: "コード。highlight.js で色付けし、pane に収まるよう縮小する" });
67
+ c.bind(BlockLayout, ["image"], ImageBlock, { type: imageType, description: "画像。pane にアスペクト比維持で収める。text はキャプション" });
68
+ c.bind(BlockLayout, ["video"], VideoBlock, { type: videoType, description: "動画。YouTube の URL は embed に変換して iframe で埋め込む" });
69
+ c.bind(BlockLayout, ["flow"], FlowBlock, {
70
+ type: flowType,
71
+ description: "流れ(手順)。縦は STEP ピル + 縦レール + 見出しと説明(1 カラム構成)、横(direction: row)は吹き出し番号付きの枠カードを › でつなぐ。via / phase / detail / focus。1 つで 1 pane",
72
+ });
73
+ c.bind(BlockLayout, ["flow", "boxed"], FlowBoxed, {
74
+ type: flowType,
75
+ description: "流れ(手順)の別の見せ方。角丸の枠を縦に積み、点線と ▽ でつなぐ。左に STEP と見出し、右に説明",
76
+ });
77
+ c.bind(BlockLayout, ["flow", "framed"], FlowFramed, {
78
+ type: flowType,
79
+ description: "流れ(手順)の別の見せ方。全体を 1 つの枠で囲み、区切り線に ▽ の切り込み。左に STEP と見出し、右に説明",
80
+ });
81
+ c.bind(BlockLayout, ["flow", "grid"], FlowGrid, {
82
+ type: flowType,
83
+ description: "流れ(手順)の別の見せ方。右端が矢印形のカードを 2 列に並べる。段数が多いときに高さを取らない",
84
+ });
85
+ c.bind(BlockLayout, ["quote"], QuoteBlock, { type: quoteType, description: "引用" });
86
+ c.bind(BlockLayout, ["stat"], StatBlock, { type: statType, description: "数字や固有名詞を大きく見せる。label と補足の text" });
87
+ c.bind(BlockLayout, ["item"], ItemBlock, { type: itemType, description: "並列の項目(title + 説明の text)。card slide でカードになる" });
88
+ c.bind(BlockLayout, ["note"], NoteBlock, { description: "発表者ノート。画面にも印刷にも出ず、presenter モードに出る" });
89
+ });
90
+
91
+ export default basic;