ice-web-components 1.1.0 → 1.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 +78 -6
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/components/ICELabel.d.ts +8 -0
- package/dist/types/components/ICETileMap.d.ts +12 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/model/ICEBiosModel.d.ts +124 -0
- package/dist/types/model/ICEHistoryModel.d.ts +45 -0
- package/dist/types/model/ICEPixelModel.d.ts +89 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -27,10 +27,11 @@ rings and shadows) is drawn by the engine.
|
|
|
27
27
|
- **Bootstrap 5 token theme** (plus a dark theme) — swap with one call.
|
|
28
28
|
- **No name collisions with the engine** — the package’s runtime exports are
|
|
29
29
|
disjoint from `ice-render`’s (there is a regression test for it).
|
|
30
|
-
- **Actually tested** —
|
|
31
|
-
positioning, keyboard navigation, sort/hover/focus edge cases,
|
|
32
|
-
Tetris, Snake, 2048 and CHIP-8 rule/machine models
|
|
33
|
-
(`qa:admin`, `qa:gallery`,
|
|
30
|
+
- **Actually tested** — 769 unit tests (103 suites: form validation, overlay
|
|
31
|
+
positioning, keyboard navigation, sort/hover/focus edge cases, the Minesweeper,
|
|
32
|
+
Tetris, Snake, 2048 and CHIP-8 rule/machine models, the pixel canvas and the undo
|
|
33
|
+
stack, and the console BIOS) plus six browser QA suites (`qa:admin`, `qa:gallery`,
|
|
34
|
+
`qa:workbench`, `qa:xp`, `qa:arcade`, `qa:pixel` — 246 assertions) that drive the demo pages with
|
|
34
35
|
real mouse and keyboard events and fail on any console error.
|
|
35
36
|
|
|
36
37
|
## Quick start
|
|
@@ -219,6 +220,26 @@ the buttons and the sound switch are all ICE components, and there is not a sing
|
|
|
219
220
|
bitmap asset in the picture. Four cartridges are plugged in, and the cartridge row at
|
|
220
221
|
the top switches between them (a fifth slot, Chinese chess, is disabled for now).
|
|
221
222
|
|
|
223
|
+
Before any cartridge runs, the console boots through its own **BIOS**: a power-on
|
|
224
|
+
self-test (CPU / RAM / VRAM / SOUND / CART, each line going grey → amber → green with a
|
|
225
|
+
beep) followed by a classic boot menu, exactly like the real thing.
|
|
226
|
+
|
|
227
|
+
| POST (power-on self-test) | BIOS boot menu |
|
|
228
|
+
|---|---|
|
|
229
|
+
|  |  |
|
|
230
|
+
|
|
231
|
+
`ICEBiosModel` is the state machine behind it (pure logic, 17 unit tests): the self-test
|
|
232
|
+
is a **timed sequence** the page advances with `tick(dt)` — each step owns its duration and
|
|
233
|
+
reports `pending` / `running` / `ok`; the menu is a cursor + confirm console UI with a
|
|
234
|
+
**wrapping** cursor; `confirm()` returns an *action* (`boot` / `settings` / `menu`) instead
|
|
235
|
+
of executing it, so the whole flow is testable in node. Settings (quick boot + default
|
|
236
|
+
cartridge) persist through an injected storage that degrades gracefully on corrupt JSON
|
|
237
|
+
or a full quota.
|
|
238
|
+
|
|
239
|
+
F2 (or the BIOS button) returns to the menu at any time — on a game page that *is* the
|
|
240
|
+
reset button. Any key during POST skips the rest of the self-test, and with quick boot on
|
|
241
|
+
(the factory default) the console goes straight back to the last cartridge after POST.
|
|
242
|
+
|
|
222
243
|
| | |
|
|
223
244
|
|---|---|
|
|
224
245
|
|  |  |
|
|
@@ -307,6 +328,52 @@ Under the hood this page is where the engine work happens:
|
|
|
307
328
|
> A game page keeps the keyboard for itself; mouse hover still goes through
|
|
308
329
|
> `ICEHoverManager`.
|
|
309
330
|
|
|
331
|
+
### `pixel-editor.html` — ICE Pixel Studio (a real pixel editor)
|
|
332
|
+
|
|
333
|
+
The other direction: instead of “draw a business screen”, this page is a **tool**.
|
|
334
|
+
The canvas, tool palette, colour swatches and status bar are all components — only the
|
|
335
|
+
pixels themselves are self-drawn, as a single `ICETileMap` node. Pencil, eraser, line,
|
|
336
|
+
rectangle and flood fill, undo/redo, and PNG + SVG export.
|
|
337
|
+
|
|
338
|
+

|
|
339
|
+
|
|
340
|
+
Two pure models carry it (no canvas involved):
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
import { ICEPixelModel, ICEHistoryModel } from 'ice-web-components';
|
|
344
|
+
|
|
345
|
+
const model = new ICEPixelModel({ rows: 32, cols: 32, palette: PALETTE, background: 0 });
|
|
346
|
+
model.setPixel(4, 4, 1); // live change; returns whether it really changed
|
|
347
|
+
model.drawLine(0, 0, 0, 7, 2); // Bresenham
|
|
348
|
+
model.fill(3, 3, 5); // 4-neighbour flood fill (iterative, no recursion)
|
|
349
|
+
model.commit(); // one commit = one undo step
|
|
350
|
+
model.toSVG({ cellSize: 16 }); // run-length merged SVG string
|
|
351
|
+
model.toRGBA(16); // feed it straight into ImageData for PNG export
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
The three decisions worth stealing:
|
|
355
|
+
|
|
356
|
+
1. **History is per *operation*, not per pixel** — a 20-cell drag pushes exactly one
|
|
357
|
+
snapshot (`mousedown` paints, `mouseup` commits). Otherwise undo would need 20
|
|
358
|
+
presses to walk one stroke back, which decides whether a 1024-cell editor is usable.
|
|
359
|
+
`ICEHistoryModel` itself is a plain generic stack (push clears redo, trims to a limit,
|
|
360
|
+
notifies with a reason) — reusable for kanban or table editing too.
|
|
361
|
+
2. **Preview via the highlight layer, not “draw then undo”** — dragging a line or a
|
|
362
|
+
rectangle lights up `ICETileMap.setHighlights()` from `getLineCells()` /
|
|
363
|
+
`getRectCells()`, and only `mouseup` commits. Preview and painting share the same
|
|
364
|
+
coordinate API, so the preview is exactly what you get (a unit test paints both and
|
|
365
|
+
compares cell by cell).
|
|
366
|
+
3. **Export is pure** — `toSVG()` merges horizontal runs into single `<rect>`s (the
|
|
367
|
+
32×32 smiley emits 20 elements, not 1024), and `toRGBA(scale)` hands the page an
|
|
368
|
+
`ImageData` buffer; only the page touches `canvas.toDataURL()`. The QA asserts on the
|
|
369
|
+
data: the PNG check decodes the **IHDR** chunk to prove the bitmap is 512×512.
|
|
370
|
+
|
|
371
|
+
> A component gap this page closed: `ICETileMap` cached `rows`/`cols`/`cellSize` in
|
|
372
|
+
> instance fields, so resizing with only `setState({ rows, cols })` left the internals
|
|
373
|
+
> stale and the next `setTiles` threw (“expected 1024 cells, got 256”). There is now a
|
|
374
|
+
> proper `setSize(rows, cols, cellSize?)` that updates the internals, the state and the
|
|
375
|
+
> default width/height in one go, and clears the old cell data.
|
|
376
|
+
|
|
310
377
|
## Components
|
|
311
378
|
|
|
312
379
|
| Group | Components |
|
|
@@ -318,12 +385,12 @@ Under the hood this page is where the engine work happens:
|
|
|
318
385
|
| Feedback & status | `ICEAlert` `ICEModal` `ICEDrawer` `ICEMessage` `ICENotification` `ICETooltip` `ICEPopover` `ICEPopconfirm` `ICETour` `ICEFloatButton` `ICEEmpty` `ICESkeleton` `ICESpin` `ICEResult` `ICESteps` `ICEOverlayManager` |
|
|
319
386
|
| Navigation | `ICEMenu` `ICEBreadcrumb` `ICEAnchor` `ICEBackTop` `ICEDropdown` `ICEPagination` `ICETabs` |
|
|
320
387
|
| Layout & core | `ICEWidget` `ICEContainer` `ICEHoverManager` `ICEFocusManager` `ICEMessageManager` `ICEManager` (`ICEPainter` / `ICELayoutManager` are types) |
|
|
321
|
-
| Models | `ICEButtonModel` `ICEToggleModel` `ICEBoundedRangeModel` `ICESelectionModel` `ICEFormModel` `ICETetrisModel` `ICESnakeModel` `ICE2048Model` `ICEChip8Model` `ICEMinesweeperModel` `ICEHighScoreModel` |
|
|
388
|
+
| Models | `ICEButtonModel` `ICEToggleModel` `ICEBoundedRangeModel` `ICESelectionModel` `ICEFormModel` `ICEBiosModel` `ICEHistoryModel` `ICEPixelModel` `ICETetrisModel` `ICESnakeModel` `ICE2048Model` `ICEChip8Model` `ICEMinesweeperModel` `ICEHighScoreModel` |
|
|
322
389
|
|
|
323
390
|
Helper functions: `attachTooltip` `attachPopover` `attachPopconfirm` `attachDropdown`
|
|
324
391
|
`openModal` `openDrawer` `getICEOverlayManager` `getICEFocusManager` `getICEMessageManager`
|
|
325
392
|
`formatStatisticValue` `formatCountdown` `truncateTextLines` `buildMonthGrid` `formatCalendarDate`
|
|
326
|
-
`openImagePreview` `tween` `fadeIn` `fadeOut` `slideIn` `scaleIn` and friends.
|
|
393
|
+
`openImagePreview` `icePixelParseColor` `tween` `fadeIn` `fadeOut` `slideIn` `scaleIn` and friends.
|
|
327
394
|
|
|
328
395
|
## Theme
|
|
329
396
|
|
|
@@ -458,6 +525,11 @@ npm run qa:xp
|
|
|
458
525
|
# real clicks on the HUD
|
|
459
526
|
npm run qa:arcade
|
|
460
527
|
|
|
528
|
+
# browser QA for examples/pixel-editor.html: drawing with a real mouse (pencil drag,
|
|
529
|
+
# line/rect preview, flood fill, eraser), undo/redo via buttons and Ctrl+Z/Y, and the
|
|
530
|
+
# PNG (IHDR-checked) / SVG exports
|
|
531
|
+
npm run qa:pixel
|
|
532
|
+
|
|
461
533
|
# docs: regenerate the API reference and check relative links
|
|
462
534
|
npm run docs
|
|
463
535
|
```
|