ice-web-components 1.0.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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +487 -0
  3. package/dist/index.cjs +1 -0
  4. package/dist/index.mjs +1 -0
  5. package/dist/index.umd.js +1 -0
  6. package/dist/types/components/ICEAlert.d.ts +28 -0
  7. package/dist/types/components/ICEAnchor.d.ts +69 -0
  8. package/dist/types/components/ICEAutoComplete.d.ts +71 -0
  9. package/dist/types/components/ICEAvatar.d.ts +11 -0
  10. package/dist/types/components/ICEAvatarGroup.d.ts +40 -0
  11. package/dist/types/components/ICEBackTop.d.ts +39 -0
  12. package/dist/types/components/ICEBadge.d.ts +17 -0
  13. package/dist/types/components/ICEBreadcrumb.d.ts +82 -0
  14. package/dist/types/components/ICEButton.d.ts +25 -0
  15. package/dist/types/components/ICECalendar.d.ts +84 -0
  16. package/dist/types/components/ICECard.d.ts +22 -0
  17. package/dist/types/components/ICECarousel.d.ts +86 -0
  18. package/dist/types/components/ICECascader.d.ts +84 -0
  19. package/dist/types/components/ICECheckBox.d.ts +21 -0
  20. package/dist/types/components/ICECheckboxGroup.d.ts +75 -0
  21. package/dist/types/components/ICECollapse.d.ts +49 -0
  22. package/dist/types/components/ICEColorPicker.d.ts +52 -0
  23. package/dist/types/components/ICEComment.d.ts +36 -0
  24. package/dist/types/components/ICEDatePicker.d.ts +90 -0
  25. package/dist/types/components/ICEDescriptions.d.ts +40 -0
  26. package/dist/types/components/ICEDrawer.d.ts +59 -0
  27. package/dist/types/components/ICEDropdown.d.ts +63 -0
  28. package/dist/types/components/ICEEmpty.d.ts +28 -0
  29. package/dist/types/components/ICEFloatButton.d.ts +63 -0
  30. package/dist/types/components/ICEForm.d.ts +48 -0
  31. package/dist/types/components/ICEFormItem.d.ts +65 -0
  32. package/dist/types/components/ICEGrid.d.ts +59 -0
  33. package/dist/types/components/ICEIcon.d.ts +9 -0
  34. package/dist/types/components/ICEIconTile.d.ts +53 -0
  35. package/dist/types/components/ICEImagePreview.d.ts +91 -0
  36. package/dist/types/components/ICEImageView.d.ts +62 -0
  37. package/dist/types/components/ICEInputNumber.d.ts +54 -0
  38. package/dist/types/components/ICEKanban.d.ts +85 -0
  39. package/dist/types/components/ICELabel.d.ts +28 -0
  40. package/dist/types/components/ICEList.d.ts +59 -0
  41. package/dist/types/components/ICEMenu.d.ts +48 -0
  42. package/dist/types/components/ICEModal.d.ts +73 -0
  43. package/dist/types/components/ICEPagination.d.ts +62 -0
  44. package/dist/types/components/ICEPanel.d.ts +7 -0
  45. package/dist/types/components/ICEPasswordField.d.ts +18 -0
  46. package/dist/types/components/ICEPopconfirm.d.ts +21 -0
  47. package/dist/types/components/ICEPopover.d.ts +48 -0
  48. package/dist/types/components/ICEProgressBar.d.ts +37 -0
  49. package/dist/types/components/ICERadioButton.d.ts +21 -0
  50. package/dist/types/components/ICERadioGroup.d.ts +71 -0
  51. package/dist/types/components/ICERate.d.ts +43 -0
  52. package/dist/types/components/ICEResult.d.ts +30 -0
  53. package/dist/types/components/ICEScrollPane.d.ts +72 -0
  54. package/dist/types/components/ICESegmented.d.ts +34 -0
  55. package/dist/types/components/ICESelect.d.ts +85 -0
  56. package/dist/types/components/ICESeparator.d.ts +7 -0
  57. package/dist/types/components/ICESkeleton.d.ts +29 -0
  58. package/dist/types/components/ICESlider.d.ts +63 -0
  59. package/dist/types/components/ICESpace.d.ts +51 -0
  60. package/dist/types/components/ICESpin.d.ts +33 -0
  61. package/dist/types/components/ICESplitter.d.ts +85 -0
  62. package/dist/types/components/ICEStatCard.d.ts +14 -0
  63. package/dist/types/components/ICEStatistic.d.ts +78 -0
  64. package/dist/types/components/ICESteps.d.ts +31 -0
  65. package/dist/types/components/ICESvgIcon.d.ts +9 -0
  66. package/dist/types/components/ICESwitch.d.ts +23 -0
  67. package/dist/types/components/ICETable.d.ts +250 -0
  68. package/dist/types/components/ICETabs.d.ts +17 -0
  69. package/dist/types/components/ICETag.d.ts +15 -0
  70. package/dist/types/components/ICETextArea.d.ts +8 -0
  71. package/dist/types/components/ICETextField.d.ts +80 -0
  72. package/dist/types/components/ICETileMap.d.ts +152 -0
  73. package/dist/types/components/ICETimePicker.d.ts +81 -0
  74. package/dist/types/components/ICETimeline.d.ts +33 -0
  75. package/dist/types/components/ICETooltip.d.ts +55 -0
  76. package/dist/types/components/ICETour.d.ts +97 -0
  77. package/dist/types/components/ICETransfer.d.ts +68 -0
  78. package/dist/types/components/ICETree.d.ts +107 -0
  79. package/dist/types/components/ICETreeSelect.d.ts +64 -0
  80. package/dist/types/components/ICETypography.d.ts +67 -0
  81. package/dist/types/components/ICEUpload.d.ts +75 -0
  82. package/dist/types/components/ICEVirtualList.d.ts +100 -0
  83. package/dist/types/components/ICEWatermark.d.ts +49 -0
  84. package/dist/types/components/ICEWindow.d.ts +159 -0
  85. package/dist/types/core/ICEContainer.d.ts +10 -0
  86. package/dist/types/core/ICEFocusManager.d.ts +70 -0
  87. package/dist/types/core/ICEHoverManager.d.ts +26 -0
  88. package/dist/types/core/ICEManager.d.ts +24 -0
  89. package/dist/types/core/ICEMessageManager.d.ts +80 -0
  90. package/dist/types/core/ICEOverlayManager.d.ts +92 -0
  91. package/dist/types/core/ICEPainter.d.ts +12 -0
  92. package/dist/types/core/ICEWidget.d.ts +86 -0
  93. package/dist/types/i18n/ICEI18n.d.ts +35 -0
  94. package/dist/types/index.d.ts +111 -0
  95. package/dist/types/model/ICE2048Model.d.ts +90 -0
  96. package/dist/types/model/ICEBoundedRangeModel.d.ts +20 -0
  97. package/dist/types/model/ICEButtonModel.d.ts +16 -0
  98. package/dist/types/model/ICEFormModel.d.ts +105 -0
  99. package/dist/types/model/ICEHighScoreModel.d.ts +60 -0
  100. package/dist/types/model/ICEMinesweeperModel.d.ts +102 -0
  101. package/dist/types/model/ICESelectionModel.d.ts +31 -0
  102. package/dist/types/model/ICESnakeModel.d.ts +90 -0
  103. package/dist/types/model/ICETetrisModel.d.ts +118 -0
  104. package/dist/types/model/ICEToggleModel.d.ts +14 -0
  105. package/dist/types/theme/ICEArcadeTheme.d.ts +22 -0
  106. package/dist/types/theme/ICETheme.d.ts +120 -0
  107. package/dist/types/util/ICEAccessibilityMirror.d.ts +55 -0
  108. package/dist/types/util/ICEAnimation.d.ts +71 -0
  109. package/dist/types/util/ICEDragReorder.d.ts +102 -0
  110. package/dist/types/util/ICENativeInput.d.ts +65 -0
  111. package/dist/types/util/ICEOverlayPosition.d.ts +52 -0
  112. package/dist/types/util/ICEStyle.d.ts +60 -0
  113. package/dist/types/util/ICEWorldBox.d.ts +14 -0
  114. package/package.json +56 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 排行榜的纯逻辑模型(不碰 canvas,也不直接依赖 localStorage)。
3
+ *
4
+ * - `add(score)` 插入后按**分数降序**排,并列时保持先来后到,超过 `maxEntries` 截断;
5
+ * - `getBest()` 给最高分(空榜 0);`isInTop(score)` 判断「这一局值不值得炫耀」;
6
+ * - 存储通过构造函数注入(默认 `globalThis.localStorage`):key 按卡带隔离;
7
+ * - 存档损坏(非法 JSON / 结构不对 / 里层字段不合法)一律降级成空榜,绝不抛;
8
+ * - 写盘失败(隐私模式、配额满)不影响内存里的成绩。
9
+ */
10
+ export interface ICEHighScoreEntry {
11
+ score: number;
12
+ /** 可选标签(用户名 / 备注) */
13
+ label?: string;
14
+ /** 可选时间戳 */
15
+ at?: number;
16
+ }
17
+ /** 只需要这两个方法,注入内存实现即可在 node 里测。 */
18
+ export interface ICEHighScoreStorage {
19
+ getItem(key: string): string | null;
20
+ setItem(key: string, value: string): void;
21
+ removeItem?(key: string): void;
22
+ }
23
+ export interface ICEHighScoreOptions {
24
+ /** 榜单标识(一般用卡带 key:tetris / snake…) */
25
+ key: string;
26
+ /** 最多保留几条,默认 5 */
27
+ maxEntries?: number;
28
+ /** 存储实现;传 null 表示只放内存;不传则用 globalThis.localStorage(没有就退化成内存) */
29
+ storage?: ICEHighScoreStorage | null;
30
+ /** 存储键前缀,默认 `ice-arcade-scores-` */
31
+ prefix?: string;
32
+ }
33
+ export declare class ICEHighScoreModel {
34
+ private key;
35
+ private maxEntries;
36
+ private storage;
37
+ private prefix;
38
+ private entries;
39
+ constructor(options: ICEHighScoreOptions);
40
+ getKey(): string;
41
+ getStorageKey(): string;
42
+ getMaxEntries(): number;
43
+ /** 榜单拷贝(降序)。 */
44
+ getScores(): ICEHighScoreEntry[];
45
+ /** 最高分(空榜为 0)。 */
46
+ getBest(): number;
47
+ /** 这个分数能不能进榜(榜没满一律能进;并列最小分也算能进)。 */
48
+ isInTop(score: number): boolean;
49
+ /** 记一笔成绩,返回更新后的榜单。非法分数直接忽略。 */
50
+ add(score: number, options?: {
51
+ label?: string;
52
+ at?: number;
53
+ }): ICEHighScoreEntry[];
54
+ clear(): void;
55
+ /** 从存储重新读一遍(多标签页/多窗口场景)。 */
56
+ reload(): ICEHighScoreEntry[];
57
+ private __defaultStorage;
58
+ private __load;
59
+ private __save;
60
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * 扫雷的纯逻辑模型(不碰 canvas)。
3
+ *
4
+ * 规则按 Windows XP 扫雷:
5
+ * - **首次点击安全**:第一次掀开格子时才布雷,且排除该格及其 8 邻域(空间够时)——
6
+ * 所以第一下永远不会炸,也常常一下展开一片;
7
+ * - **揭示**:相邻雷数为 0 时洪水填充展开整片空白;
8
+ * - **插旗循环**:无 → 🚩 → ❓ → 无(`questionMarks: false` 时只有旗);
9
+ * - **chord**(双击数字):周围旗数等于数字时,掀开其余未插旗的邻格(可能炸);
10
+ * - **胜负**:掀开所有非雷格 = 胜;掀开雷 = 负(把所有雷亮出来);
11
+ * - **计时**:由调用方 `tick()`(每秒一次)驱动;**只有 playing 才累加**(XP 的计时从第一次点击开始),
12
+ * 结束或还没开始都不动 —— 测试里可直接手动推进。
13
+ *
14
+ * 布雷用注入的 `random`(默认 `Math.random`),测试传固定序列即可复现棋局。
15
+ */
16
+ export interface ICEMinesweeperDifficulty {
17
+ key: string;
18
+ label: string;
19
+ rows: number;
20
+ cols: number;
21
+ mines: number;
22
+ }
23
+ /** XP 扫雷的三档标准难度。 */
24
+ export declare const ICE_MINESWEEPER_DIFFICULTIES: ICEMinesweeperDifficulty[];
25
+ export declare type ICEMinesweeperState = 'ready' | 'playing' | 'won' | 'lost';
26
+ export interface ICEMinesweeperCell {
27
+ row: number;
28
+ col: number;
29
+ mine: boolean;
30
+ revealed: boolean;
31
+ flagged: boolean;
32
+ question: boolean;
33
+ /** 周围 8 格的雷数 */
34
+ adjacent: number;
35
+ }
36
+ export interface ICEMinesweeperOptions {
37
+ rows?: number;
38
+ cols?: number;
39
+ mines?: number;
40
+ /** 随机源(0..1),默认 Math.random —— 测试可注入固定序列 */
41
+ random?: () => number;
42
+ /** 首次点击安全(默认 true) */
43
+ firstClickSafe?: boolean;
44
+ /** 插旗循环里是否带问号(默认 true) */
45
+ questionMarks?: boolean;
46
+ }
47
+ export declare type ICEMinesweeperListener = (model: ICEMinesweeperModel) => void;
48
+ export declare class ICEMinesweeperModel {
49
+ private rows;
50
+ private cols;
51
+ private mineCount;
52
+ private random;
53
+ private firstClickSafe;
54
+ private questionMarks;
55
+ private grid;
56
+ private state;
57
+ private minesPlaced;
58
+ private elapsed;
59
+ private listeners;
60
+ constructor(options?: ICEMinesweeperOptions);
61
+ getRows(): number;
62
+ getCols(): number;
63
+ getMineCount(): number;
64
+ getState(): ICEMinesweeperState;
65
+ isWon(): boolean;
66
+ isLost(): boolean;
67
+ isOver(): boolean;
68
+ getElapsed(): number;
69
+ getFlags(): number;
70
+ /** 剩余雷数 = 总雷数 - 已插旗数(可能为负,和 XP 一样显示负数)。 */
71
+ getMinesLeft(): number;
72
+ getRevealedCount(): number;
73
+ getCells(): ICEMinesweeperCell[];
74
+ getCell(row: number, col: number): ICEMinesweeperCell | null;
75
+ /** 雷是否已经布好(首点安全时,第一次 reveal 之后才会布)。 */
76
+ areMinesPlaced(): boolean;
77
+ /** 相邻 8 格的坐标。 */
78
+ neighbors(row: number, col: number): Array<[number, number]>;
79
+ /** 掀开格子(插旗的会被忽略)。首次掀开时布雷(首点安全)。 */
80
+ reveal(row: number, col: number): this;
81
+ /** 右键:无 → 旗 → 问号 → 无。 */
82
+ toggleFlag(row: number, col: number): this;
83
+ /** 双击已掀开的数字:周围旗数够时掀开其余邻格。 */
84
+ chord(row: number, col: number): this;
85
+ /**
86
+ * 计时 +1 秒(调用方按秒驱动)。只有 `playing` 才累加:
87
+ * 还没点第一下(ready)不计时(和 XP 一致),胜负已分之后也不计。
88
+ */
89
+ tick(): this;
90
+ /** 重开(可顺带换难度)。 */
91
+ reset(options?: ICEMinesweeperOptions): this;
92
+ addChangeListener(listener: ICEMinesweeperListener): () => void;
93
+ private __inBounds;
94
+ private __at;
95
+ private __resetGrid;
96
+ /** 布雷:`safe` 是首点坐标(连同 8 邻域一起排除)。 */
97
+ private __placeMines;
98
+ /** 掀开一格:是雷就结束,是 0 就递归展开。 */
99
+ private __revealCell;
100
+ private __checkFinish;
101
+ private __notify;
102
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 选择模型:列表 / 树 / 穿梭框共用的选择状态。
3
+ *
4
+ * 与其它模型(ICEButtonModel / ICEToggleModel / ICEBoundedRangeModel)同风格:
5
+ * 纯状态 + 监听器,UI 组件只负责把状态画出来。
6
+ */
7
+ export declare type ICESelectionMode = 'single' | 'multiple';
8
+ export interface ICESelectionModelOptions {
9
+ mode?: ICESelectionMode;
10
+ selected?: string[];
11
+ }
12
+ export declare type ICESelectionListener = (model: ICESelectionModel) => void;
13
+ export declare class ICESelectionModel {
14
+ private mode;
15
+ private selected;
16
+ private listeners;
17
+ constructor(options?: ICESelectionModelOptions);
18
+ getMode(): ICESelectionMode;
19
+ setMode(mode: ICESelectionMode): this;
20
+ getSelectedKeys(): string[];
21
+ isSelected(key: string): boolean;
22
+ /** 选中(single 替换;multiple 追加,已选中则不变)。 */
23
+ select(key: string): this;
24
+ /** 切换选中状态(点一下选中、再点取消)。 */
25
+ toggle(key: string): this;
26
+ setSelected(keys: string[]): this;
27
+ clear(): this;
28
+ addChangeListener(listener: ICESelectionListener): () => void;
29
+ private __normalize;
30
+ private __notify;
31
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * 贪吃蛇的纯逻辑模型(不碰 canvas)。
3
+ *
4
+ * 规则按经典街机 / Nokia 贪吃蛇:
5
+ * - **前进**:`tick()` 让头往前走一格、尾巴收一格(长度不变);
6
+ * - **吃食物**:头落到食物上 → 长度 +1、加分、食物重新生成(绝不落在蛇身上);
7
+ * - **转向**:可以排队两个转向依次生效;**不能 180° 掉头**(向右时按左无效);
8
+ * - **撞墙即死**;`wrap: true` 时穿墙(从左边出去从右边回来);
9
+ * - **撞自己即死**,但「正在移开的尾巴」不算 —— 那格这一步就空出来了;
10
+ * - **越吃越快**:每 5 个升一级,`getTickInterval()` 按等级递减并有下限(70ms);
11
+ * - 暂停时 `tick()` 与转向都无效;食物位置由注入的 `random` 决定,测试可复现。
12
+ *
13
+ * 蛇身是 `[row, col]` 数组,**头在最前**(`body[0]`),和 `ICETetrisModel` 的坐标约定一致。
14
+ */
15
+ /** 四个方向。 */
16
+ export declare type ICESnakeDirection = 'up' | 'right' | 'down' | 'left';
17
+ /** 按上、右、下、左顺序排列的方向表(UI 画方向盘可以直接用)。 */
18
+ export declare const ICE_SNAKE_DIRECTIONS: ICESnakeDirection[];
19
+ /** 棋盘上的一格。 */
20
+ export declare type ICESnakePoint = [number, number];
21
+ export interface ICESnakeOptions {
22
+ rows?: number;
23
+ cols?: number;
24
+ /** 随机源(0..1),默认 `Math.random` —— 测试注入固定序列即可复现食物位置 */
25
+ random?: () => number;
26
+ /** 撞墙时穿墙而不是死(默认 false) */
27
+ wrap?: boolean;
28
+ /** 初始长度(默认 3,最小 2) */
29
+ initialLength?: number;
30
+ }
31
+ export declare type ICESnakeListener = (model: ICESnakeModel) => void;
32
+ export declare class ICESnakeModel {
33
+ private rows;
34
+ private cols;
35
+ private random;
36
+ private wrap;
37
+ private initialLength;
38
+ private body;
39
+ private food;
40
+ private direction;
41
+ /** 待生效的转向(最多两个,按顺序 consume) */
42
+ private queue;
43
+ private score;
44
+ private eaten;
45
+ private gameOver;
46
+ private paused;
47
+ private listeners;
48
+ constructor(options?: ICESnakeOptions);
49
+ getRows(): number;
50
+ getCols(): number;
51
+ /** 蛇身(头在最前)。 */
52
+ getBody(): ICESnakePoint[];
53
+ /** 头的坐标。 */
54
+ getHead(): ICESnakePoint;
55
+ getLength(): number;
56
+ getFood(): ICESnakePoint | null;
57
+ getDirection(): ICESnakeDirection;
58
+ /** 排队中的转向(UI 可以拿它显示「已接收输入」)。 */
59
+ getPendingDirections(): ICESnakeDirection[];
60
+ getScore(): number;
61
+ /** 已经吃掉的food个数。 */
62
+ getEaten(): number;
63
+ /** 每 5 个食物升一级,从 1 开始。 */
64
+ getLevel(): number;
65
+ /** 当前等级下的步进间隔(毫秒),等级越高越短,下限 70ms。 */
66
+ getTickInterval(): number;
67
+ isGameOver(): boolean;
68
+ isPaused(): boolean;
69
+ addChangeListener(listener: ICESnakeListener): () => void;
70
+ /**
71
+ * 掉头请求会被忽略并返回 `false`;重复的「当前方向」算接受(`true`)但不占队列;
72
+ * 队列满(已有两个待生效转向)也会被忽略。
73
+ */
74
+ setDirection(direction: ICESnakeDirection): boolean;
75
+ /** 前进一步;撞墙 / 撞自己则进入 game over 并返回 false。 */
76
+ tick(): boolean;
77
+ pause(): void;
78
+ resume(): void;
79
+ /** 重置:可只覆盖部分选项(行列、随机源、穿墙、初始长度)。 */
80
+ reset(options?: ICESnakeOptions): void;
81
+ /** 直接摆一条蛇(造题、读档、UI demo 都用得上)。 */
82
+ setBodyForTest(cells: ICESnakePoint[], direction?: ICESnakeDirection): void;
83
+ /** 直接摆一个食物。 */
84
+ setFoodForTest(row: number, col: number): void;
85
+ private __resetBoard;
86
+ private __die;
87
+ /** 在所有空格里随机挑一个放食物(挑不到说明棋盘满了)。 */
88
+ private __spawnFood;
89
+ private notify;
90
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * 俄罗斯方块的纯逻辑模型(不碰 canvas)。
3
+ *
4
+ * 规则按现代标准俄罗斯方块(SRS-lite):
5
+ * - **7-bag 随机**:每 7 个方块恰好包含 7 种各一次(公平性),可用注入的 `random` 复现同一局;
6
+ * - 移动/旋转受墙与已落方块阻挡;旋转带简易踢墙(0 / ±1 / ±2 依次尝试);
7
+ * - 重力由 `tick()` 驱动(下落一行),间隔随等级变快;
8
+ * - 消行计分:1/2/3/4 行 = 100/300/500/800 × 等级;每 10 行升一级;
9
+ * - 软降 +1 分/格、硬降 +2 分/格;
10
+ * - 生成位置被占 → game over;暂停时所有操作无效。
11
+ *
12
+ * 棋盘格存的直接是方块类型(`'I' | 'O' | ... | null`),UI 层拿它当调色板的 key 用。
13
+ */
14
+ /** 七种方块。 */
15
+ export declare type ICETetrominoType = 'I' | 'O' | 'T' | 'S' | 'Z' | 'J' | 'L';
16
+ /** 棋盘格子:落了方块就是它的类型,否则 null。 */
17
+ export declare type ICETetrisCell = ICETetrominoType | null;
18
+ /** 方块内的一格,用 `[row, col]` 相对(或绝对)坐标表示。 */
19
+ export declare type ICETetrisOffset = [number, number];
20
+ /** 方块类型 → 4 个旋转状态,每个状态是 4 个 `[row, col]` 偏移。 */
21
+ export declare type ICETetrominoShape = ICETetrisOffset[];
22
+ /**
23
+ * 七种方块 × 4 个旋转状态。
24
+ * 旋转在固定的方阵内进行(不做归一化),因此 O 转完还是 O、I 会躺平/立起来。
25
+ */
26
+ export declare const ICE_TETROMINOES: Record<ICETetrominoType, ICETetrominoShape[]>;
27
+ /** 当前正在下落的方块。 */
28
+ export interface ICETetrisPiece {
29
+ type: ICETetrominoType;
30
+ /** 旋转状态下标 0..3 */
31
+ rotation: number;
32
+ /** 方块左上角在棋盘上的行 */
33
+ row: number;
34
+ /** 方块左上角在棋盘上的列 */
35
+ col: number;
36
+ /** 四个格子的**绝对**棋盘坐标 */
37
+ cells: ICETetrisOffset[];
38
+ }
39
+ export interface ICETetrisOptions {
40
+ rows?: number;
41
+ cols?: number;
42
+ /** 随机源(0..1),默认 `Math.random` —— 测试注入固定序列即可复现 */
43
+ random?: () => number;
44
+ }
45
+ export declare type ICETetrisListener = (model: ICETetrisModel) => void;
46
+ /** 消 1/2/3/4 行的基础分(再乘等级),经典数值。 */
47
+ export declare const ICE_TETRIS_LINE_SCORES: number[];
48
+ export declare class ICETetrisModel {
49
+ private rows;
50
+ private cols;
51
+ private random;
52
+ private board;
53
+ private queue;
54
+ private current;
55
+ private score;
56
+ private lines;
57
+ private gameOver;
58
+ private paused;
59
+ private lastCleared;
60
+ private listeners;
61
+ constructor(options?: ICETetrisOptions);
62
+ getRows(): number;
63
+ getCols(): number;
64
+ getBoard(): ICETetrisCell[][];
65
+ getCurrent(): ICETetrisPiece;
66
+ /** 预览队列(下一个方块在 `[0]`)。 */
67
+ getNextQueue(): ICETetrominoType[];
68
+ isGameOver(): boolean;
69
+ isPaused(): boolean;
70
+ getScore(): number;
71
+ getLines(): number;
72
+ /** 上一次锁定消掉了几行(0 表示没消;UI 用它做特效/连击提示)。 */
73
+ getLastClearedLines(): number;
74
+ /** 每 10 行升一级,从 1 开始。 */
75
+ getLevel(): number;
76
+ /** 当前等级下的自动下落间隔(毫秒),等级越高越短。 */
77
+ getDropInterval(): number;
78
+ /** 当前方块笔直落下去会停在哪(画幽灵投影用)。 */
79
+ getGhost(): ICETetrisOffset[];
80
+ addChangeListener(listener: ICETetrisListener): () => void;
81
+ moveLeft(): boolean;
82
+ moveRight(): boolean;
83
+ /** 顺时针旋转(带上踢墙)。 */
84
+ rotateCW(): boolean;
85
+ /** 逆时针旋转(带上踢墙)。 */
86
+ rotateCCW(): boolean;
87
+ /** 重力:下落一行;到底就锁定。 */
88
+ tick(): boolean;
89
+ /** 软降:下落一行并 +1 分;到底就锁定。 */
90
+ softDrop(): boolean;
91
+ /** 硬降:一步落到底、锁定,按落下的格数 +2 分/格。 */
92
+ hardDrop(): boolean;
93
+ pause(): void;
94
+ resume(): void;
95
+ /** 重置:可只覆盖部分选项(行列、随机源),其余沿用构造时的配置。 */
96
+ reset(options?: ICETetrisOptions): void;
97
+ /** 直接摆一格(造题、读档、UI demo 都用得上)。 */
98
+ setCellForTest(row: number, col: number, type: ICETetrominoType | null): void;
99
+ /** 直接改累计消行数(测试升级曲线用)。 */
100
+ setLinesForTest(lines: number): void;
101
+ private __resetBoard;
102
+ /** 暂停 / 结束 / 没有当前方块时,一切输入无效。 */
103
+ private blocked;
104
+ private tryMove;
105
+ /** 移动但不通知(硬降内部用,避免一次操作刷屏)。 */
106
+ private tryMoveQuiet;
107
+ /** 旋转 + 踢墙:依次尝试 (0,0) → 左右各 1 → 左右各 2 → 上抬一格。 */
108
+ private tryRotate;
109
+ private stepDown;
110
+ /** 把当前方块写进棋盘 → 消行 → 出下一个;顶到天花板就 game over。 */
111
+ private lock;
112
+ private clearLines;
113
+ private spawn;
114
+ /** 队列见底就补一袋(保证预览里永远有下一袋可看)。 */
115
+ private refillQueue;
116
+ private collides;
117
+ private notify;
118
+ }
@@ -0,0 +1,14 @@
1
+ export declare type ICEToggleModelListener = (model: ICEToggleModel) => void;
2
+ export declare class ICEToggleModel {
3
+ private selected;
4
+ private listeners;
5
+ constructor(options?: {
6
+ selected?: boolean;
7
+ });
8
+ isSelected(): boolean;
9
+ setSelected(selected: boolean): this;
10
+ toggle(): this;
11
+ addChangeListener(listener: ICEToggleModelListener): this;
12
+ removeChangeListener(listener: ICEToggleModelListener): this;
13
+ private __notify;
14
+ }
@@ -0,0 +1,22 @@
1
+ import { ICEThemeTokens } from './ICETheme';
2
+ import { ICETileMapPalette } from '../components/ICETileMap';
3
+ /**
4
+ * 街机主题:给「掌机 / 游戏」这类深色场景用的一套 token。
5
+ *
6
+ * 为什么要有它:arcade 示例一开始把方块和蛇的颜色写死在页面里,结果是**面板文字跟着主题走、
7
+ * 游戏美术不跟** —— 一个页面两套配色来源。现在游戏配色也收进 token:
8
+ *
9
+ * ```ts
10
+ * iceUIManager.registerTheme('arcade', ICE_ARCADE_THEME).setTheme('arcade');
11
+ * const board = new ICETileMap({ rows, cols, palette: ICE_ARCADE_PALETTE });
12
+ * ```
13
+ *
14
+ * 它是**完整主题**(不是补丁):token 组与内置 dark 完全一致,只换颜色,所以任何组件切过去
15
+ * 都不会缺 token。
16
+ */
17
+ export declare const ICE_ARCADE_THEME: ICEThemeTokens;
18
+ /**
19
+ * 游戏调色板:方块 7 种 + 蛇头 / 蛇身 / 食物。
20
+ * 颜色取 Bootstrap 语义色,描边统一是填充色压暗 35%(和页面里 `shade(color, -0.35)` 一致)。
21
+ */
22
+ export declare const ICE_ARCADE_PALETTE: ICETileMapPalette;
@@ -0,0 +1,120 @@
1
+ export declare type ICEColor = string;
2
+ /** 阴影:直接给引擎认的四个数值字段(比自己再造一套 shadow 名字更可控)。 */
3
+ export declare type ICEShadowTokens = {
4
+ shadowColor: string;
5
+ shadowBlur: number;
6
+ shadowOffsetX: number;
7
+ shadowOffsetY: number;
8
+ };
9
+ export declare type ICEThemeTokens = {
10
+ colors: {
11
+ primary: ICEColor;
12
+ primaryHover: ICEColor;
13
+ primaryActive: ICEColor;
14
+ primaryBg: ICEColor;
15
+ primaryBorder: ICEColor;
16
+ primaryText: ICEColor;
17
+ background: ICEColor;
18
+ surface: ICEColor;
19
+ elevated: ICEColor;
20
+ border: ICEColor;
21
+ borderSecondary: ICEColor;
22
+ text: ICEColor;
23
+ textSecondary: ICEColor;
24
+ textTertiary: ICEColor;
25
+ textDisabled: ICEColor;
26
+ muted: ICEColor;
27
+ disabled: ICEColor;
28
+ disabledText: ICEColor;
29
+ success: ICEColor;
30
+ successBg: ICEColor;
31
+ successBorder: ICEColor;
32
+ warning: ICEColor;
33
+ warningBg: ICEColor;
34
+ warningBorder: ICEColor;
35
+ error: ICEColor;
36
+ errorBg: ICEColor;
37
+ errorBorder: ICEColor;
38
+ info: ICEColor;
39
+ infoBg: ICEColor;
40
+ infoBorder: ICEColor;
41
+ /**
42
+ * 强调文字色(Bootstrap 的 `*-text-emphasis`):用在 **subtle 底**上的文字。
43
+ * 直接把 `warning: #ffc107` 这样的亮色当文字压不住(对比度不足),
44
+ * 所以浅底场景(Alert/Tag/Badge)统一取这一组深色。
45
+ */
46
+ primaryTextEmphasis: ICEColor;
47
+ successTextEmphasis: ICEColor;
48
+ warningTextEmphasis: ICEColor;
49
+ errorTextEmphasis: ICEColor;
50
+ infoTextEmphasis: ICEColor;
51
+ /** 聚焦态描边色(Bootstrap 的 `$input-btn-focus-color` / 聚焦输入框边框 `#86b7fe`)。 */
52
+ focusRing: ICEColor;
53
+ };
54
+ spacing: {
55
+ xxs: number;
56
+ xs: number;
57
+ sm: number;
58
+ md: number;
59
+ lg: number;
60
+ xl: number;
61
+ xxl: number;
62
+ };
63
+ radius: {
64
+ xs: number;
65
+ sm: number;
66
+ md: number;
67
+ lg: number;
68
+ xl: number;
69
+ pill: number;
70
+ };
71
+ font: {
72
+ family: string;
73
+ size: number;
74
+ sizeSmall: number;
75
+ sizeLarge: number;
76
+ weightNormal: string;
77
+ weightMedium: string;
78
+ weightSemibold: string;
79
+ weightBold: string;
80
+ };
81
+ control: {
82
+ heightSmall: number;
83
+ height: number;
84
+ heightLarge: number;
85
+ paddingXXS: number;
86
+ paddingXS: number;
87
+ paddingSmall: number;
88
+ padding: number;
89
+ paddingLarge: number;
90
+ lineWidth: number;
91
+ lineWidthFocused: number;
92
+ switchWidth: number;
93
+ switchHeight: number;
94
+ switchHandle: number;
95
+ checkboxSize: number;
96
+ radioSize: number;
97
+ progressHeight: number;
98
+ sliderTrackHeight: number;
99
+ sliderHandle: number;
100
+ };
101
+ shadows: {
102
+ sm: ICEShadowTokens;
103
+ md: ICEShadowTokens;
104
+ lg: ICEShadowTokens;
105
+ };
106
+ };
107
+ export declare const ICE_LIGHT_THEME: ICEThemeTokens;
108
+ export declare const ICE_DARK_THEME: ICEThemeTokens;
109
+ /**
110
+ * Windows XP 经典主题(Luna 蓝 + 米灰控件)。
111
+ *
112
+ * 用途:桌面 / 怀旧风格的应用。用 `iceUIManager.registerTheme('xp', ICE_XP_THEME).setTheme('xp')`
113
+ * 切换(主题在组件构造时读取,先切主题再建组件)。
114
+ *
115
+ * 取色要点:
116
+ * - 主色取 XP 选择蓝 `#316ac5`,控件面 `#ece9d8`(经典米灰),输入框白底 + `#7f9db9` 边框;
117
+ * - 圆角压到 2~3px、控件更矮更紧凑(XP 的按钮比 Bootstrap 小一圈);
118
+ * - 阴影几乎不用(XP 是描边风格,不是投影风格)。
119
+ */
120
+ export declare const ICE_XP_THEME: ICEThemeTokens;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * 无障碍(a11y)DOM 镜像层。
3
+ *
4
+ * canvas 内容对屏幕阅读器完全不可见(`<canvas>` 只是位图),所以必须有一层隐藏 DOM 把
5
+ * 语义暴露出去。引擎负责产出快照(见引擎 `src/a11y/accessibility.ts`:
6
+ * id / 角色建议 / `state.ariaLabel` / 屏幕盒 / tab 顺序),**这里负责把快照变成 DOM**:
7
+ *
8
+ * ```ts
9
+ * const mirror = mountICEAccessibilityMirror(ice);
10
+ * // 场景变化后(换页、开窗、列表刷新……)调一次
11
+ * mirror.refresh();
12
+ * ```
13
+ *
14
+ * 元素是「透明但存在」的(`opacity: 0`,不是 `display:none` —— 后者会把语义一起藏掉),
15
+ * 位置与画布组件对齐,键盘 Tab 能进去、屏幕阅读器能读到、点它等于点画布组件。
16
+ * 容器默认 `pointer-events: none`,只有可交互元素打开指针事件,避免挡住画布本身。
17
+ */
18
+ export interface ICEAccessibleNodeLike {
19
+ id: string;
20
+ role: string;
21
+ label: string;
22
+ box: {
23
+ x: number;
24
+ y: number;
25
+ width: number;
26
+ height: number;
27
+ };
28
+ visible: boolean;
29
+ interactive: boolean;
30
+ focusable: boolean;
31
+ tabIndex: number;
32
+ selected: boolean;
33
+ level: number;
34
+ parentId: string | null;
35
+ }
36
+ export interface ICEA11yMirrorOptions {
37
+ /** 注入 document(测试用假对象);不传取全局 document */
38
+ doc?: any;
39
+ /** 挂载容器(默认挂到 document.body) */
40
+ container?: any;
41
+ /** 容器 id,默认 `ice-a11y-mirror` */
42
+ id?: string;
43
+ /** 是否包含不可见组件(默认 false,跟引擎默认一致) */
44
+ includeHidden?: boolean;
45
+ /** 自定义角色映射:引擎给的是「建议」,产品语义可以覆盖 */
46
+ roleMap?: (node: ICEAccessibleNodeLike, component: any) => string | null;
47
+ }
48
+ export interface ICEA11yMirrorHandle {
49
+ isMounted(): boolean;
50
+ getContainer(): any;
51
+ getElements(): any[];
52
+ refresh(): void;
53
+ unmount(): void;
54
+ }
55
+ export declare function mountICEAccessibilityMirror(ice: any, options?: ICEA11yMirrorOptions): ICEA11yMirrorHandle;