@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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 onfi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,17 @@
1
- # Temporary Holding Version
1
+ # @yadeck/slide-components-basic
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 標準の Layout 一式(basic プラグイン)。表紙、章扉、自動レイアウト、2 列、カード、コード、画像、流れの図など。
4
+
5
+ YADECK は、AI が schema 付きの YAML に内容を書き、作り込みたいページだけを JSX で作るスライドジェネレータです。
6
+
7
+ ```ts
8
+ import basic from "@yadeck/slide-components-basic";
9
+ export default defineConfig({ plugins: [basic] });
10
+ ```
11
+
12
+ - ドキュメント: https://onfi.github.io/yadeck/
13
+ - リポジトリ: https://github.com/onfi/yadeck
14
+
15
+ ## License
16
+
17
+ MIT
@@ -0,0 +1,8 @@
1
+ import { type BlockNode } from "@yadeck/slide-core";
2
+ /** スライド枠いっぱいに広げる共通のパディング付きコンテナ */
3
+ export declare const PAGE = "absolute inset-0 flex flex-col gap-6 px-20 py-14";
4
+ export declare const SlideHeading: ({ block, description }: {
5
+ block: BlockNode;
6
+ description?: string;
7
+ }) => import("react").JSX.Element;
8
+ //# sourceMappingURL=chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../src/chrome.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAErE,kCAAkC;AAClC,eAAO,MAAM,IAAI,qDAAqD,CAAC;AAavE,eAAO,MAAM,YAAY,GAAI,wBAAwB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,gCAY9F,CAAC"}
package/dist/chrome.js ADDED
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Block, RichText } from "@yadeck/slide-core";
3
+ /** スライド枠いっぱいに広げる共通のパディング付きコンテナ */
4
+ export const PAGE = "absolute inset-0 flex flex-col gap-6 px-20 py-14";
5
+ /**
6
+ * スライド上部の見出し。accent の縦バーと primary の細い下線で、表紙と同じ文法にする。
7
+ * slide の description があれば見出しの下に 1 行添える
8
+ */
9
+ /** 見出しの表示幅(全角 2、半角 1)。長い見出しは 1 段小さくして 1 行に収める */
10
+ function headingWidth(text) {
11
+ let w = 0;
12
+ for (const ch of text.replace(/[`*_]/g, ""))
13
+ w += (ch.codePointAt(0) ?? 0) > 0x2e7f ? 2 : 1;
14
+ return w;
15
+ }
16
+ export const SlideHeading = ({ block, description }) => (_jsxs("header", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: `flex items-center gap-4 border-b-2 border-primary/30 pb-3 ${headingWidth(block.text ?? "") > 44 ? "[&_.b-heading]:text-h3" : "[&_.b-heading]:text-h2"}`, children: [_jsx("span", { className: "h-10 w-2 shrink-0 rounded-sm bg-accent" }), _jsx(Block, { data: block })] }), description && _jsx(RichText, { as: "p", className: "m-0 pl-6 text-small leading-snug text-muted", text: description })] }));
17
+ //# sourceMappingURL=chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../src/chrome.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB,MAAM,oBAAoB,CAAC;AAErE,kCAAkC;AAClC,MAAM,CAAC,MAAM,IAAI,GAAG,kDAAkD,CAAC;AAEvE;;;GAGG;AACH,iDAAiD;AACjD,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAAE,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAA8C,EAAE,EAAE,CAAC,CAClG,kBAAQ,SAAS,EAAC,qBAAqB,aACrC,eACE,SAAS,EAAE,6DACT,YAAY,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,wBACnE,EAAE,aAEF,eAAM,SAAS,EAAC,wCAAwC,GAAG,EAC3D,KAAC,KAAK,IAAC,IAAI,EAAE,KAAK,GAAI,IAClB,EACL,WAAW,IAAI,KAAC,QAAQ,IAAC,EAAE,EAAC,GAAG,EAAC,SAAS,EAAC,6CAA6C,EAAC,IAAI,EAAE,WAAW,GAAI,IACvG,CACV,CAAC"}
package/dist/flow.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+ import { type BlockOf } from "@yadeck/slide-core";
3
+ export declare const flowType: z.ZodObject<{
4
+ steps: z.ZodArray<z.ZodObject<{
5
+ label: z.ZodString;
6
+ via: z.ZodOptional<z.ZodString>;
7
+ phase: z.ZodOptional<z.ZodString>;
8
+ detail: z.ZodOptional<z.ZodString>;
9
+ }, z.core.$strip>>;
10
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
11
+ direction: z.ZodOptional<z.ZodEnum<{
12
+ row: "row";
13
+ column: "column";
14
+ }>>;
15
+ }, z.core.$strip>;
16
+ type FlowProps = BlockOf<typeof flowType>;
17
+ /** `flow`: 縦は 1 カラム構成(STEP ピル + レール + 点線)、横(direction: row)はポップ(吹き出し番号 + 枠カード + ›) */
18
+ export declare const FlowBlock: (block: FlowProps) => import("react").JSX.Element;
19
+ /** `flow boxed`: 枠線を使ったデザイン。角丸の枠を縦に積み、点線と ▽ でつなぐ */
20
+ export declare const FlowBoxed: (block: FlowProps) => import("react").JSX.Element;
21
+ /** `flow framed`: スタイリッシュ。全体を 1 つの枠で囲み、区切り線に ▽ の切り込み */
22
+ export declare const FlowFramed: (block: FlowProps) => import("react").JSX.Element;
23
+ /** `flow grid`: 2 カラム構成。右端が矢印の枠を 2 列に */
24
+ export declare const FlowGrid: (block: FlowProps) => import("react").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../src/flow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,QAAQ;;;;;;;;;;;;iBAoBnB,CAAC;AAEH,KAAK,SAAS,GAAG,OAAO,CAAC,OAAO,QAAQ,CAAC,CAAC;AAoD1C,sFAAsF;AACtF,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,gCACyG,CAAC;AAEpJ,oDAAoD;AACpD,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,gCAA+D,CAAC;AAE1G,wDAAwD;AACxD,eAAO,MAAM,UAAU,GAAI,OAAO,SAAS,gCAAgE,CAAC;AAE5G,yCAAyC;AACzC,eAAO,MAAM,QAAQ,GAAI,OAAO,SAAS,gCAA8D,CAAC"}
package/dist/flow.js ADDED
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { z } from "zod";
3
+ import { RichText } from "@yadeck/slide-core";
4
+ export const flowType = z.object({
5
+ steps: z
6
+ .array(z.object({
7
+ label: z.string().describe("段の名前。見出しとして出す"),
8
+ via: z.string().optional().describe("この段に入ってくる矢印のラベル(変換や処理の名前)"),
9
+ phase: z.string().optional().describe("この段が属する段階の名前。見出しの横に小さく出す"),
10
+ detail: z.string().optional().describe("この段で起きることの一言。説明として出す"),
11
+ }))
12
+ .min(2)
13
+ .describe("流れの各段。順番どおり"),
14
+ focus: z
15
+ .union([z.number().int().min(1), z.array(z.number().int().min(1))])
16
+ .optional()
17
+ .describe("焦点にする段の番号(1 始まり)。配列で複数可。他の段は薄くなる"),
18
+ direction: z
19
+ .enum(["row", "column"])
20
+ .optional()
21
+ .describe("row: 左から右、column: 上から下(既定)。見せ方の種類は block の tags(flow / flow boxed / flow framed / flow grid)で選ぶ"),
22
+ });
23
+ /**
24
+ * 流れ(手順)。マークアップと CSS は https://www.ameamelog.com/css-flow/ の 5 パターンを移植したもので、
25
+ * 色をテーマトークンに、寸法をスライド向けに直している(CSS は styles.ts の .b-flow-*)。
26
+ * 構造は共通: ul.b-flow > li > .icon(番号) + dl > dt(見出し) / dd(説明)
27
+ */
28
+ function FlowList({ block, variant, numbered }) {
29
+ const focus = new Set(block.focus === undefined ? [] : Array.isArray(block.focus) ? block.focus : [block.focus]);
30
+ // boxed / framed は原型どおり番号を dt の中(見出しの上)に置く
31
+ const iconInTitle = variant === "boxed" || variant === "framed";
32
+ return (_jsx("ul", { className: `b-flow b-flow-${variant} ${focus.size > 0 ? "has-focus" : ""}`, children: block.steps.map((st, i) => {
33
+ const num = String(i + 1).padStart(2, "0");
34
+ const icon = _jsx("span", { className: "icon", children: numbered === "step" ? `STEP.${num}` : num });
35
+ return (_jsxs("li", { className: focus.has(i + 1) ? "is-focus" : "", children: [!iconInTitle && icon, st.via && (_jsx("span", { className: "via", children: _jsx(RichText, { text: st.via }) })), _jsxs("dl", { children: [_jsxs("dt", { children: [iconInTitle && icon, _jsx(RichText, { text: st.label }), st.phase && !iconInTitle && (_jsx("span", { className: "phase", children: _jsx(RichText, { text: st.phase }) }))] }), (st.detail || (st.phase && iconInTitle)) && (_jsxs("dd", { children: [st.phase && iconInTitle && (_jsx("span", { className: "phase", children: _jsx(RichText, { text: st.phase }) })), st.detail && _jsx(RichText, { text: st.detail })] }))] })] }, i));
36
+ }) }));
37
+ }
38
+ /** `flow`: 縦は 1 カラム構成(STEP ピル + レール + 点線)、横(direction: row)はポップ(吹き出し番号 + 枠カード + ›) */
39
+ export const FlowBlock = (block) => block.direction === "row" ? _jsx(FlowList, { block: block, variant: "pop", numbered: "plain" }) : _jsx(FlowList, { block: block, variant: "rail", numbered: "step" });
40
+ /** `flow boxed`: 枠線を使ったデザイン。角丸の枠を縦に積み、点線と ▽ でつなぐ */
41
+ export const FlowBoxed = (block) => _jsx(FlowList, { block: block, variant: "boxed", numbered: "step" });
42
+ /** `flow framed`: スタイリッシュ。全体を 1 つの枠で囲み、区切り線に ▽ の切り込み */
43
+ export const FlowFramed = (block) => _jsx(FlowList, { block: block, variant: "framed", numbered: "step" });
44
+ /** `flow grid`: 2 カラム構成。右端が矢印の枠を 2 列に */
45
+ export const FlowGrid = (block) => _jsx(FlowList, { block: block, variant: "grid", numbered: "step" });
46
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../src/flow.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export * from "./layouts.js";
2
+ export * from "./panes.js";
3
+ export * from "./flow.js";
4
+ export * from "./chrome.js";
5
+ export { BASIC_CSS, DEFAULT_THEME } from "./styles.js";
6
+ /**
7
+ * 最小 tag セット。全 Interface に tags: [] の fallback を持つので、
8
+ * これを先頭に置けばどんな tags でも必ず何かが描画される。
9
+ */
10
+ export declare const basic: import("@yadeck/slide-core").Plugin;
11
+ export default basic;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmCA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,KAAK,qCA2ChB,CAAC;AAEH,eAAe,KAAK,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ import { BlockLayout, DeckLayout, SlideLayout, definePlugin } from "@yadeck/slide-core";
2
+ import { BodyBlock, CardSlide, CodeBlock, DefaultBlock, DefaultDeck, HeaderSlide, HeadingBlock, ImageBlock, ItemBlock, ListBlock, NoteBlock, ProfileSlide, QuoteBlock, SectionHeaderSlide, StatBlock, TwoColumnSlide, VideoBlock, codeType, headerType, headingType, imageType, itemType, listType, profileType, quoteType, sectionHeaderType, statType, videoType, } from "./layouts.js";
3
+ import { FlowBlock, FlowBoxed, FlowFramed, FlowGrid, flowType } from "./flow.js";
4
+ import { ColumnsSlide, DefaultSlide } from "./panes.js";
5
+ import { BASIC_CSS, DEFAULT_THEME } from "./styles.js";
6
+ export * from "./layouts.js";
7
+ export * from "./panes.js";
8
+ export * from "./flow.js";
9
+ export * from "./chrome.js";
10
+ export { BASIC_CSS, DEFAULT_THEME } from "./styles.js";
11
+ /**
12
+ * 最小 tag セット。全 Interface に tags: [] の fallback を持つので、
13
+ * これを先頭に置けばどんな tags でも必ず何かが描画される。
14
+ */
15
+ export const basic = definePlugin((c) => {
16
+ c.addStyle(DEFAULT_THEME);
17
+ c.addStyle(BASIC_CSS);
18
+ c.bind(DeckLayout, [], DefaultDeck, { description: "スライドを縦に並べる" });
19
+ c.bind(SlideLayout, [], DefaultSlide, {
20
+ description: "汎用。テキスト(tags なし / body / list / quote / stat / item)は全部で 1 pane、code / image / video は 1 つずつ 1 pane に数え、1: 全面、2: 左右、3: ト型、4: 十字、5 以上: 左右 2 列に自動配置。テキストは 1 行なら中央に大きく、2 行以上なら箇条書き",
21
+ });
22
+ c.bind(SlideLayout, ["header"], HeaderSlide, { type: headerType, description: "表紙。title / subtitle を大きく、発表者情報を左下、イベント情報を右下、logo を右上" });
23
+ c.bind(SlideLayout, ["profile"], ProfileSlide, { type: profileType, description: "自己紹介。左に名前・肩書き・写真・アカウント、右に items" });
24
+ c.bind(SlideLayout, ["section-header"], SectionHeaderSlide, { type: sectionHeaderType, description: "章扉。number と heading、body だけを描く" });
25
+ c.bind(SlideLayout, ["two-column"], TwoColumnSlide, { description: "2 列の対比。left を付けた block を左列、right を右列、どちらも無い block は前置きとして列の上に置く。列の見出しは heading left / heading right" });
26
+ c.bind(SlideLayout, ["card"], CardSlide, { description: "item をカードにして並べる(3 枚までは 1 行、4 枚は 2×2、5 枚以上は 3 列)。他の block は前置きとして上に置く" });
27
+ c.bind(SlideLayout, ["columns"], ColumnsSlide, { description: "pane を横一列に等分する(4 まで。5 以上は 3 列 × 2 行)" });
28
+ c.bind(BlockLayout, [], DefaultBlock, { description: "本文 1 行。markdown 可" });
29
+ c.bind(BlockLayout, ["heading"], HeadingBlock, { type: headingType, description: "見出し。slide の上部に置かれる" });
30
+ c.bind(BlockLayout, ["body"], BodyBlock, { description: "本文。markdown 可。複数行は段落になる" });
31
+ c.bind(BlockLayout, ["list"], ListBlock, { type: listType, description: "行ごとの箇条書き" });
32
+ c.bind(BlockLayout, ["code"], CodeBlock, { type: codeType, description: "コード。highlight.js で色付けし、pane に収まるよう縮小する" });
33
+ c.bind(BlockLayout, ["image"], ImageBlock, { type: imageType, description: "画像。pane にアスペクト比維持で収める。text はキャプション" });
34
+ c.bind(BlockLayout, ["video"], VideoBlock, { type: videoType, description: "動画。YouTube の URL は embed に変換して iframe で埋め込む" });
35
+ c.bind(BlockLayout, ["flow"], FlowBlock, {
36
+ type: flowType,
37
+ description: "流れ(手順)。縦は STEP ピル + 縦レール + 見出しと説明(1 カラム構成)、横(direction: row)は吹き出し番号付きの枠カードを › でつなぐ。via / phase / detail / focus。1 つで 1 pane",
38
+ });
39
+ c.bind(BlockLayout, ["flow", "boxed"], FlowBoxed, {
40
+ type: flowType,
41
+ description: "流れ(手順)の別の見せ方。角丸の枠を縦に積み、点線と ▽ でつなぐ。左に STEP と見出し、右に説明",
42
+ });
43
+ c.bind(BlockLayout, ["flow", "framed"], FlowFramed, {
44
+ type: flowType,
45
+ description: "流れ(手順)の別の見せ方。全体を 1 つの枠で囲み、区切り線に ▽ の切り込み。左に STEP と見出し、右に説明",
46
+ });
47
+ c.bind(BlockLayout, ["flow", "grid"], FlowGrid, {
48
+ type: flowType,
49
+ description: "流れ(手順)の別の見せ方。右端が矢印形のカードを 2 列に並べる。段数が多いときに高さを取らない",
50
+ });
51
+ c.bind(BlockLayout, ["quote"], QuoteBlock, { type: quoteType, description: "引用" });
52
+ c.bind(BlockLayout, ["stat"], StatBlock, { type: statType, description: "数字や固有名詞を大きく見せる。label と補足の text" });
53
+ c.bind(BlockLayout, ["item"], ItemBlock, { type: itemType, description: "並列の項目(title + 説明の text)。card slide でカードになる" });
54
+ c.bind(BlockLayout, ["note"], NoteBlock, { description: "発表者ノート。画面にも印刷にも出ず、presenter モードに出る" });
55
+ });
56
+ export default basic;
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { z } from "zod";
2
+ import { type BlockNode, type BlockOf, type DeckNode, type SlideNode, type SlideOf } from "@yadeck/slide-core";
3
+ export declare const DefaultDeck: (deck: DeckNode) => import("react").JSX.Element;
4
+ /**
5
+ * `card` を付けた slide。item をカードで横並びにし、それ以外の block は前置きとして上に置く。
6
+ * この bind が無い構成では tags 無しの slide に fallback して縦に並ぶ。
7
+ */
8
+ /** カードの列数。3 枚までは 1 行、4 枚は 2×2、5 枚以上は 3 列で折り返す(1 枚に見出しと説明が入る分、columns より早く折り返す) */
9
+ export declare function cardColumns(n: number): number;
10
+ export declare const CardSlide: (slide: SlideNode) => import("react").JSX.Element;
11
+ export declare const headerType: z.ZodObject<{
12
+ title: z.ZodString;
13
+ subtitle: z.ZodOptional<z.ZodString>;
14
+ author: z.ZodOptional<z.ZodString>;
15
+ affiliation: z.ZodOptional<z.ZodString>;
16
+ event: z.ZodOptional<z.ZodString>;
17
+ date: z.ZodOptional<z.ZodString>;
18
+ logo: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>;
20
+ /**
21
+ * 表紙。title / subtitle を中央左寄せで大きく、発表者情報を左下、イベント情報を右下に置く。
22
+ * items は title の下に補足として並ぶ(通常は空)。
23
+ */
24
+ export declare const HeaderSlide: (slide: SlideOf<typeof headerType>) => import("react").JSX.Element;
25
+ export declare const profileType: z.ZodObject<{
26
+ name: z.ZodString;
27
+ role: z.ZodOptional<z.ZodString>;
28
+ affiliation: z.ZodOptional<z.ZodString>;
29
+ photo: z.ZodOptional<z.ZodString>;
30
+ accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
31
+ }, z.core.$strip>;
32
+ /**
33
+ * 自己紹介。左に名前・肩書き・写真、右に items(heading があれば右上の見出しに)。
34
+ */
35
+ export declare const ProfileSlide: (slide: SlideOf<typeof profileType>) => import("react").JSX.Element;
36
+ export declare const sectionHeaderType: z.ZodObject<{
37
+ number: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strip>;
39
+ /**
40
+ * 章扉。表紙と同じ primary の地と accent の縦バーで、本文ページとの切り替わりを見せる。
41
+ * number は左上に accent で大きく、右下に透かしでもう一度出す
42
+ */
43
+ export declare const SectionHeaderSlide: (slide: SlideOf<typeof sectionHeaderType>) => import("react").JSX.Element;
44
+ /** 見出し + 前置き + left / right の 2 列。left / right の無い block は前置きとして列の上に置く */
45
+ export declare const TwoColumnSlide: (slide: SlideNode) => import("react").JSX.Element;
46
+ export declare const DefaultBlock: (block: BlockNode) => import("react").JSX.Element;
47
+ export declare const headingType: z.ZodObject<{
48
+ level: z.ZodOptional<z.ZodNumber>;
49
+ }, z.core.$strip>;
50
+ /** 見出し。文字サイズは level で決まるが、slide 側が `[&_.b-heading]:text-*` で上書きできる */
51
+ export declare const HeadingBlock: (block: BlockOf<typeof headingType>) => import("react").JSX.Element;
52
+ export declare const BodyBlock: (block: BlockNode) => import("react").JSX.Element;
53
+ export declare const listType: z.ZodObject<{
54
+ ordered: z.ZodOptional<z.ZodBoolean>;
55
+ focus: z.ZodOptional<z.ZodNumber>;
56
+ }, z.core.$strip>;
57
+ /** text の各行を項目にする。markdown の箇条書きは body でも書けるので、こちらは行区切りの簡易記法 */
58
+ export declare const ListBlock: (block: BlockOf<typeof listType>) => import("react").JSX.Element;
59
+ export declare const codeType: z.ZodObject<{
60
+ lang: z.ZodOptional<z.ZodString>;
61
+ caption: z.ZodOptional<z.ZodString>;
62
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>]>>;
63
+ }, z.core.$strip>;
64
+ /** focus の指定を行番号(0 始まり)の集合にする */
65
+ export declare function focusLines(lines: string[], focus: z.infer<typeof codeType>["focus"]): Set<number>;
66
+ /**
67
+ * ハイライト済み HTML を行ごとに分ける。行をまたぐ span(複数行コメントなど)は
68
+ * 行末で閉じて次の行頭で開き直す。
69
+ */
70
+ export declare function splitHighlighted(html: string): string[];
71
+ /**
72
+ * コード。highlight.js で SSG 時に色付けする。
73
+ * 行数と最大行長を CSS 変数で渡し、pane に収まるフォントサイズを CSS の calc で決める(styles.ts)。
74
+ */
75
+ /** コードの最大行幅(全角 2)と行数。フォントサイズの計算に使う */
76
+ export declare function codeSize(text: string | undefined): {
77
+ cols: number;
78
+ rows: number;
79
+ };
80
+ /** 箱の上下余白(40px)と、caption があればその 1 行分(40px)。高さからこの分を引いた残りに行を収める */
81
+ export declare function codeChrome(caption: string | undefined): number;
82
+ export declare const CodeBlock: (block: BlockOf<typeof codeType>) => import("react").JSX.Element;
83
+ export declare const imageType: z.ZodObject<{
84
+ src: z.ZodString;
85
+ alt: z.ZodOptional<z.ZodString>;
86
+ width: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
87
+ }, z.core.$strip>;
88
+ /** 画像。pane いっぱいにアスペクト比を保って収める。width 指定があればその幅にする */
89
+ export declare const ImageBlock: (block: BlockOf<typeof imageType>) => import("react").JSX.Element;
90
+ export declare const videoType: z.ZodObject<{
91
+ url: z.ZodString;
92
+ }, z.core.$strip>;
93
+ /** 動画。YouTube は embed URL に変換して iframe で埋め込む。text はキャプション */
94
+ export declare const VideoBlock: (block: BlockOf<typeof videoType>) => import("react").JSX.Element;
95
+ export declare function toEmbedUrl(url: string): string;
96
+ export declare const statType: z.ZodObject<{
97
+ value: z.ZodString;
98
+ label: z.ZodOptional<z.ZodString>;
99
+ }, z.core.$strip>;
100
+ /** 数字や固有名詞を主役にする block。text は補足として小さく出す */
101
+ export declare const StatBlock: (block: BlockOf<typeof statType>) => import("react").JSX.Element;
102
+ export declare const itemType: z.ZodObject<{
103
+ title: z.ZodString;
104
+ logo: z.ZodOptional<z.ZodString>;
105
+ }, z.core.$strip>;
106
+ /** 並列の項目。タイトルと説明を持つ。見せ方(カードにするか等)は slide の Layout が決める */
107
+ export declare const ItemBlock: (block: BlockOf<typeof itemType>) => import("react").JSX.Element;
108
+ export declare const quoteType: z.ZodObject<{
109
+ cite: z.ZodOptional<z.ZodString>;
110
+ }, z.core.$strip>;
111
+ export declare const QuoteBlock: (block: BlockOf<typeof quoteType>) => import("react").JSX.Element;
112
+ /** 発表者ノート。画面・印刷には出さず、presenter モードが `.yd-notes` を拾って表示する */
113
+ export declare const NoteBlock: (block: BlockNode) => import("react").JSX.Element;
114
+ //# sourceMappingURL=layouts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layouts.d.ts","sourceRoot":"","sources":["../src/layouts.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import hljs from "highlight.js";
3
+ import { z } from "zod";
4
+ import { Block, RichText, Slide, pick, pickAll, } from "@yadeck/slide-core";
5
+ import { PAGE, SlideHeading } from "./chrome.js";
6
+ // ---- deck ----
7
+ export const DefaultDeck = (deck) => (_jsx("main", { className: "yd-deck", children: deck.slides.map((s) => (_jsx(Slide, { data: s }, s.id))) }));
8
+ // ---- slide ----
9
+ /**
10
+ * `card` を付けた slide。item をカードで横並びにし、それ以外の block は前置きとして上に置く。
11
+ * この bind が無い構成では tags 無しの slide に fallback して縦に並ぶ。
12
+ */
13
+ /** カードの列数。3 枚までは 1 行、4 枚は 2×2、5 枚以上は 3 列で折り返す(1 枚に見出しと説明が入る分、columns より早く折り返す) */
14
+ export function cardColumns(n) {
15
+ if (n <= 3)
16
+ return Math.max(1, n);
17
+ return n === 4 ? 2 : 3;
18
+ }
19
+ export const CardSlide = (slide) => {
20
+ const [heading, rest] = pick(slide.items, ["heading"]);
21
+ const [entries, lead] = pickAll(rest, ["item"]);
22
+ return (_jsxs("div", { className: `${PAGE} b-card`, children: [heading && _jsx(SlideHeading, { block: heading, description: slide.description }), lead.length > 0 && (_jsx("div", { className: "flex flex-col gap-3", children: lead.map((b) => (_jsx(Block, { data: b }, b.id))) })), _jsx("div", { className: "grid min-h-0 flex-1 auto-rows-[minmax(0,1fr)] gap-6", style: { gridTemplateColumns: `repeat(${cardColumns(entries.length)}, minmax(0, 1fr))` }, children: entries.map((b) => (_jsx("div", { className: "flex min-h-0 flex-col justify-center rounded-2xl bg-ink/5 px-8 py-5 [&_.b-item]:items-center [&_.b-item]:text-center", children: _jsx(Block, { data: b }) }, b.id))) })] }));
23
+ };
24
+ export const headerType = z.object({
25
+ title: z.string().describe("発表タイトル"),
26
+ subtitle: z.string().optional().describe("副題"),
27
+ author: z.string().optional().describe("発表者名"),
28
+ affiliation: z.string().optional().describe("所属。author の下に小さく出す"),
29
+ event: z.string().optional().describe("イベント名。右下に date と並べる"),
30
+ date: z.string().optional().describe("日付"),
31
+ logo: z.string().optional().describe("ロゴ画像。public/ のファイルは ./logo.svg、外部は URL。右上に白抜きで出す"),
32
+ });
33
+ /**
34
+ * 表紙。title / subtitle を中央左寄せで大きく、発表者情報を左下、イベント情報を右下に置く。
35
+ * items は title の下に補足として並ぶ(通常は空)。
36
+ */
37
+ export const HeaderSlide = (slide) => (_jsxs("div", { className: "b-header absolute inset-0 flex flex-col overflow-hidden bg-linear-to-br from-primary to-primary-deep px-20 py-14 text-surface", children: [_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute -right-40 -bottom-64 size-[640px] rounded-full bg-accent/10" }), _jsx("div", { "aria-hidden": "true", className: "absolute inset-x-0 bottom-0 h-3 bg-accent" }), slide.logo && _jsx("img", { className: "absolute top-14 right-20 h-12 w-auto brightness-0 invert", src: slide.logo, alt: "" }), _jsxs("div", { className: "relative flex flex-1 flex-col justify-center", children: [_jsxs("div", { className: "flex flex-col gap-5 border-l-[10px] border-accent pl-8", children: [_jsx("h1", { className: "m-0 text-h1 leading-[1.25] font-bold", children: _jsx(RichText, { text: slide.title }) }), slide.subtitle && (_jsx("p", { className: "m-0 text-h3 leading-snug font-normal text-accent", children: _jsx(RichText, { text: slide.subtitle }) }))] }), slide.items.length > 0 && (_jsx("div", { className: "mt-8 flex flex-col gap-3", children: slide.items.map((b) => (_jsx(Block, { data: b }, b.id))) }))] }), _jsxs("div", { className: "relative flex items-end justify-between gap-6 text-small leading-snug", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [slide.author && _jsx("span", { className: "text-h4 font-bold", children: slide.author }), slide.affiliation && _jsx("span", { className: "opacity-85", children: slide.affiliation })] }), _jsxs("div", { className: "flex flex-col items-end gap-1 opacity-85", children: [slide.event && _jsx("span", { children: slide.event }), slide.date && _jsx("span", { children: slide.date })] })] })] }));
38
+ export const profileType = z.object({
39
+ name: z.string().describe("名前"),
40
+ role: z.string().optional().describe("肩書き・役割"),
41
+ affiliation: z.string().optional().describe("所属"),
42
+ photo: z.string().optional().describe("顔写真。無ければ name の頭文字を accent の円で出す"),
43
+ accounts: z.record(z.string(), z.string()).optional().describe("SNS や GitHub の ID。{ x: id, github: id } の形"),
44
+ });
45
+ const ACCOUNT_LABEL = { x: "X", twitter: "X", github: "GitHub", bluesky: "Bluesky", mastodon: "Mastodon", zenn: "Zenn", qiita: "Qiita" };
46
+ /**
47
+ * 自己紹介。左に名前・肩書き・写真、右に items(heading があれば右上の見出しに)。
48
+ */
49
+ export const ProfileSlide = (slide) => {
50
+ const [heading, rest] = pick(slide.items, ["heading"]);
51
+ return (_jsxs("div", { className: `${PAGE} b-profile`, children: [heading && (_jsx(SlideHeading, { block: heading, description: slide.description })), _jsxs("div", { className: "grid min-h-0 flex-1 grid-cols-[380px_1fr] gap-12", children: [_jsxs("div", { className: "relative flex flex-col items-center justify-center gap-6 overflow-hidden rounded-2xl bg-linear-to-br from-primary to-primary-deep px-8 py-10 text-center text-surface", children: [_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute -right-20 -bottom-24 size-72 rounded-full bg-accent/15" }), slide.photo ? (_jsx("img", { className: "relative size-52 rounded-full object-cover ring-6 ring-accent", src: slide.photo, alt: "" })) : (_jsx("div", { className: "relative flex size-52 items-center justify-center rounded-full bg-surface/10 text-display font-extrabold text-accent ring-6 ring-accent", children: Array.from(slide.name)[0] })), _jsxs("div", { className: "relative flex flex-col gap-1", children: [_jsx("span", { className: "text-h3 font-bold", children: slide.name }), slide.role && _jsx("span", { className: "text-body text-accent", children: slide.role }), slide.affiliation && _jsx("span", { className: "text-small opacity-85", children: slide.affiliation })] }), slide.accounts && (_jsx("div", { className: "relative flex flex-col gap-1 text-small", children: Object.entries(slide.accounts).map(([service, id]) => (_jsxs("span", { children: [_jsx("span", { className: "mr-2 text-accent", children: ACCOUNT_LABEL[service.toLowerCase()] ?? service }), "@", id] }, service))) }))] }), _jsx("div", { className: "flex min-w-0 flex-col justify-center gap-6", children: rest.map((b) => (_jsx(Block, { data: b }, b.id))) })] })] }));
52
+ };
53
+ export const sectionHeaderType = z.object({
54
+ number: z.string().optional().describe("章番号。\"01\" のように表示したい文字列"),
55
+ });
56
+ /**
57
+ * 章扉。表紙と同じ primary の地と accent の縦バーで、本文ページとの切り替わりを見せる。
58
+ * number は左上に accent で大きく、右下に透かしでもう一度出す
59
+ */
60
+ export const SectionHeaderSlide = (slide) => {
61
+ const [heading, rest] = pick(slide.items, ["heading"]);
62
+ const [bodies] = pickAll(rest, ["body"]);
63
+ return (_jsxs("div", { className: "b-section absolute inset-0 flex flex-col justify-center overflow-hidden bg-linear-to-br from-primary to-primary-deep px-20 py-14 text-surface [&_.b-heading]:m-0 [&_.b-heading]:text-[64px] [&_.b-heading]:leading-tight [&_.b-heading]:text-surface [&_.b-body]:m-0 [&_.b-body]:text-h3 [&_.b-body]:text-accent", children: [slide.number && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute -right-6 -bottom-28 text-[420px] leading-none font-extrabold text-surface/5 select-none", children: slide.number })), _jsx("div", { "aria-hidden": "true", className: "absolute inset-x-0 bottom-0 h-3 bg-accent" }), _jsxs("div", { className: "relative flex flex-col gap-6", children: [slide.number && _jsx("div", { className: "text-display leading-none font-extrabold text-accent", children: slide.number }), _jsxs("div", { className: "flex flex-col gap-4 border-l-[10px] border-accent pl-8", children: [heading && _jsx(Block, { data: heading }), bodies.map((b) => (_jsx(Block, { data: b }, b.id)))] })] })] }));
64
+ };
65
+ /** 見出し + 前置き + left / right の 2 列。left / right の無い block は前置きとして列の上に置く */
66
+ export const TwoColumnSlide = (slide) => {
67
+ const [heading, rest] = pick(slide.items, ["heading"]);
68
+ const [right, rest2] = pickAll(rest, ["right"]);
69
+ const [left, lead] = pickAll(rest2, ["left"]);
70
+ // 列の中の code が収まるよう、pane 相当の寸法を渡す(幅は列幅、高さは列の半分程度を上限とみなす)
71
+ const column = (blocks) => (_jsx("div", { className: "flex min-w-0 flex-col gap-5 [&_.b-heading]:text-h3 [&_.b-heading]:text-primary", style: { "--pane-w": "540px", "--pane-h": "260px" }, children: blocks.map((b) => (_jsx(Block, { data: b }, b.id))) }));
72
+ return (_jsxs("div", { className: `${PAGE} b-two-column`, children: [heading && _jsx(SlideHeading, { block: heading, description: slide.description }), lead.length > 0 && (_jsx("div", { className: "flex flex-col gap-3", children: lead.map((b) => (_jsx(Block, { data: b }, b.id))) })), _jsxs("div", { className: "grid min-h-0 flex-1 grid-cols-2 gap-10", children: [column(left), column(right)] })] }));
73
+ };
74
+ // ---- block ----
75
+ export const DefaultBlock = (block) => _jsx(RichText, { as: "div", className: "b-body", text: block.text });
76
+ export const headingType = z.object({
77
+ level: z.number().int().min(1).max(4).optional().describe("見出しレベル 1〜4。既定 2"),
78
+ });
79
+ const HEADING_SIZE = { 1: "text-h1", 2: "text-h2", 3: "text-h3", 4: "text-h4" };
80
+ /** 見出し。文字サイズは level で決まるが、slide 側が `[&_.b-heading]:text-*` で上書きできる */
81
+ export const HeadingBlock = (block) => {
82
+ const level = (block.level ?? 2);
83
+ const Tag = `h${level}`;
84
+ return (_jsx(Tag, { className: `b-heading m-0 leading-tight font-bold ${HEADING_SIZE[level]}`, children: _jsx(RichText, { text: block.text }) }));
85
+ };
86
+ export const BodyBlock = (block) => _jsx(RichText, { as: "div", className: "b-body", text: block.text });
87
+ export const listType = z.object({
88
+ ordered: z.boolean().optional().describe("番号付きにする"),
89
+ focus: z.number().int().min(1).optional().describe("焦点にする項目の番号(1 始まり)。他の項目は薄くなる"),
90
+ });
91
+ /** text の各行を項目にする。markdown の箇条書きは body でも書けるので、こちらは行区切りの簡易記法 */
92
+ export const ListBlock = (block) => {
93
+ const lines = (block.text ?? "").split("\n").filter((l) => l.trim().length > 0);
94
+ const Tag = block.ordered ? "ol" : "ul";
95
+ return (_jsx(Tag, { className: `b-list m-0 pl-[1.2em] marker:text-accent ${block.ordered ? "list-decimal" : "list-disc"}`, children: lines.map((line, i) => (_jsx("li", { className: `my-1 ${block.focus ? (block.focus === i + 1 ? "font-bold text-primary" : "opacity-50") : ""}`, children: _jsx(RichText, { text: line }) }, i))) }));
96
+ };
97
+ export const codeType = z.object({
98
+ lang: z.string().optional().describe("言語。省略で自動判定、text でログなどを無色表示"),
99
+ caption: z.string().optional().describe("コードの下に添える 1 行"),
100
+ focus: z
101
+ .union([z.string(), z.number().int().min(1), z.array(z.union([z.string(), z.number().int().min(1)]))])
102
+ .optional()
103
+ .describe('焦点にする行。行番号(1 始まり)、"6-8" の範囲、または行に含まれる文字列。配列で複数可。他の行は薄くなる'),
104
+ });
105
+ /** focus の指定を行番号(0 始まり)の集合にする */
106
+ export function focusLines(lines, focus) {
107
+ const set = new Set();
108
+ if (focus === undefined)
109
+ return set;
110
+ for (const f of Array.isArray(focus) ? focus : [focus]) {
111
+ if (typeof f === "number") {
112
+ set.add(f - 1);
113
+ continue;
114
+ }
115
+ const range = f.match(/^(\d+)-(\d+)$/);
116
+ if (range) {
117
+ for (let i = Number(range[1]); i <= Number(range[2]); i++)
118
+ set.add(i - 1);
119
+ continue;
120
+ }
121
+ lines.forEach((l, i) => {
122
+ if (l.includes(f))
123
+ set.add(i);
124
+ });
125
+ }
126
+ return set;
127
+ }
128
+ /**
129
+ * ハイライト済み HTML を行ごとに分ける。行をまたぐ span(複数行コメントなど)は
130
+ * 行末で閉じて次の行頭で開き直す。
131
+ */
132
+ export function splitHighlighted(html) {
133
+ const out = [];
134
+ const open = [];
135
+ for (const raw of html.split("\n")) {
136
+ let line = open.join("");
137
+ for (const m of raw.matchAll(/<span[^>]*>|<\/span>/g)) {
138
+ if (m[0] === "</span>")
139
+ open.pop();
140
+ else
141
+ open.push(m[0]);
142
+ }
143
+ line += raw + "</span>".repeat(open.length);
144
+ out.push(line);
145
+ }
146
+ return out;
147
+ }
148
+ /**
149
+ * コード。highlight.js で SSG 時に色付けする。
150
+ * 行数と最大行長を CSS 変数で渡し、pane に収まるフォントサイズを CSS の calc で決める(styles.ts)。
151
+ */
152
+ /** コードの最大行幅(全角 2)と行数。フォントサイズの計算に使う */
153
+ export function codeSize(text) {
154
+ const lines = (text ?? "").replace(/\n$/, "").split("\n");
155
+ return { cols: Math.max(1, ...lines.map(displayWidth)), rows: lines.length };
156
+ }
157
+ /** 箱の上下余白(40px)と、caption があればその 1 行分(40px)。高さからこの分を引いた残りに行を収める */
158
+ export function codeChrome(caption) {
159
+ return caption ? 80 : 40;
160
+ }
161
+ export const CodeBlock = (block) => {
162
+ const code = (block.text ?? "").replace(/\n$/, "");
163
+ const lines = code.split("\n");
164
+ const { cols } = codeSize(code);
165
+ // lang 無しは自動判定、text / plain はログなどの無色表示
166
+ const plain = block.lang === "text" || block.lang === "plain" || block.lang === "plaintext";
167
+ const lang = block.lang && hljs.getLanguage(block.lang) ? block.lang : undefined;
168
+ const html = plain ? escapeHtml(code) : lang ? hljs.highlight(code, { language: lang }).value : hljs.highlightAuto(code).value;
169
+ const focus = focusLines(lines, block.focus);
170
+ const rows = splitHighlighted(html);
171
+ // 箱は内容の高さで止め、pane の中では縦中央に置く(短いコードで黒い箱が間延びしない)
172
+ return (_jsxs("figure", { className: "m-0 flex min-h-0 flex-1 flex-col justify-center gap-2", children: [_jsx("pre", { className: "b-code m-0 max-h-full min-h-0 overflow-hidden rounded-lg bg-code py-5 font-mono leading-snug text-code-ink", "data-lang": block.lang, style: { "--code-cols": cols, "--code-rows": lines.length, "--code-chrome": `${codeChrome(block.caption)}px` }, children: _jsx("code", { className: "hljs block", children: rows.map((row, i) => (_jsx("span", { className: `block border-l-4 px-5 ${focus.size === 0 ? "border-transparent" : focus.has(i) ? "border-accent bg-accent/15" : "border-transparent opacity-40"}`, dangerouslySetInnerHTML: { __html: row || " " } }, i))) }) }), block.caption && (_jsx("figcaption", { className: "shrink-0 text-small text-muted", children: _jsx(RichText, { text: block.caption }) }))] }));
173
+ };
174
+ export const imageType = z.object({
175
+ src: z.string().describe("画像のパス(public/ なら ./name.png)か URL"),
176
+ alt: z.string().optional().describe("代替テキスト"),
177
+ width: z.union([z.string(), z.number()]).optional().describe("幅を固定したいときだけ。既定は pane いっぱい"),
178
+ });
179
+ /** 画像。pane いっぱいにアスペクト比を保って収める。width 指定があればその幅にする */
180
+ export const ImageBlock = (block) => (_jsxs("figure", { className: "b-image m-0 flex min-h-0 flex-1 flex-col items-center gap-2", children: [_jsx("img", { className: block.width ? "max-h-full" : "min-h-0 w-full flex-1 object-contain", src: block.src, alt: block.alt ?? "", style: block.width ? { width: block.width } : undefined }), block.text && (_jsx("figcaption", { className: "shrink-0 text-small text-muted", children: _jsx(RichText, { text: block.text }) }))] }));
181
+ export const videoType = z.object({
182
+ url: z.string().describe("YouTube の watch / youtu.be / shorts の URL、または iframe で開ける URL"),
183
+ });
184
+ /** 動画。YouTube は embed URL に変換して iframe で埋め込む。text はキャプション */
185
+ export const VideoBlock = (block) => (_jsxs("figure", { className: "b-video m-0 flex min-h-0 flex-1 flex-col items-center gap-2", children: [_jsx("iframe", { className: "min-h-0 w-full flex-1 rounded-lg border-0 bg-code", src: toEmbedUrl(block.url), allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true }), block.text && (_jsx("figcaption", { className: "shrink-0 text-small text-muted", children: _jsx(RichText, { text: block.text }) }))] }));
186
+ /** 等幅フォントでの表示幅。全角(CJK や全角記号)は半角 2 つ分として数える */
187
+ function displayWidth(line) {
188
+ let w = 0;
189
+ for (const ch of line) {
190
+ const cp = ch.codePointAt(0);
191
+ w += cp >= 0x1100 && (cp <= 0x115f || (cp >= 0x2e80 && cp <= 0xa4cf) || (cp >= 0xac00 && cp <= 0xd7a3) || (cp >= 0xf900 && cp <= 0xfaff) || (cp >= 0xfe30 && cp <= 0xfe4f) || (cp >= 0xff00 && cp <= 0xff60) || (cp >= 0xffe0 && cp <= 0xffe6) || cp >= 0x20000) ? 2 : 1;
192
+ }
193
+ return w;
194
+ }
195
+ function escapeHtml(s) {
196
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
197
+ }
198
+ export function toEmbedUrl(url) {
199
+ const m = url.match(/(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([\w-]{11})/);
200
+ return m ? `https://www.youtube.com/embed/${m[1]}` : url;
201
+ }
202
+ export const statType = z.object({
203
+ value: z.string().describe("大きく出す値。数字や固有名詞"),
204
+ label: z.string().optional().describe("値の説明。1 行"),
205
+ });
206
+ /** 数字や固有名詞を主役にする block。text は補足として小さく出す */
207
+ export const StatBlock = (block) => (_jsxs("div", { className: "b-stat flex items-baseline gap-5", children: [_jsx("span", { className: "w-[240px] shrink-0 text-right text-h1 leading-none font-extrabold text-primary", children: _jsx(RichText, { text: block.value }) }), _jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [block.label && (_jsx("span", { className: "text-h4 leading-tight font-bold", children: _jsx(RichText, { text: block.label }) })), block.text && (_jsx("span", { className: "text-small leading-snug text-muted", children: _jsx(RichText, { text: block.text }) }))] })] }));
208
+ export const itemType = z.object({
209
+ title: z.string().describe("項目名"),
210
+ logo: z.string().optional().describe("項目のロゴ画像"),
211
+ });
212
+ /** 並列の項目。タイトルと説明を持つ。見せ方(カードにするか等)は slide の Layout が決める */
213
+ export const ItemBlock = (block) => (_jsxs("div", { className: "b-item flex flex-col gap-2", children: [block.logo && _jsx("img", { className: "h-14 w-auto", src: block.logo, alt: "" }), _jsx("span", { className: "text-h4 leading-tight font-bold [word-break:keep-all]", children: _jsx(RichText, { text: block.title }) }), block.text && (_jsx("span", { className: "text-body leading-snug text-muted", children: _jsx(RichText, { text: block.text }) }))] }));
214
+ export const quoteType = z.object({
215
+ cite: z.string().optional().describe("出典"),
216
+ });
217
+ export const QuoteBlock = (block) => (_jsxs("blockquote", { className: "b-quote m-0 border-l-[6px] border-primary px-6 py-2 text-muted", children: [_jsx(RichText, { as: "div", className: "b-body", text: block.text }), block.cite && _jsx("cite", { className: "mt-2 block text-small text-faint", children: block.cite })] }));
218
+ /** 発表者ノート。画面・印刷には出さず、presenter モードが `.yd-notes` を拾って表示する */
219
+ export const NoteBlock = (block) => (_jsx("div", { className: "yd-notes b-note", hidden: true, children: _jsx(RichText, { as: "div", text: block.text }) }));
220
+ //# sourceMappingURL=layouts.js.map