@shipload/item-renderer 0.2.1 → 0.2.2
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/package.json +8 -4
- package/src/templates/_shared.ts +2 -2
- package/src/templates/component.ts +12 -9
- package/src/templates/item-cell.ts +6 -2
- package/src/templates/module.ts +2 -3
- package/src/templates/ship-panel.ts +4 -4
- package/test/__image_snapshots__/component-hull-plates.diff.png +0 -0
- package/test/__image_snapshots__/module-engine-t1.diff.png +0 -0
- package/test/__image_snapshots__/module-storage-t1.diff.png +0 -0
- package/test/__image_snapshots__/packed-entity-ship-t1-only-engine.diff.png +0 -0
- package/test/__image_snapshots__/packed-entity-ship-t1-two-modules.diff.png +0 -0
- package/test/__image_snapshots__/resource-ore-t1.diff.png +0 -0
- package/test/templates-ship-panel.test.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipload/item-renderer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Deterministic SVG rendering for Shipload items",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
"default": "./test/fixtures/cargo-items.ts"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
-
"files": [
|
|
27
|
+
"files": [
|
|
28
|
+
"src",
|
|
29
|
+
"!src/**/*.test.ts"
|
|
30
|
+
],
|
|
28
31
|
"scripts": {
|
|
29
32
|
"test": "bun test",
|
|
30
33
|
"test:pixel": "bun test test/pixel.test.ts",
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
"fonts:copy": "bun run scripts/copy-fonts.ts"
|
|
35
38
|
},
|
|
36
39
|
"dependencies": {
|
|
37
|
-
"@shipload/sdk": "2.0.0-
|
|
40
|
+
"@shipload/sdk": "2.0.0-rc21",
|
|
38
41
|
"@wharfkit/antelope": "^1.0.0"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
|
@@ -47,5 +50,6 @@
|
|
|
47
50
|
"pixelmatch": "^6.0.0",
|
|
48
51
|
"pngjs": "^7.0.0",
|
|
49
52
|
"typescript": "^5.4.0"
|
|
50
|
-
}
|
|
53
|
+
},
|
|
54
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
51
55
|
}
|
package/src/templates/_shared.ts
CHANGED
|
@@ -4,8 +4,8 @@ export function formatMass(n: number): string {
|
|
|
4
4
|
return n.toLocaleString('en-US')
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function tierBorder(tier:
|
|
8
|
-
const key = tier
|
|
7
|
+
export function tierBorder(tier: number): string {
|
|
8
|
+
const key = `t${tier}` as keyof typeof tokens.colors.tier
|
|
9
9
|
return tokens.colors.tier[key] ?? tokens.colors.surface.panelBorder
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ResolvedItem } from '@shipload/sdk'
|
|
2
|
-
import {
|
|
1
|
+
import type { ResolvedItem, ResourceCategory } from '@shipload/sdk'
|
|
2
|
+
import { formatTier, getRecipe, getStatDefinitions, categoryColors } from '@shipload/sdk'
|
|
3
3
|
import type { CargoItem } from '../payload/codec.ts'
|
|
4
4
|
import { panel } from '../primitives/panel.ts'
|
|
5
5
|
import { iconHex } from '../primitives/icon-hex.ts'
|
|
@@ -42,16 +42,20 @@ export function renderComponent(
|
|
|
42
42
|
inverted: s.inverted,
|
|
43
43
|
}))
|
|
44
44
|
} else {
|
|
45
|
-
const
|
|
46
|
-
rows = (
|
|
47
|
-
const
|
|
48
|
-
|
|
45
|
+
const recipe = getRecipe(resolved.itemId)
|
|
46
|
+
rows = (recipe?.statSlots ?? []).flatMap(slot => {
|
|
47
|
+
const src = slot.sources[0]
|
|
48
|
+
if (!src) return []
|
|
49
|
+
const input = recipe!.inputs[src.inputIndex]
|
|
50
|
+
if (!input || !('category' in input)) return []
|
|
51
|
+
const category = input.category as ResourceCategory
|
|
52
|
+
const def = getStatDefinitions(category)[src.statIndex]
|
|
49
53
|
if (!def) return []
|
|
50
54
|
return [{
|
|
51
55
|
label: def.label,
|
|
52
56
|
abbreviation: def.abbreviation,
|
|
53
57
|
value: null,
|
|
54
|
-
color: categoryColors[
|
|
58
|
+
color: categoryColors[category],
|
|
55
59
|
inverted: def.inverted,
|
|
56
60
|
}]
|
|
57
61
|
})
|
|
@@ -83,7 +87,6 @@ export function renderComponent(
|
|
|
83
87
|
family: tokens.typography.display,
|
|
84
88
|
})
|
|
85
89
|
|
|
86
|
-
const tierNum = resolved.tier.replace(/^t/i, '')
|
|
87
90
|
const subtitleText = text({
|
|
88
91
|
x: pad,
|
|
89
92
|
y: pad + headerH + 4,
|
|
@@ -94,7 +97,7 @@ export function renderComponent(
|
|
|
94
97
|
const subtitleValue = text({
|
|
95
98
|
x: w - pad,
|
|
96
99
|
y: pad + headerH + 4,
|
|
97
|
-
value: `COMPONENT ·
|
|
100
|
+
value: `COMPONENT · ${formatTier(resolved.tier)}`,
|
|
98
101
|
size: tokens.typography.sizes.body,
|
|
99
102
|
weight: 600,
|
|
100
103
|
anchor: 'end',
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import type { ResolvedItem } from '@shipload/sdk'
|
|
1
|
+
import type { ResolvedItem, ResourceTier } from '@shipload/sdk'
|
|
2
2
|
import { tierColors, categoryColors, categoryIconShapes } from '@shipload/sdk'
|
|
3
3
|
import { el } from '../primitives/svg.ts'
|
|
4
4
|
import { text } from '../primitives/text.ts'
|
|
5
5
|
import { categoryIconPath } from '../primitives/category-icon.ts'
|
|
6
6
|
import { tokens } from '../tokens/index.ts'
|
|
7
7
|
|
|
8
|
+
function tierKey(tier: number): ResourceTier {
|
|
9
|
+
return `t${tier}` as ResourceTier
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
export interface ItemCellProps {
|
|
9
13
|
resolved: ResolvedItem
|
|
10
14
|
quantity?: number
|
|
@@ -30,7 +34,7 @@ function cellInner(props: ItemCellProps): string {
|
|
|
30
34
|
rx: r,
|
|
31
35
|
ry: r,
|
|
32
36
|
fill: tokens.colors.surface.panel,
|
|
33
|
-
stroke: tierColors[props.resolved.tier],
|
|
37
|
+
stroke: tierColors[tierKey(props.resolved.tier)] ?? tokens.colors.surface.panelBorder,
|
|
34
38
|
'stroke-width': 1.5,
|
|
35
39
|
})
|
|
36
40
|
|
package/src/templates/module.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ResolvedItem } from '@shipload/sdk'
|
|
2
|
-
import { describeModuleForItem, renderDescription } from '@shipload/sdk'
|
|
2
|
+
import { describeModuleForItem, formatTier, renderDescription } from '@shipload/sdk'
|
|
3
3
|
import type { CargoItem } from '../payload/codec.ts'
|
|
4
4
|
import { panel } from '../primitives/panel.ts'
|
|
5
5
|
import { iconHex } from '../primitives/icon-hex.ts'
|
|
@@ -86,7 +86,6 @@ export function renderModule(item: CargoItem, resolved: ResolvedItem, opts?: Ren
|
|
|
86
86
|
family: tokens.typography.display,
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
const tierNum = resolved.tier.replace(/^t/i, '')
|
|
90
89
|
const subtitleLabel = text({
|
|
91
90
|
x: pad,
|
|
92
91
|
y: pad + headerH + 4,
|
|
@@ -97,7 +96,7 @@ export function renderModule(item: CargoItem, resolved: ResolvedItem, opts?: Ren
|
|
|
97
96
|
const subtitleValue = text({
|
|
98
97
|
x: w - pad,
|
|
99
98
|
y: pad + headerH + 4,
|
|
100
|
-
value: `MODULE ·
|
|
99
|
+
value: `MODULE · ${formatTier(resolved.tier)}`,
|
|
101
100
|
size: tokens.typography.sizes.body,
|
|
102
101
|
weight: 600,
|
|
103
102
|
anchor: 'end',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TextSpan } from '@shipload/sdk'
|
|
2
2
|
import { panel } from '../primitives/panel.ts'
|
|
3
3
|
import { iconHex } from '../primitives/icon-hex.ts'
|
|
4
4
|
import { text } from '../primitives/text.ts'
|
|
@@ -16,7 +16,7 @@ export interface ShipPanelSlot {
|
|
|
16
16
|
|
|
17
17
|
export interface ShipPanelProps {
|
|
18
18
|
name: string
|
|
19
|
-
tier:
|
|
19
|
+
tier: number
|
|
20
20
|
quantity?: number
|
|
21
21
|
attributes: { capability: string; attributes: { label: string; value: number }[] }[]
|
|
22
22
|
slots: ShipPanelSlot[]
|
|
@@ -26,8 +26,8 @@ function formatNumber(n: number): string {
|
|
|
26
26
|
return n.toLocaleString('en-US')
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function tierBorder(tier:
|
|
30
|
-
const key = tier
|
|
29
|
+
function tierBorder(tier: number): string {
|
|
30
|
+
const key = `t${tier}` as keyof typeof tokens.colors.tier
|
|
31
31
|
return tokens.colors.tier[key] ?? tokens.colors.surface.panelBorder
|
|
32
32
|
}
|
|
33
33
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,7 +4,7 @@ import { renderShipPanel } from '../src/templates/ship-panel.ts'
|
|
|
4
4
|
test('renderShipPanel with empty slots renders empty module rows', () => {
|
|
5
5
|
const svg = renderShipPanel({
|
|
6
6
|
name: 'Ship T1 (Packed)',
|
|
7
|
-
tier:
|
|
7
|
+
tier: 1,
|
|
8
8
|
attributes: [{
|
|
9
9
|
capability: 'Hull',
|
|
10
10
|
attributes: [
|
|
@@ -28,7 +28,7 @@ test('renderShipPanel with empty slots renders empty module rows', () => {
|
|
|
28
28
|
test('renderShipPanel with installed slots + string descriptions', () => {
|
|
29
29
|
const svg = renderShipPanel({
|
|
30
30
|
name: 'Ship T1 (Packed)',
|
|
31
|
-
tier:
|
|
31
|
+
tier: 1,
|
|
32
32
|
attributes: [{
|
|
33
33
|
capability: 'Hull',
|
|
34
34
|
attributes: [{ label: 'Mass', value: 100 }],
|
|
@@ -47,7 +47,7 @@ test('renderShipPanel with installed slots + string descriptions', () => {
|
|
|
47
47
|
test('renderShipPanel with TextSpan[] descriptions preserves highlights', () => {
|
|
48
48
|
const svg = renderShipPanel({
|
|
49
49
|
name: 'Ship T1 (Packed)',
|
|
50
|
-
tier:
|
|
50
|
+
tier: 1,
|
|
51
51
|
attributes: [{
|
|
52
52
|
capability: 'Hull',
|
|
53
53
|
attributes: [{ label: 'Mass', value: 100 }],
|
|
@@ -71,7 +71,7 @@ test('renderShipPanel with TextSpan[] descriptions preserves highlights', () =>
|
|
|
71
71
|
test('renderShipPanel mixed slots (installed + empty)', () => {
|
|
72
72
|
const svg = renderShipPanel({
|
|
73
73
|
name: 'Ship T1 (Packed)',
|
|
74
|
-
tier:
|
|
74
|
+
tier: 1,
|
|
75
75
|
attributes: [{
|
|
76
76
|
capability: 'Hull',
|
|
77
77
|
attributes: [{ label: 'Mass', value: 100 }],
|