chesspal 0.2.3 → 0.3.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 +11 -12
- package/dist/cli/cli.js +83 -3
- package/dist/cli/command-line.js +26 -9
- package/dist/cli/icon.d.ts +25 -0
- package/dist/cli/icon.js +80 -0
- package/dist/commands/agents.d.ts +19 -2
- package/dist/commands/agents.js +41 -14
- package/dist/commands/ai-say.d.ts +2 -1
- package/dist/commands/ai-say.js +3 -4
- package/dist/commands/analyse-game.d.ts +6 -0
- package/dist/commands/analyse-game.js +51 -15
- package/dist/commands/annotate-game.d.ts +4 -0
- package/dist/commands/annotate-game.js +60 -20
- package/dist/commands/answer-lines.d.ts +10 -4
- package/dist/commands/answer-lines.js +30 -4
- package/dist/commands/coach.js +6 -4
- package/dist/commands/context.d.ts +11 -1
- package/dist/commands/context.js +5 -0
- package/dist/commands/delete-review.js +9 -4
- package/dist/commands/game-summary.d.ts +9 -2
- package/dist/commands/game-summary.js +11 -0
- package/dist/commands/index.d.ts +4 -3
- package/dist/commands/index.js +8 -5
- package/dist/commands/init.js +2 -4
- package/dist/commands/instructions.d.ts +9 -0
- package/dist/commands/instructions.js +30 -0
- package/dist/commands/lead-input.d.ts +1 -1
- package/dist/commands/lead-input.js +7 -4
- package/dist/commands/look.d.ts +9 -5
- package/dist/commands/look.js +19 -9
- package/dist/commands/page-link.js +6 -5
- package/dist/commands/past-games.d.ts +1 -1
- package/dist/commands/past-games.js +12 -5
- package/dist/commands/player-move.js +2 -3
- package/dist/commands/ponder.js +1 -1
- package/dist/commands/position.js +2 -2
- package/dist/commands/profiles.d.ts +23 -9
- package/dist/commands/profiles.js +76 -35
- package/dist/commands/ratings.d.ts +8 -0
- package/dist/commands/ratings.js +45 -0
- package/dist/commands/registry.d.ts +1 -1
- package/dist/commands/registry.js +3 -2
- package/dist/commands/say.d.ts +11 -6
- package/dist/commands/say.js +21 -13
- package/dist/commands/status.d.ts +6 -2
- package/dist/commands/status.js +70 -26
- package/dist/commands/study.d.ts +11 -1
- package/dist/commands/study.js +39 -7
- package/dist/commands/view.d.ts +17 -5
- package/dist/commands/view.js +67 -10
- package/dist/core/facts.d.ts +14 -2
- package/dist/core/facts.js +32 -7
- package/dist/core/game.d.ts +5 -0
- package/dist/core/game.js +9 -0
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +1 -1
- package/dist/core/placement.d.ts +63 -0
- package/dist/core/placement.js +259 -0
- package/dist/core/possibilities.d.ts +38 -0
- package/dist/core/possibilities.js +254 -0
- package/dist/core/review.d.ts +6 -1
- package/dist/core/review.js +21 -6
- package/dist/games/ai-model.d.ts +4 -2
- package/dist/games/ai-model.js +10 -1
- package/dist/games/analysis.d.ts +31 -4
- package/dist/games/analysis.js +44 -5
- package/dist/games/archive.d.ts +6 -3
- package/dist/games/archive.js +13 -5
- package/dist/games/current-game.d.ts +26 -2
- package/dist/games/current-game.js +57 -21
- package/dist/games/files.d.ts +7 -0
- package/dist/games/files.js +48 -1
- package/dist/games/index.d.ts +4 -4
- package/dist/games/index.js +4 -4
- package/dist/games/table-talk.d.ts +2 -0
- package/dist/games/table-talk.js +5 -1
- package/dist/games/talk.d.ts +4 -3
- package/dist/games/talk.js +3 -3
- package/dist/home/data-folder.d.ts +2 -0
- package/dist/home/data-folder.js +5 -1
- package/dist/home/index.d.ts +1 -1
- package/dist/home/index.js +1 -1
- package/dist/host-files/agents.d.ts +2 -2
- package/dist/host-files/agents.js +12 -6
- package/dist/host-files/host-files.d.ts +5 -3
- package/dist/host-files/host-files.js +15 -8
- package/dist/host-files/index.d.ts +2 -2
- package/dist/host-files/index.js +2 -2
- package/dist/page/app/app.js +59 -22
- package/dist/page/app/keys.js +16 -2
- package/dist/page/app/served.js +2 -2
- package/dist/page/app/title.js +17 -0
- package/dist/page/avatars/torretta.js +4 -4
- package/dist/page/board/board.js +2 -1
- package/dist/page/board/marks.js +4 -24
- package/dist/page/board/signs.js +23 -0
- package/dist/page/dialogs/analyses.js +4 -4
- package/dist/page/dialogs/dialog.js +4 -1
- package/dist/page/dialogs/dialogs.css +84 -10
- package/dist/page/dialogs/profiles.js +95 -42
- package/dist/page/game/column.js +6 -2
- package/dist/page/game/game.css +12 -0
- package/dist/page/game/move-list.js +2 -2
- package/dist/page/game/plies.js +11 -0
- package/dist/page/guide/blocks.js +67 -0
- package/dist/page/guide/en.md +66 -0
- package/dist/page/guide/foot.js +18 -0
- package/dist/page/guide/guide.css +200 -0
- package/dist/page/guide/guide.js +89 -0
- package/dist/page/guide/it.md +66 -0
- package/dist/page/guide/markdown.js +67 -0
- package/dist/page/helps/helps.css +10 -11
- package/dist/page/helps/helps.js +15 -15
- package/dist/page/layout/favicon.svg +13 -0
- package/dist/page/layout/header.js +3 -3
- package/dist/page/layout/icon.icns +0 -0
- package/dist/page/layout/icon.ico +0 -0
- package/dist/page/layout/icon.png +0 -0
- package/dist/page/layout/layout.css +140 -9
- package/dist/page/layout/window.js +45 -0
- package/dist/page/legend/legend.css +203 -0
- package/dist/page/legend/legend.js +169 -0
- package/dist/page/legend/view.js +54 -0
- package/dist/page/main.js +4 -1
- package/dist/page/players/card.js +1 -1
- package/dist/page/profile/profile.js +14 -9
- package/dist/page/profile/settings.js +9 -0
- package/dist/page/style.css +4 -0
- package/dist/page/table/opener.css +65 -0
- package/dist/page/table/opener.js +59 -0
- package/dist/page/talk/chat.css +97 -0
- package/dist/page/talk/talk.css +38 -26
- package/dist/page/talk/talk.js +31 -7
- package/dist/page/text.js +120 -18
- package/dist/page/theme.css +7 -0
- package/dist/profiles/index.d.ts +2 -1
- package/dist/profiles/index.js +2 -1
- package/dist/profiles/profiles.d.ts +10 -15
- package/dist/profiles/profiles.js +30 -15
- package/dist/profiles/ratings.d.ts +35 -0
- package/dist/profiles/ratings.js +61 -0
- package/dist/server/bell.d.ts +24 -3
- package/dist/server/bell.js +84 -10
- package/dist/server/caller.d.ts +2 -1
- package/dist/server/caller.js +3 -2
- package/dist/server/mcp.d.ts +7 -3
- package/dist/server/mcp.js +106 -56
- package/dist/server/page/analyses.d.ts +2 -0
- package/dist/server/page/analyses.js +20 -5
- package/dist/server/page/attach.d.ts +4 -0
- package/dist/server/page/attach.js +112 -0
- package/dist/server/page/chat.d.ts +60 -0
- package/dist/server/page/chat.js +79 -0
- package/dist/server/page/events.d.ts +7 -0
- package/dist/server/page/events.js +20 -0
- package/dist/server/page/files.js +10 -1
- package/dist/server/page/game.js +62 -29
- package/dist/server/page/page.d.ts +47 -7
- package/dist/server/page/page.js +74 -51
- package/dist/server/page/profiles.d.ts +5 -0
- package/dist/server/page/profiles.js +26 -10
- package/dist/server/page/table.d.ts +39 -0
- package/dist/server/page/table.js +102 -0
- package/dist/server/table/browser.d.ts +6 -0
- package/dist/server/table/browser.js +48 -0
- package/dist/server/table/hosts/chats.d.ts +7 -0
- package/dist/server/table/hosts/chats.js +31 -0
- package/dist/server/table/hosts/find.d.ts +2 -0
- package/dist/server/table/hosts/find.js +20 -0
- package/dist/server/table/hosts/hosts.d.ts +34 -0
- package/dist/server/table/hosts/hosts.js +49 -0
- package/dist/server/table/hosts/index.d.ts +3 -0
- package/dist/server/table/hosts/index.js +4 -0
- package/dist/server/table/hosts/play.d.ts +25 -0
- package/dist/server/table/hosts/play.js +152 -0
- package/dist/server/table/hosts/seat.d.ts +25 -0
- package/dist/server/table/hosts/seat.js +74 -0
- package/dist/server/table/hosts/terminal.d.ts +6 -0
- package/dist/server/table/hosts/terminal.js +63 -0
- package/dist/server/table/icon/index.d.ts +32 -0
- package/dist/server/table/icon/index.js +83 -0
- package/dist/server/table/icon/linux.d.ts +5 -0
- package/dist/server/table/icon/linux.js +47 -0
- package/dist/server/table/icon/macos.d.ts +3 -0
- package/dist/server/table/icon/macos.js +38 -0
- package/dist/server/table/icon/windows.d.ts +3 -0
- package/dist/server/table/icon/windows.js +48 -0
- package/dist/server/table/index.d.ts +6 -0
- package/dist/server/table/index.js +7 -0
- package/dist/server/table/launch.d.ts +19 -0
- package/dist/server/table/launch.js +78 -0
- package/dist/server/table/link.d.ts +10 -0
- package/dist/server/table/link.js +230 -0
- package/dist/server/table/table.d.ts +35 -0
- package/dist/server/table/table.js +94 -0
- package/dist/sites/chesscom.d.ts +4 -0
- package/dist/sites/chesscom.js +25 -0
- package/dist/sites/choice.d.ts +17 -0
- package/dist/sites/choice.js +13 -0
- package/dist/sites/index.d.ts +2 -0
- package/dist/sites/index.js +4 -0
- package/dist/sites/lichess.d.ts +4 -0
- package/dist/sites/lichess.js +32 -0
- package/dist/sites/request.d.ts +11 -0
- package/dist/sites/request.js +15 -0
- package/dist/sites/sites.d.ts +6 -0
- package/dist/sites/sites.js +33 -0
- package/instructions/analysis.md +1 -1
- package/instructions/analyst-agent.md +1 -1
- package/instructions/coach.md +2 -1
- package/instructions/opponent.md +6 -6
- package/instructions/ponder.md +1 -0
- package/instructions/start.md +1 -0
- package/package.json +1 -1
|
@@ -553,6 +553,83 @@
|
|
|
553
553
|
flex: none;
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
+
/* Beside the board the talk is a row a side, each half the column, or what its card, note and box need when that is more: only the words give way, and
|
|
557
|
+
never spill over the other side (Stefano, Zoe). Turned round, the player's row comes first. In analysis the AI's note keeps its height while the thread
|
|
558
|
+
gives way, and scrolls by itself only when nothing else is left to give */
|
|
559
|
+
@media (min-width: 841px) {
|
|
560
|
+
.talk {
|
|
561
|
+
display: grid;
|
|
562
|
+
grid-template-rows: minmax(min-content, 1fr) minmax(min-content, 1fr);
|
|
563
|
+
container: talk / size;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.ai-block,
|
|
567
|
+
.you-block {
|
|
568
|
+
max-height: none;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/* The player's card stays by the board's edge when the words above it go */
|
|
572
|
+
.you-block {
|
|
573
|
+
justify-content: flex-end;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.flipped .ai-block {
|
|
577
|
+
grid-row: 2;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.flipped .you-block {
|
|
581
|
+
grid-row: 1;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/* The words take the room left, and ask none of their own */
|
|
585
|
+
.says,
|
|
586
|
+
.sent {
|
|
587
|
+
flex: 1 1 0;
|
|
588
|
+
contain: size;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.talk.studied {
|
|
592
|
+
grid-template-rows: minmax(0, max-content) minmax(min-content, 1fr);
|
|
593
|
+
overflow: hidden;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.flipped .talk.studied {
|
|
597
|
+
grid-template-rows: minmax(min-content, 1fr) minmax(0, max-content);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.talk.studied > .ai-block > .ai-note {
|
|
601
|
+
flex: 0 1 auto;
|
|
602
|
+
min-height: 0;
|
|
603
|
+
overflow-y: auto;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/* On a short column the table's note keeps its buttons and drops the commands to type, then the box and the words go: they wait for a chat anyway.
|
|
607
|
+
In analysis the cards are taller and the AI's note needs room too */
|
|
608
|
+
@container talk (max-height: 560px) {
|
|
609
|
+
.opener-command {
|
|
610
|
+
display: none;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
@container talk (max-height: 500px) {
|
|
615
|
+
.ai-block:has(> .opener) + .you-block > :is(.sent, .compose) {
|
|
616
|
+
display: none;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
@container talk (max-height: 640px) {
|
|
621
|
+
.talk.studied .opener-command {
|
|
622
|
+
display: none;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
@container talk (max-height: 580px) {
|
|
627
|
+
.talk.studied > .ai-block:has(> .opener) + .you-block > .chat {
|
|
628
|
+
display: none;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
556
633
|
/* The game's column, which folds from its tab */
|
|
557
634
|
.side {
|
|
558
635
|
grid-area: side;
|
|
@@ -580,15 +657,22 @@
|
|
|
580
657
|
align-items: center;
|
|
581
658
|
}
|
|
582
659
|
|
|
583
|
-
/* Between games
|
|
660
|
+
/* Between games and in analysis the Torretta alone stands for the name, at every width, to leave the chip its room */
|
|
584
661
|
@media (min-width: 841px) {
|
|
585
|
-
.top:has(.verdict.idle, .verdict.over) .title {
|
|
662
|
+
.top:has(.verdict.idle, .verdict.over, .verdict.analysis) .title {
|
|
586
663
|
display: none;
|
|
587
664
|
}
|
|
588
665
|
|
|
589
|
-
.top:has(.verdict.idle, .verdict.over) .verdict {
|
|
666
|
+
.top:has(.verdict.idle, .verdict.over, .verdict.analysis) .verdict {
|
|
590
667
|
margin-right: auto;
|
|
591
668
|
}
|
|
669
|
+
|
|
670
|
+
/* Over a board of 760 px or less the sound and the theme leave their room to the chip, and stay in the settings; in a game they come back */
|
|
671
|
+
@container (max-width: 760px) {
|
|
672
|
+
.top:has(.verdict.idle, .verdict.over, .verdict.analysis) :is(.sound-button, .theme-button) {
|
|
673
|
+
display: none;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
592
676
|
}
|
|
593
677
|
|
|
594
678
|
/* Beside the board, a column's content keeps its width and its outer edge while the column folds: it slides under the board, the text never flows again */
|
|
@@ -751,10 +835,31 @@
|
|
|
751
835
|
display: none;
|
|
752
836
|
}
|
|
753
837
|
|
|
754
|
-
/* A game in analysis
|
|
755
|
-
|
|
838
|
+
/* A game in analysis: the card on top, the board, its steps under the thumb, the Torretta's note, the talk, the card below, the moves; turned round,
|
|
839
|
+
the player's card on top (Zoe) */
|
|
840
|
+
.app:has(.talk.studied) {
|
|
841
|
+
grid-template-areas: "head" "ai" "board" "steps" "note" "chat" "you" "side";
|
|
842
|
+
}
|
|
843
|
+
|
|
756
844
|
.app.flipped:has(.talk.studied) {
|
|
757
|
-
grid-template-areas: "head" "
|
|
845
|
+
grid-template-areas: "head" "you" "board" "steps" "note" "chat" "ai" "side";
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.talk.studied > .you-block {
|
|
849
|
+
display: contents;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.talk.studied > .you-block > :not(.chat) {
|
|
853
|
+
grid-area: you;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/* The talk, under the note: half the screen of it at most */
|
|
857
|
+
.talk.studied .chat {
|
|
858
|
+
grid-area: chat;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.talk.studied .sent {
|
|
862
|
+
max-height: 50vh;
|
|
758
863
|
}
|
|
759
864
|
|
|
760
865
|
.talk.studied > .ai-block {
|
|
@@ -771,9 +876,29 @@
|
|
|
771
876
|
}
|
|
772
877
|
|
|
773
878
|
/* With no chat listening, its note comes before the Torretta's (Zoe) */
|
|
774
|
-
.app:has(.talk.studied > .ai-block > .asleep)
|
|
879
|
+
.app:has(.talk.studied > .ai-block > .asleep) {
|
|
880
|
+
grid-template-areas: "head" "ai" "board" "steps" "asleep" "note" "chat" "you" "side";
|
|
881
|
+
}
|
|
882
|
+
|
|
775
883
|
.app.flipped:has(.talk.studied > .ai-block > .asleep) {
|
|
776
|
-
grid-template-areas: "head" "
|
|
884
|
+
grid-template-areas: "head" "you" "board" "steps" "asleep" "note" "chat" "ai" "side";
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/* With the helps on, their map under the steps: an area the grid lacks would put it in a column of its own, off the screen */
|
|
888
|
+
.app:has(.talk.studied):has(.board-map) {
|
|
889
|
+
grid-template-areas: "head" "ai" "board" "steps" "map" "note" "chat" "you" "side";
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.app.flipped:has(.talk.studied):has(.board-map) {
|
|
893
|
+
grid-template-areas: "head" "you" "board" "steps" "map" "note" "chat" "ai" "side";
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
.app:has(.talk.studied > .ai-block > .asleep):has(.board-map) {
|
|
897
|
+
grid-template-areas: "head" "ai" "board" "steps" "map" "asleep" "note" "chat" "you" "side";
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
.app.flipped:has(.talk.studied > .ai-block > .asleep):has(.board-map) {
|
|
901
|
+
grid-template-areas: "head" "you" "board" "steps" "map" "asleep" "note" "chat" "ai" "side";
|
|
777
902
|
}
|
|
778
903
|
|
|
779
904
|
.talk.studied > .ai-block > .asleep {
|
|
@@ -810,12 +935,18 @@
|
|
|
810
935
|
box-shadow: 0 8px 24px rgb(0 0 0 / 16%);
|
|
811
936
|
}
|
|
812
937
|
|
|
813
|
-
/* On a phone the header's first line holds the Torretta, which stands for the name, and every button down to the player's picture, a little closer
|
|
938
|
+
/* On a phone the header's first line holds the Torretta, which stands for the name, and every button down to the player's picture, a little closer; the
|
|
939
|
+
sound and the theme stay in the settings */
|
|
814
940
|
@media (max-width: 420px) {
|
|
815
941
|
.top {
|
|
816
942
|
column-gap: 4px;
|
|
817
943
|
}
|
|
818
944
|
|
|
945
|
+
.top .sound-button,
|
|
946
|
+
.top .theme-button {
|
|
947
|
+
display: none;
|
|
948
|
+
}
|
|
949
|
+
|
|
819
950
|
.top .title {
|
|
820
951
|
display: none;
|
|
821
952
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// The table's window the first time it opens (D-104): Chrome and Edge open an application window about 1000 px wide, where the page has two columns. The
|
|
2
|
+
// page asks once for 16:9, 1600×900 or what the screen has, centred; after that the browser keeps the size the player gives it (Zoe).
|
|
3
|
+
// The mark the table puts on the address of the window it opens (server/table/browser.ts).
|
|
4
|
+
const mark = "opened";
|
|
5
|
+
const sizedKey = "chesspal-window-sized";
|
|
6
|
+
const wanted = { width: 1600, height: 900 };
|
|
7
|
+
/** Sizes the window the table opened, once in this browser, and takes the mark off the address. */
|
|
8
|
+
export function fitOpenedWindow() {
|
|
9
|
+
const address = new URL(location.href);
|
|
10
|
+
if (!address.searchParams.has(mark)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
address.searchParams.delete(mark);
|
|
14
|
+
history.replaceState(history.state, "", address.pathname + address.search + address.hash);
|
|
15
|
+
if (sizedBefore()) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const place = windowPlace(screen.availWidth, screen.availHeight);
|
|
19
|
+
window.resizeTo(place.width, place.height);
|
|
20
|
+
window.moveTo(place.left, place.top);
|
|
21
|
+
noteSized();
|
|
22
|
+
}
|
|
23
|
+
/** Where the window goes on a screen with this much room: 1600×900, or less on a smaller screen, centred. */
|
|
24
|
+
export function windowPlace(roomWidth, roomHeight) {
|
|
25
|
+
const width = Math.min(wanted.width, roomWidth);
|
|
26
|
+
const height = Math.min(wanted.height, roomHeight);
|
|
27
|
+
return { width, height, left: Math.round((roomWidth - width) / 2), top: Math.round((roomHeight - height) / 2) };
|
|
28
|
+
}
|
|
29
|
+
function sizedBefore() {
|
|
30
|
+
try {
|
|
31
|
+
return localStorage.getItem(sizedKey) !== null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// A browser that keeps nothing for the page: sizing it at every opening is the lesser harm.
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function noteSized() {
|
|
39
|
+
try {
|
|
40
|
+
localStorage.setItem(sizedKey, "1");
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Nothing kept: the next opening sizes the window again.
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/* The legend of the marks on the board (D-99): a ? beside the map's button, and under it the marks the board shows now, each as the board draws it */
|
|
2
|
+
.marks-legend {
|
|
3
|
+
position: relative;
|
|
4
|
+
display: flex;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* The ? in a ring, drawn in lines as the eye shut; lit while the legend is open */
|
|
8
|
+
.legend-button svg {
|
|
9
|
+
width: 15px;
|
|
10
|
+
height: 15px;
|
|
11
|
+
fill: none;
|
|
12
|
+
stroke: currentColor;
|
|
13
|
+
stroke-width: 1.4;
|
|
14
|
+
stroke-linecap: round;
|
|
15
|
+
stroke-linejoin: round;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.legend-button[aria-expanded="true"] {
|
|
19
|
+
background: var(--accent);
|
|
20
|
+
color: var(--on-accent);
|
|
21
|
+
border-color: var(--accent);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Over the cards under it, the board in sight beside it; placed under its button by the page, since the cards clip what overflows them */
|
|
25
|
+
.legend-panel {
|
|
26
|
+
position: fixed;
|
|
27
|
+
z-index: 20;
|
|
28
|
+
width: 300px;
|
|
29
|
+
max-width: calc(100vw - 32px);
|
|
30
|
+
overflow-y: auto;
|
|
31
|
+
padding: 10px 10px 8px;
|
|
32
|
+
border: 1px solid var(--line);
|
|
33
|
+
border-radius: 10px;
|
|
34
|
+
background: var(--card);
|
|
35
|
+
box-shadow: 0 8px 28px rgba(16, 28, 44, 0.22);
|
|
36
|
+
color: var(--ink);
|
|
37
|
+
font-size: 13.5px;
|
|
38
|
+
font-weight: normal;
|
|
39
|
+
text-align: left;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.legend-title {
|
|
43
|
+
margin: 0 0 6px 6px;
|
|
44
|
+
color: var(--soft);
|
|
45
|
+
font-size: 12px;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.legend-none {
|
|
50
|
+
margin: 0 6px 4px;
|
|
51
|
+
color: var(--soft);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.legend-panel ul {
|
|
55
|
+
display: grid;
|
|
56
|
+
gap: 2px;
|
|
57
|
+
margin: 0;
|
|
58
|
+
padding: 0;
|
|
59
|
+
list-style: none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.legend-panel li {
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 10px;
|
|
66
|
+
min-height: 30px;
|
|
67
|
+
padding: 2px 6px;
|
|
68
|
+
border-radius: 6px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.legend-panel li:hover {
|
|
72
|
+
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* The marks in a column of their own, so that the names line up */
|
|
76
|
+
.legend-mark {
|
|
77
|
+
flex: none;
|
|
78
|
+
display: flex;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
width: 48px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Names start with a capital, whoever's words they are */
|
|
84
|
+
.legend-name::first-letter {
|
|
85
|
+
text-transform: uppercase;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.legend-name small {
|
|
89
|
+
margin-left: 6px;
|
|
90
|
+
color: var(--soft);
|
|
91
|
+
font-size: 12px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* A square of the board's dark colour, or two, under the marks the board draws on its squares */
|
|
95
|
+
.legend-tile {
|
|
96
|
+
position: relative;
|
|
97
|
+
display: block;
|
|
98
|
+
width: 24px;
|
|
99
|
+
height: 24px;
|
|
100
|
+
border-radius: 3px;
|
|
101
|
+
background: var(--dark-square);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.legend-tile.wide {
|
|
105
|
+
width: 48px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* A square rung as the AI rings one: the arrival square when an arrow goes with it */
|
|
109
|
+
.legend-ring {
|
|
110
|
+
position: absolute;
|
|
111
|
+
top: 0;
|
|
112
|
+
right: 0;
|
|
113
|
+
width: 24px;
|
|
114
|
+
height: 24px;
|
|
115
|
+
border-radius: 3px;
|
|
116
|
+
box-shadow: inset 0 0 0 3px var(--ring), inset 0 0 0 4.5px rgba(255, 255, 255, 0.8);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.legend-ring.green {
|
|
120
|
+
--ring: var(--drawn-green);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.legend-ring.red {
|
|
124
|
+
--ring: var(--drawn-red);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.legend-ring.yellow {
|
|
128
|
+
--ring: var(--drawn-yellow);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.legend-ring.blue {
|
|
132
|
+
--ring: var(--drawn-blue);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* The board's own marks, sized for a square of 24 pixels */
|
|
136
|
+
.legend-tile .helps-layer,
|
|
137
|
+
.legend-tile .arrows {
|
|
138
|
+
position: absolute;
|
|
139
|
+
inset: 0;
|
|
140
|
+
width: 100%;
|
|
141
|
+
height: 100%;
|
|
142
|
+
aspect-ratio: auto;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.legend-tile .help-notch {
|
|
146
|
+
width: 14px;
|
|
147
|
+
height: 14px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.legend-tile .help-pin,
|
|
151
|
+
.legend-tile .help-skewer {
|
|
152
|
+
height: 17px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.legend-mark .move-badge {
|
|
156
|
+
width: 20px;
|
|
157
|
+
height: 20px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.legend-mark .badge {
|
|
161
|
+
position: static;
|
|
162
|
+
width: 20px;
|
|
163
|
+
height: 20px;
|
|
164
|
+
font-size: 13px;
|
|
165
|
+
box-shadow: 0 0 0 1.5px #fff, 0 1px 3px rgba(0, 0, 0, 0.4);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.legend-mark .control-count {
|
|
169
|
+
position: static;
|
|
170
|
+
translate: none;
|
|
171
|
+
font-size: 12px;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* On a phone the ? is the last on the right under the board, and the legend opens below the board's row, as wide as it, never over the board */
|
|
175
|
+
.board-map .marks-legend {
|
|
176
|
+
position: static;
|
|
177
|
+
float: right;
|
|
178
|
+
margin-left: 8px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.board-map .marks-legend .hold-button {
|
|
182
|
+
float: none;
|
|
183
|
+
margin-left: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.legend-panel.under {
|
|
187
|
+
position: absolute;
|
|
188
|
+
top: calc(100% + 6px);
|
|
189
|
+
right: 0;
|
|
190
|
+
left: 0;
|
|
191
|
+
width: auto;
|
|
192
|
+
max-width: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@media (max-width: 840px) {
|
|
196
|
+
.board-map {
|
|
197
|
+
position: relative;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.helps-card .marks-legend {
|
|
201
|
+
display: none;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useLayoutEffect, useRef, useState } from "preact/hooks";
|
|
3
|
+
import { Badge, Notch, Pushpin, Skewer } from "../board/marks.js";
|
|
4
|
+
import { BadgeIcon } from "../game/badges.js";
|
|
5
|
+
/**
|
|
6
|
+
* The ? beside the map's button, and the legend it opens: a click, the ? key, Esc or a click elsewhere closes it, and puts out the squares it lit; while
|
|
7
|
+
* open it follows the board. The pointer on a line lights the squares that bear its mark, as a square in the AI's words. Under the board on a phone,
|
|
8
|
+
* `under` opens it below the board's row, never over the board.
|
|
9
|
+
*/
|
|
10
|
+
export function MarksLegend({ rows, open, onOpen, drawn, onPoint, under = false, text }) {
|
|
11
|
+
const button = useRef(null);
|
|
12
|
+
const panel = useId();
|
|
13
|
+
useClosing(open, () => onOpen(false));
|
|
14
|
+
usePutOut(open, onPoint);
|
|
15
|
+
const place = usePlace(button, open && !under);
|
|
16
|
+
const words = text.legend;
|
|
17
|
+
const shown = open && (under || place !== undefined);
|
|
18
|
+
return (_jsxs("span", { class: "marks-legend", children: [_jsx("button", { ref: button, type: "button", class: "hold-button legend-button", "aria-expanded": open, "aria-controls": shown ? panel : undefined, "aria-label": words.title, title: words.hint, onClick: () => onOpen(!open), children: _jsxs("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", children: [_jsx("circle", { cx: "8", cy: "8", r: "6.5" }), _jsx("path", { d: "M6.1 6.3a1.95 1.95 0 1 1 2.7 1.8c-.5.2-.8.6-.8 1.1v.5M8 11.4v.1" })] }) }), shown
|
|
19
|
+
? (_jsxs("section", { id: panel, class: `legend-panel${under ? " under" : ""}`, "aria-label": words.title, style: under ? undefined : place, children: [_jsx("p", { class: "legend-title", children: words.title }), rows.length === 0 ? _jsx("p", { class: "legend-none", children: words.none }) : (_jsx("ul", { children: rows.map((row) => (_jsxs("li", { onPointerEnter: () => onPoint(row.squares), onPointerLeave: (event) => event.pointerType === "mouse" && onPoint([]), children: [_jsx("span", { class: "legend-mark", children: _jsx(Mark, { row: row }) }), _jsx(Name, { row: row, drawn: drawn, text: text })] }, keyOf(row)))) }))] }))
|
|
20
|
+
: null] }));
|
|
21
|
+
}
|
|
22
|
+
/** A mark as the board draws it, on a square of the board's colour where the board draws it on one. */
|
|
23
|
+
function Mark({ row }) {
|
|
24
|
+
switch (row.kind) {
|
|
25
|
+
case "badge":
|
|
26
|
+
return _jsx(BadgeIcon, { badge: row.badge });
|
|
27
|
+
case "risk":
|
|
28
|
+
return (_jsx(Tile, { children: _jsx(Notch, { tone: row.tone }) }));
|
|
29
|
+
case "pin":
|
|
30
|
+
return (_jsx(Tile, { children: _jsx(Pushpin, { tone: row.tone }) }));
|
|
31
|
+
case "skewer":
|
|
32
|
+
return (_jsx(Tile, { children: _jsx(Skewer, { tone: row.tone }) }));
|
|
33
|
+
case "pinLine":
|
|
34
|
+
case "skewerLine":
|
|
35
|
+
return (_jsx(Tile, { wide: true, children: _jsx("svg", { class: "helps-layer", viewBox: "0 0 2 1", children: _jsxs("g", { class: row.kind === "pinLine" ? "pin" : "skewer", children: [_jsx("line", { class: "halo", x1: "0.2", y1: "0.5", x2: "1.8", y2: "0.5" }), _jsx("line", { x1: "0.2", y1: "0.5", x2: "1.8", y2: "0.5" })] }) }) }));
|
|
36
|
+
case "drawn":
|
|
37
|
+
return (_jsxs(Tile, { wide: row.arrow, children: [row.ring ? _jsx("span", { class: `legend-ring ${row.colour}` }) : null, row.arrow
|
|
38
|
+
? (_jsxs("svg", { class: "arrows drawn", viewBox: "0 0 2 1", children: [_jsx("path", { class: "edge", d: arrowShaft }), _jsx("polygon", { class: "edge", points: arrowHead }), _jsxs("g", { class: row.colour, children: [_jsx("path", { d: arrowShaft }), _jsx("polygon", { points: arrowHead })] })] }))
|
|
39
|
+
: null] }));
|
|
40
|
+
case "control":
|
|
41
|
+
return (_jsxs("span", { class: "control-count", "aria-hidden": "true", children: [_jsx("b", { class: "white", children: "2" }), _jsx("b", { class: "black", children: "1" })] }));
|
|
42
|
+
case "end":
|
|
43
|
+
return _jsx(Badge, { kind: row.sign });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function Name({ row, drawn, text }) {
|
|
47
|
+
const words = text.legend;
|
|
48
|
+
switch (row.kind) {
|
|
49
|
+
case "badge":
|
|
50
|
+
return _jsx(Named, { name: text.badges[row.badge], detail: words.badge });
|
|
51
|
+
case "risk":
|
|
52
|
+
case "pin":
|
|
53
|
+
case "skewer":
|
|
54
|
+
return _jsx(Named, { name: words.sign(row.kind, row.tone) });
|
|
55
|
+
case "pinLine":
|
|
56
|
+
return _jsx(Named, { name: words.pinLine });
|
|
57
|
+
case "skewerLine":
|
|
58
|
+
return _jsx(Named, { name: words.skewerLine });
|
|
59
|
+
case "drawn":
|
|
60
|
+
return _jsx(Named, { name: drawn.words[row.colour], detail: drawn.by });
|
|
61
|
+
case "control":
|
|
62
|
+
return _jsx(Named, { name: words.control });
|
|
63
|
+
case "end":
|
|
64
|
+
return _jsx(Named, { name: words.ends[row.sign] });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function Named({ name, detail }) {
|
|
68
|
+
return (_jsxs("span", { class: "legend-name", children: [name, detail === undefined ? null : _jsx("small", { children: detail })] }));
|
|
69
|
+
}
|
|
70
|
+
/** A square, or two side by side, of the board's dark colour, for the marks the board draws on its squares. */
|
|
71
|
+
function Tile({ wide = false, children }) {
|
|
72
|
+
return _jsx("span", { class: `legend-tile${wide ? " wide" : ""}`, "aria-hidden": "true", children: children });
|
|
73
|
+
}
|
|
74
|
+
/** Puts out the squares the legend lit when it closes, however it closes. */
|
|
75
|
+
function usePutOut(open, onPoint) {
|
|
76
|
+
const wasOpen = useRef(open);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (wasOpen.current && !open) {
|
|
79
|
+
onPoint([]);
|
|
80
|
+
}
|
|
81
|
+
wasOpen.current = open;
|
|
82
|
+
}, [open]);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Closes the legend at Esc and at a press outside it. The page has a legend in the card and one under the board for a phone, one of them hidden: a press on
|
|
86
|
+
* either is no press outside.
|
|
87
|
+
*/
|
|
88
|
+
function useClosing(open, close) {
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!open) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const key = (event) => {
|
|
94
|
+
if (event.key === "Escape") {
|
|
95
|
+
close();
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const press = (event) => {
|
|
99
|
+
if (!(event.target instanceof Element && event.target.closest(".marks-legend") !== null)) {
|
|
100
|
+
close();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
window.addEventListener("keydown", key);
|
|
104
|
+
window.addEventListener("pointerdown", press);
|
|
105
|
+
return () => {
|
|
106
|
+
window.removeEventListener("keydown", key);
|
|
107
|
+
window.removeEventListener("pointerdown", press);
|
|
108
|
+
};
|
|
109
|
+
}, [open]);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Where the legend opens: under its button, or over it when the window has more room there, its right edge on the button's and no wider than the card it
|
|
113
|
+
* sits in, so that it leaves the board in sight; over the page, since the cards clip what overflows them. It follows the button as the window changes or
|
|
114
|
+
* scrolls.
|
|
115
|
+
*/
|
|
116
|
+
function usePlace(button, open) {
|
|
117
|
+
const [place, setPlace] = useState(undefined);
|
|
118
|
+
useLayoutEffect(() => {
|
|
119
|
+
if (!open) {
|
|
120
|
+
setPlace(undefined);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const follow = () => {
|
|
124
|
+
const box = button.current?.getBoundingClientRect();
|
|
125
|
+
const card = button.current?.closest(".card")?.getBoundingClientRect();
|
|
126
|
+
if (box !== undefined) {
|
|
127
|
+
const { clientWidth: width, clientHeight: height } = document.documentElement;
|
|
128
|
+
const below = height - box.bottom - panelGap - edge;
|
|
129
|
+
const above = box.top - panelGap - edge;
|
|
130
|
+
const side = { right: `${Math.max(edge, width - box.right)}px`, width: `${Math.min(panelWidth, box.right - (card?.left ?? box.right - panelWidth))}px` };
|
|
131
|
+
setPlace(below >= roomEnough || below >= above
|
|
132
|
+
? { top: `${box.bottom + panelGap}px`, ...side, maxHeight: `${below}px` }
|
|
133
|
+
: { bottom: `${height - box.top + panelGap}px`, ...side, maxHeight: `${above}px` });
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
follow();
|
|
137
|
+
window.addEventListener("resize", follow);
|
|
138
|
+
window.addEventListener("scroll", follow, true);
|
|
139
|
+
return () => {
|
|
140
|
+
window.removeEventListener("resize", follow);
|
|
141
|
+
window.removeEventListener("scroll", follow, true);
|
|
142
|
+
};
|
|
143
|
+
}, [open]);
|
|
144
|
+
return place;
|
|
145
|
+
}
|
|
146
|
+
// How far the legend stands from its button, and from the window's edges; its width at most; the room under the button that is enough for it.
|
|
147
|
+
const panelGap = 6;
|
|
148
|
+
const edge = 16;
|
|
149
|
+
const panelWidth = 300;
|
|
150
|
+
const roomEnough = 320;
|
|
151
|
+
function keyOf(row) {
|
|
152
|
+
switch (row.kind) {
|
|
153
|
+
case "badge":
|
|
154
|
+
return row.kind;
|
|
155
|
+
case "risk":
|
|
156
|
+
case "pin":
|
|
157
|
+
case "skewer":
|
|
158
|
+
return `${row.kind} ${row.tone}`;
|
|
159
|
+
case "drawn":
|
|
160
|
+
return `${row.kind} ${row.colour}`;
|
|
161
|
+
case "end":
|
|
162
|
+
return `${row.kind} ${row.sign}`;
|
|
163
|
+
default:
|
|
164
|
+
return row.kind;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// An arrow across two squares, as the AI's: its shaft into its point, the point as long and wide as the board's.
|
|
168
|
+
const arrowShaft = "M0.3 0.5 L1.475 0.5";
|
|
169
|
+
const arrowHead = "1.4,0.71 1.7,0.5 1.4,0.29";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { pinSquares } from "../helps/view.js";
|
|
2
|
+
/** The legend's lines, in the order the eye meets the marks: the move's judgment, the helps' signs, the drawings, the map, the end. */
|
|
3
|
+
export function legendOf({ badge, helps, drawn, control = false, ends }) {
|
|
4
|
+
const rows = badge === undefined ? [] : [{ kind: "badge", badge: badge.badge, squares: [badge.square] }];
|
|
5
|
+
return [...rows, ...helpsRows(helps, control), ...drawnRows(drawn), ...(control ? [{ kind: "control", squares: [] }] : []), ...endRows(ends)];
|
|
6
|
+
}
|
|
7
|
+
// The helps' signs by kind, then by tone, the player's threats first, each lighting the pieces that bear it; the pins' and skewers' lines after them,
|
|
8
|
+
// lighting the whole line. Over the control map the board shows the corners alone.
|
|
9
|
+
function helpsRows(helps, control) {
|
|
10
|
+
if (helps === undefined) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const kinds = control ? ["risk"] : ["risk", "pin", "skewer"];
|
|
14
|
+
const signs = kinds.flatMap((kind) => tones.flatMap((tone) => {
|
|
15
|
+
const squares = helps.lines.filter((line) => line.kind === kind && line.tone === tone).flatMap(markedSquares);
|
|
16
|
+
return squares.length === 0 ? [] : [{ kind, tone, squares }];
|
|
17
|
+
}));
|
|
18
|
+
const lines = control ? [] : [
|
|
19
|
+
...(helps.pins.length === 0 ? [] : [{ kind: "pinLine", squares: helps.pins.flatMap(pinSquares) }]),
|
|
20
|
+
...(helps.skewers.length === 0 ? [] : [{ kind: "skewerLine", squares: helps.skewers.flatMap(pinSquares) }]),
|
|
21
|
+
];
|
|
22
|
+
return [...signs, ...lines];
|
|
23
|
+
}
|
|
24
|
+
// The pieces a line of the tactics marks on the board.
|
|
25
|
+
function markedSquares(line) {
|
|
26
|
+
switch (line.kind) {
|
|
27
|
+
case "risk":
|
|
28
|
+
return line.items.map((risk) => risk.piece.square);
|
|
29
|
+
case "pin":
|
|
30
|
+
case "skewer":
|
|
31
|
+
return line.items.map((pin) => pin.piece.square);
|
|
32
|
+
default:
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// One line a colour, with an arrow, a ring or both as the board has them.
|
|
37
|
+
function drawnRows(drawn) {
|
|
38
|
+
return colours.flatMap((colour) => {
|
|
39
|
+
const arrows = (drawn?.arrows ?? []).filter((arrow) => arrow.colour === colour);
|
|
40
|
+
const rings = (drawn?.squares ?? []).filter((square) => square.colour === colour);
|
|
41
|
+
const squares = [...arrows.flatMap((arrow) => [arrow.from, arrow.to]), ...rings.map((ring) => ring.square)];
|
|
42
|
+
return squares.length === 0 ? [] : [{ kind: "drawn", colour, arrow: arrows.length > 0, ring: rings.length > 0, squares }];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function endRows(ends) {
|
|
46
|
+
const signs = [...(ends ?? [])];
|
|
47
|
+
return endSigns.flatMap((sign) => {
|
|
48
|
+
const squares = signs.filter(([, each]) => each.badge === sign).map(([square]) => square);
|
|
49
|
+
return squares.length === 0 ? [] : [{ kind: "end", sign, squares }];
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const tones = ["threat", "chance", "neutral"];
|
|
53
|
+
const colours = ["green", "red", "yellow", "blue"];
|
|
54
|
+
const endSigns = ["crown", "mate", "flag", "half"];
|
package/dist/page/main.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
-
// The page's start: the settings this browser remembers, shown before the first frame, then the app
|
|
2
|
+
// The page's start: the window the table opened sized the first time, the settings this browser remembers, shown before the first frame, then the app
|
|
3
|
+
// drawn into its place.
|
|
3
4
|
import { render } from "preact";
|
|
4
5
|
import { App } from "./app/app.js";
|
|
6
|
+
import { fitOpenedWindow } from "./layout/window.js";
|
|
5
7
|
import { loadSettings, showSettings } from "./profile/settings.js";
|
|
8
|
+
fitOpenedWindow();
|
|
6
9
|
const settings = loadSettings();
|
|
7
10
|
showSettings(settings);
|
|
8
11
|
render(_jsx(App, { start: settings }), document.getElementById("app"));
|