@hackersheet/next-document-content-kifu 0.1.0-alpha.1 → 0.1.0-alpha.11

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.
Files changed (32) hide show
  1. package/dist/cjs/components/kifu/kifu.d.ts +1 -1
  2. package/dist/cjs/components/kifu/kifu.js +5 -21
  3. package/dist/cjs/components/kifu-to/kifu-to.js +1 -1
  4. package/dist/cjs/components/shogi-player/button.d.ts +8 -0
  5. package/dist/cjs/components/shogi-player/button.js +44 -0
  6. package/dist/cjs/components/shogi-player/index.d.ts +2 -0
  7. package/dist/cjs/components/shogi-player/index.js +38 -0
  8. package/dist/cjs/components/shogi-player/moves-area.d.ts +11 -0
  9. package/dist/cjs/components/shogi-player/moves-area.js +78 -0
  10. package/dist/cjs/components/shogi-player/shogi-board-canvas.d.ts +17 -0
  11. package/dist/cjs/components/shogi-player/shogi-board-canvas.js +180 -0
  12. package/dist/cjs/components/shogi-player/shogi-hands-canvas.d.ts +16 -0
  13. package/dist/cjs/components/shogi-player/shogi-hands-canvas.js +140 -0
  14. package/dist/cjs/components/shogi-player/shogi-player.d.ts +10 -0
  15. package/dist/cjs/components/shogi-player/shogi-player.js +112 -0
  16. package/dist/cjs/index.js +3 -3
  17. package/dist/esm/components/kifu/kifu.d.mts +1 -1
  18. package/dist/esm/components/kifu/kifu.mjs +5 -21
  19. package/dist/esm/components/kifu-to/kifu-to.mjs +1 -1
  20. package/dist/esm/components/shogi-player/button.d.mts +8 -0
  21. package/dist/esm/components/shogi-player/button.mjs +14 -0
  22. package/dist/esm/components/shogi-player/index.d.mts +2 -0
  23. package/dist/esm/components/shogi-player/index.mjs +4 -0
  24. package/dist/esm/components/shogi-player/moves-area.d.mts +11 -0
  25. package/dist/esm/components/shogi-player/moves-area.mjs +44 -0
  26. package/dist/esm/components/shogi-player/shogi-board-canvas.d.mts +17 -0
  27. package/dist/esm/components/shogi-player/shogi-board-canvas.mjs +150 -0
  28. package/dist/esm/components/shogi-player/shogi-hands-canvas.d.mts +16 -0
  29. package/dist/esm/components/shogi-player/shogi-hands-canvas.mjs +110 -0
  30. package/dist/esm/components/shogi-player/shogi-player.d.mts +10 -0
  31. package/dist/esm/components/shogi-player/shogi-player.mjs +82 -0
  32. package/package.json +13 -13
@@ -1,6 +1,6 @@
1
1
  import { KifuComponentProps } from '@hackersheet/react-document-content';
2
2
  import React from 'react';
3
3
 
4
- declare function Kifu({ code, language }: KifuComponentProps): React.JSX.Element | null;
4
+ declare function Kifu({ code, language }: KifuComponentProps): React.JSX.Element;
5
5
 
6
6
  export { Kifu as default };
@@ -32,36 +32,20 @@ __export(kifu_exports, {
32
32
  default: () => Kifu
33
33
  });
34
34
  module.exports = __toCommonJS(kifu_exports);
35
- var import_kifu_for_js = require("kifu-for-js");
36
35
  var import_navigation = require("next/navigation");
37
36
  var import_react = __toESM(require("react"));
37
+ var import_shogi_player = require("../shogi-player");
38
38
  function Kifu({ code, language }) {
39
+ const [ply, setPly] = (0, import_react.useState)(0);
39
40
  const [, filename] = language.split(":");
40
41
  const searchParams = (0, import_navigation.useSearchParams)();
41
42
  const id = filename ? `user-content-${filename}` : void 0;
42
- const [kifuStore] = (0, import_react.useState)(() => new import_kifu_for_js.KifuStore({ kifu: code }));
43
- (0, import_react.useEffect)(() => {
44
- initKifuUserSettings();
45
- }, []);
46
43
  (0, import_react.useEffect)(() => {
47
44
  const newPly = Number(searchParams.get("ply") ?? 0);
48
45
  const hash = typeof window !== "undefined" ? window.location.hash.replace(/^#!?/, "") : "";
49
46
  if (hash === id) {
50
- kifuStore.player.goto(newPly);
47
+ setPly(newPly);
51
48
  }
52
- }, [searchParams, kifuStore, id]);
53
- if (!kifuStore) {
54
- return null;
55
- }
56
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "my-4 flex justify-center", id }, /* @__PURE__ */ import_react.default.createElement(import_kifu_for_js.KifuLite, { style: { width: "100%" }, kifuStore }));
57
- }
58
- function initKifuUserSettings() {
59
- const LOCALSTORAGE_KEY = "kifuforjs";
60
- const defaultSettings = {
61
- hapticFeedback: false
62
- };
63
- const settings = localStorage.getItem(LOCALSTORAGE_KEY);
64
- if (!settings) {
65
- localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(defaultSettings));
66
- }
49
+ }, [searchParams, id]);
50
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "kifu-block", id }, /* @__PURE__ */ import_react.default.createElement(import_shogi_player.ShogiPlayer, { kifuText: code, tesuu: ply, size: 320 }));
67
51
  }
@@ -37,5 +37,5 @@ function KifuTo({ id, ply, label: defaultLabel }) {
37
37
  const fullId = `user-content-${id}`;
38
38
  const href = `?ply=${ply}#${fullId}`;
39
39
  const label = defaultLabel ?? `${ply}\u624B\u76EE`;
40
- return /* @__PURE__ */ import_react.default.createElement(import_link.default, { href }, label);
40
+ return /* @__PURE__ */ import_react.default.createElement(import_link.default, { href, prefetch: false }, label);
41
41
  }
@@ -0,0 +1,8 @@
1
+ import React, { MouseEventHandler, PropsWithChildren } from 'react';
2
+
3
+ type ButtonProps = {
4
+ onClick?: MouseEventHandler<HTMLButtonElement>;
5
+ } & PropsWithChildren;
6
+ declare function Button({ children, onClick }: ButtonProps): React.JSX.Element;
7
+
8
+ export { type ButtonProps, Button as default };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var button_exports = {};
30
+ __export(button_exports, {
31
+ default: () => Button
32
+ });
33
+ module.exports = __toCommonJS(button_exports);
34
+ var import_react = __toESM(require("react"));
35
+ function Button({ children, onClick }) {
36
+ return /* @__PURE__ */ import_react.default.createElement(
37
+ "button",
38
+ {
39
+ className: "border-2 text-xs text-black p-2 border-black rounded-lg hover:bg-amber-100 cursor-pointer",
40
+ onClick
41
+ },
42
+ children
43
+ );
44
+ }
@@ -0,0 +1,2 @@
1
+ export { default as ShogiPlayer } from './shogi-player.js';
2
+ import 'react';
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var shogi_player_exports = {};
30
+ __export(shogi_player_exports, {
31
+ ShogiPlayer: () => import_shogi_player.default
32
+ });
33
+ module.exports = __toCommonJS(shogi_player_exports);
34
+ var import_shogi_player = __toESM(require("./shogi-player"));
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ ShogiPlayer
38
+ });
@@ -0,0 +1,11 @@
1
+ import { IMoveFormat } from 'json-kifu-format/dist/src/Formats';
2
+ import React from 'react';
3
+
4
+ type MovesAreaProps = {
5
+ moves: IMoveFormat[];
6
+ tesuu: number;
7
+ onTesuuChange?: (tesuu: number) => void;
8
+ };
9
+ declare function MovesArea(props: MovesAreaProps): React.JSX.Element;
10
+
11
+ export { MovesArea, type MovesAreaProps };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var moves_area_exports = {};
31
+ __export(moves_area_exports, {
32
+ MovesArea: () => MovesArea
33
+ });
34
+ module.exports = __toCommonJS(moves_area_exports);
35
+ var import_json_kifu_format = require("json-kifu-format");
36
+ var import_react = __toESM(require("react"));
37
+ function MovesArea(props) {
38
+ const moves = props.moves;
39
+ const scrollRef = (0, import_react.useRef)(null);
40
+ const containerRef = (0, import_react.useRef)(null);
41
+ (0, import_react.useEffect)(() => {
42
+ if (scrollRef.current && containerRef.current) {
43
+ const containerRect = containerRef.current.getBoundingClientRect();
44
+ const scrollRect = scrollRef.current.getBoundingClientRect();
45
+ const offset = scrollRect.top - containerRect.top + containerRef.current.scrollTop - 72;
46
+ containerRef.current.scrollTo({
47
+ top: offset,
48
+ behavior: "auto"
49
+ });
50
+ }
51
+ }, [props.tesuu]);
52
+ const current = 0 === props.tesuu ? " bg-amber-600" : "";
53
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "absolute overflow-y-auto h-full w-full border-2 border-black text-black", ref: containerRef }, /* @__PURE__ */ import_react.default.createElement("div", { className: "grid gap-0 text-xs" }, /* @__PURE__ */ import_react.default.createElement(
54
+ "div",
55
+ {
56
+ onClick: () => props.onTesuuChange && props.onTesuuChange(0),
57
+ className: "col-span-500 grid grid-cols-subgrid gap-2 py-1 px-2 cursor-pointer hover:bg-amber-100" + current
58
+ },
59
+ /* @__PURE__ */ import_react.default.createElement("div", null, 0 === props.tesuu && /* @__PURE__ */ import_react.default.createElement("div", { ref: scrollRef })),
60
+ /* @__PURE__ */ import_react.default.createElement("div", null, "\u958B\u59CB\u5C40\u9762")
61
+ ), moves.map((move, index) => {
62
+ if (index === 0) return;
63
+ const current2 = index === props.tesuu ? " bg-amber-600" : "";
64
+ return /* @__PURE__ */ import_react.default.createElement(import_react.Fragment, { key: index }, /* @__PURE__ */ import_react.default.createElement(
65
+ "div",
66
+ {
67
+ className: "col-span-500 grid grid-cols-subgrid border-black gap-2 border-t py-1 px-2 cursor-pointer hover:bg-amber-100" + current2,
68
+ onClick: () => props.onTesuuChange && props.onTesuuChange(index)
69
+ },
70
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "flex" }, index === props.tesuu && /* @__PURE__ */ import_react.default.createElement("div", { ref: scrollRef }), /* @__PURE__ */ import_react.default.createElement("div", { className: "tabular-nums text-right flex-auto" }, index)),
71
+ /* @__PURE__ */ import_react.default.createElement("div", null, import_json_kifu_format.JKFPlayer.moveToReadableKifu(move))
72
+ ));
73
+ })));
74
+ }
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ MovesArea
78
+ });
@@ -0,0 +1,17 @@
1
+ import { IMoveMoveFormat } from 'json-kifu-format/dist/src/Formats';
2
+ import React from 'react';
3
+ import { Piece } from 'shogi.js';
4
+
5
+ type Props = {
6
+ size?: number;
7
+ boardColor?: string;
8
+ lineColor?: string;
9
+ fontFamily?: string;
10
+ fontSizeRatio?: number;
11
+ pieces: Piece[][];
12
+ isSente?: boolean;
13
+ currentMove?: IMoveMoveFormat;
14
+ };
15
+ declare const ShogiBoardCanvas: React.FC<Props>;
16
+
17
+ export { ShogiBoardCanvas as default };
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var shogi_board_canvas_exports = {};
31
+ __export(shogi_board_canvas_exports, {
32
+ default: () => shogi_board_canvas_default
33
+ });
34
+ module.exports = __toCommonJS(shogi_board_canvas_exports);
35
+ var import_json_kifu_format = require("json-kifu-format");
36
+ var import_react = __toESM(require("react"));
37
+ var import_shogi = require("shogi.js");
38
+ const getCanvasDimensions = (size) => {
39
+ const dpr = window.devicePixelRatio || 1;
40
+ return { width: size * dpr, height: size * dpr, dpr };
41
+ };
42
+ const getBoardLayout = (size) => {
43
+ const margin = size * 0.06;
44
+ const boardSize = size - margin * 2;
45
+ const cell = boardSize / 9;
46
+ return { margin, boardSize, cell };
47
+ };
48
+ const drawBackground = (ctx, size, boardColor) => {
49
+ ctx.fillStyle = boardColor;
50
+ ctx.fillRect(0, 0, size, size);
51
+ };
52
+ const drawBoard = (ctx, margin, boardSize, lineColor) => {
53
+ ctx.strokeStyle = lineColor;
54
+ ctx.lineWidth = 2;
55
+ ctx.strokeRect(margin, margin, boardSize, boardSize);
56
+ ctx.lineWidth = 1;
57
+ Array.from({ length: 8 }).forEach((_, i) => {
58
+ const offset = (i + 1) * (boardSize / 9);
59
+ ctx.beginPath();
60
+ ctx.moveTo(margin + offset, margin);
61
+ ctx.lineTo(margin + offset, margin + boardSize);
62
+ ctx.stroke();
63
+ ctx.beginPath();
64
+ ctx.moveTo(margin, margin + offset);
65
+ ctx.lineTo(margin + boardSize, margin + offset);
66
+ ctx.stroke();
67
+ });
68
+ };
69
+ const drawPieces = (ctx, pieces, margin, cell, fontFamily, fontSizeRatio, isSente) => {
70
+ ctx.textAlign = "center";
71
+ ctx.textBaseline = "middle";
72
+ pieces.forEach((row, rowIndex) => {
73
+ row.forEach((piece, colIndex) => {
74
+ if (!piece) return;
75
+ const x = isSente ? 8 - rowIndex : rowIndex;
76
+ const y = isSente ? colIndex : 8 - colIndex;
77
+ const px = margin + x * cell + cell / 2;
78
+ const py = margin + y * cell + cell / 2;
79
+ ctx.save();
80
+ ctx.translate(px, py);
81
+ if (isSente && piece.color === import_shogi.Color.White) {
82
+ ctx.rotate(Math.PI);
83
+ } else if (!isSente && piece.color === import_shogi.Color.Black) {
84
+ ctx.rotate(Math.PI);
85
+ }
86
+ const kan = import_json_kifu_format.JKFPlayer.kindToKan(piece.kind);
87
+ ctx.fillStyle = "#000";
88
+ if (kan.length === 2) {
89
+ const baseFontSize = cell * fontSizeRatio * 0.5;
90
+ ctx.font = `${baseFontSize}px ${fontFamily}`;
91
+ const scaleX = 2;
92
+ const scaleY = 1;
93
+ const offsetY = cell * 0.18;
94
+ ctx.save();
95
+ ctx.scale(scaleX, scaleY);
96
+ ctx.fillText(kan[0], 0 / scaleX, -offsetY / scaleY);
97
+ ctx.restore();
98
+ ctx.save();
99
+ ctx.scale(scaleX, scaleY);
100
+ ctx.fillText(kan[1], 0 / scaleX, offsetY / scaleY);
101
+ ctx.restore();
102
+ } else {
103
+ const fontSize = cell * fontSizeRatio;
104
+ ctx.font = `${fontSize}px ${fontFamily}`;
105
+ ctx.fillText(kan, 0, 0);
106
+ }
107
+ ctx.restore();
108
+ });
109
+ });
110
+ };
111
+ const drawCoordinates = (ctx, margin, boardSize, cell, fontFamily, isSente) => {
112
+ ctx.fillStyle = "#000";
113
+ ctx.font = `${cell * 0.35}px ${fontFamily}`;
114
+ ctx.textAlign = "center";
115
+ ctx.textBaseline = "middle";
116
+ Array.from({ length: 9 }).forEach((_, i) => {
117
+ const x = margin + i * cell + cell / 2;
118
+ const y = margin / 2;
119
+ const label = isSente ? import_json_kifu_format.JKFPlayer.numToZen(9 - i) : import_json_kifu_format.JKFPlayer.numToZen(i + 1);
120
+ ctx.fillText(label, x, y);
121
+ });
122
+ Array.from({ length: 9 }).forEach((_, i) => {
123
+ const x = margin + boardSize + margin / 2;
124
+ const y = margin + i * cell + cell / 2;
125
+ const label = isSente ? import_json_kifu_format.JKFPlayer.numToKan(i + 1) : import_json_kifu_format.JKFPlayer.numToKan(9 - i);
126
+ ctx.fillText(label, x, y);
127
+ });
128
+ };
129
+ const drawHighlightedCell = (ctx, margin, cell, isSente, currentMove) => {
130
+ if (!currentMove) return;
131
+ if (currentMove.to) {
132
+ const toRow = currentMove.to.x - 1;
133
+ const toCol = currentMove.to.y - 1;
134
+ const toX = isSente ? 8 - toRow : toRow;
135
+ const toY = isSente ? toCol : 8 - toCol;
136
+ ctx.fillStyle = "rgba(255,0,0,0.1)";
137
+ ctx.fillRect(margin + toX * cell, margin + toY * cell, cell, cell);
138
+ }
139
+ if (currentMove.from) {
140
+ const fromRow = currentMove.from.x - 1;
141
+ const fromCol = currentMove.from.y - 1;
142
+ const fromX = isSente ? 8 - fromRow : fromRow;
143
+ const fromY = isSente ? fromCol : 8 - fromCol;
144
+ ctx.fillStyle = "rgba(255,0,0,0.1)";
145
+ ctx.fillRect(margin + fromX * cell, margin + fromY * cell, cell, cell);
146
+ }
147
+ };
148
+ const ShogiBoardCanvas = ({
149
+ size = 360,
150
+ boardColor = "#f9d27a",
151
+ lineColor = "#000",
152
+ fontFamily = "serif",
153
+ fontSizeRatio = 0.7,
154
+ pieces,
155
+ isSente = true,
156
+ currentMove
157
+ }) => {
158
+ const canvasRef = import_react.default.useRef(null);
159
+ import_react.default.useEffect(() => {
160
+ const canvas = canvasRef.current;
161
+ if (!canvas) return;
162
+ const ctx = canvas.getContext("2d");
163
+ if (!ctx) return;
164
+ const { width, height, dpr } = getCanvasDimensions(size);
165
+ canvas.width = width;
166
+ canvas.height = height;
167
+ canvas.style.width = `${size}px`;
168
+ canvas.style.height = `${size}px`;
169
+ ctx.scale(dpr, dpr);
170
+ ctx.clearRect(0, 0, size, size);
171
+ const { margin, boardSize, cell } = getBoardLayout(size);
172
+ drawBackground(ctx, size, boardColor);
173
+ drawBoard(ctx, margin, boardSize, lineColor);
174
+ drawHighlightedCell(ctx, margin, cell, isSente, currentMove);
175
+ drawPieces(ctx, pieces, margin, cell, fontFamily, fontSizeRatio, isSente);
176
+ drawCoordinates(ctx, margin, boardSize, cell, fontFamily, isSente);
177
+ }, [size, boardColor, lineColor, fontFamily, fontSizeRatio, pieces, isSente, currentMove]);
178
+ return /* @__PURE__ */ import_react.default.createElement("canvas", { ref: canvasRef, width: size, height: size });
179
+ };
180
+ var shogi_board_canvas_default = ShogiBoardCanvas;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { Piece } from 'shogi.js';
3
+
4
+ type Props = {
5
+ size?: number;
6
+ boardColor?: string;
7
+ lineColor?: string;
8
+ fontFamily?: string;
9
+ fontSizeRatio?: number;
10
+ hands: Piece[][];
11
+ isSente?: boolean;
12
+ isTop?: boolean;
13
+ };
14
+ declare const ShogiHandsCanvas: React.FC<Props>;
15
+
16
+ export { ShogiHandsCanvas as default };
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var shogi_hands_canvas_exports = {};
31
+ __export(shogi_hands_canvas_exports, {
32
+ default: () => shogi_hands_canvas_default
33
+ });
34
+ module.exports = __toCommonJS(shogi_hands_canvas_exports);
35
+ var import_json_kifu_format = require("json-kifu-format");
36
+ var import_react = __toESM(require("react"));
37
+ var import_shogi = require("shogi.js");
38
+ const getCanvasDimensions = (size) => {
39
+ const dpr = window.devicePixelRatio || 1;
40
+ return { width: size * dpr, height: size * dpr, dpr };
41
+ };
42
+ const getHandsLayout = (size) => {
43
+ const margin = size * 0.06;
44
+ const boardSize = size - margin * 2;
45
+ const cellSize = boardSize / 9;
46
+ const handsHeight = cellSize + margin + 2;
47
+ return { margin, handsHeight, boardSize, cellSize };
48
+ };
49
+ const drawBackground = (ctx, width, height, color) => {
50
+ ctx.fillStyle = color;
51
+ ctx.fillRect(0, 0, width, height);
52
+ };
53
+ const drawHandsFrame = (ctx, x, y, width, height, lineColor, isTop) => {
54
+ ctx.strokeStyle = lineColor;
55
+ ctx.lineWidth = 2;
56
+ if (isTop) {
57
+ ctx.strokeRect(x, y, width, height);
58
+ } else {
59
+ ctx.strokeRect(x, 2, width, height);
60
+ }
61
+ };
62
+ const drawCoordinates = (ctx, fontSize, fontFamily) => {
63
+ ctx.fillStyle = "#000";
64
+ ctx.font = `${fontSize}px ${fontFamily}`;
65
+ ctx.textAlign = "center";
66
+ ctx.textBaseline = "middle";
67
+ };
68
+ const drawPieces = (ctx, hands, margin, boardSize, cell, fontFamily, fontSizeRatio, isSente, isTop) => {
69
+ ctx.textAlign = "center";
70
+ ctx.textBaseline = "middle";
71
+ const pieces = isSente && isTop || !isSente && !isTop ? hands[import_shogi.Color.White] : hands[import_shogi.Color.Black];
72
+ if (!pieces || pieces.length === 0) return;
73
+ const grouped = pieces.reduce(
74
+ (acc, piece) => {
75
+ if (!piece) return acc;
76
+ const key = piece.kind;
77
+ if (!acc[key]) acc[key] = { count: 0, color: piece.color };
78
+ acc[key].count += 1;
79
+ return acc;
80
+ },
81
+ {}
82
+ );
83
+ const order = ["OU", "HI", "KA", "KI", "GI", "KE", "KY", "FU"];
84
+ const kinds = order.filter((kind) => grouped[kind]);
85
+ kinds.forEach((kind, index) => {
86
+ const { count, color } = grouped[kind];
87
+ const px = isTop ? margin + boardSize - (index * cell + cell / 2) : margin + index * cell + cell / 2;
88
+ const py = isTop ? margin + cell / 2 : cell / 2 + 2;
89
+ ctx.save();
90
+ ctx.translate(px, py);
91
+ if (isSente && color === import_shogi.Color.White) {
92
+ ctx.rotate(Math.PI);
93
+ } else if (!isSente && color === import_shogi.Color.Black) {
94
+ ctx.rotate(Math.PI);
95
+ }
96
+ const fontSize = cell * fontSizeRatio;
97
+ const kan = import_json_kifu_format.JKFPlayer.kindToKan(kind);
98
+ ctx.font = `${fontSize}px ${fontFamily}`;
99
+ ctx.fillText(kan, 0, 0);
100
+ if (count > 1) {
101
+ ctx.font = `${fontSize * 0.5}px ${fontFamily}`;
102
+ const countOffsetX = cell * 0;
103
+ const countOffsetY = cell * 0.8;
104
+ ctx.fillText(String(count), countOffsetX, countOffsetY);
105
+ }
106
+ ctx.restore();
107
+ });
108
+ };
109
+ const ShogiHandsCanvas = ({
110
+ size = 360,
111
+ boardColor = "#f9d27a",
112
+ lineColor = "#000",
113
+ fontFamily = "serif",
114
+ fontSizeRatio = 0.7,
115
+ hands,
116
+ isSente = true,
117
+ isTop = false
118
+ }) => {
119
+ const canvasRef = import_react.default.useRef(null);
120
+ import_react.default.useEffect(() => {
121
+ const canvas = canvasRef.current;
122
+ if (!canvas) return;
123
+ const ctx = canvas.getContext("2d");
124
+ if (!ctx) return;
125
+ const { margin, handsHeight, boardSize, cellSize } = getHandsLayout(size);
126
+ const { width: canvasWidth, dpr } = getCanvasDimensions(size);
127
+ canvas.width = canvasWidth;
128
+ canvas.height = handsHeight * dpr;
129
+ canvas.style.width = `${size}px`;
130
+ canvas.style.height = `${handsHeight}px`;
131
+ ctx.scale(dpr, dpr);
132
+ ctx.clearRect(0, 0, size, handsHeight);
133
+ drawBackground(ctx, size, handsHeight, boardColor);
134
+ drawHandsFrame(ctx, margin, margin, boardSize, cellSize, lineColor, isTop);
135
+ drawCoordinates(ctx, cellSize * 0.35, fontFamily);
136
+ drawPieces(ctx, hands, margin, boardSize, cellSize, fontFamily, fontSizeRatio, isSente, isTop);
137
+ }, [size, boardColor, lineColor, fontFamily, fontSizeRatio, isSente, hands, isTop]);
138
+ return /* @__PURE__ */ import_react.default.createElement("canvas", { ref: canvasRef });
139
+ };
140
+ var shogi_hands_canvas_default = ShogiHandsCanvas;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+
3
+ type ShogiPlayerProps = {
4
+ kifuText: string;
5
+ size?: number;
6
+ tesuu?: number;
7
+ };
8
+ declare function ShogiPlayer(props: ShogiPlayerProps): React.JSX.Element;
9
+
10
+ export { type ShogiPlayerProps, ShogiPlayer as default };