@peekling/runtime 0.1.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 (120) hide show
  1. package/AUTHORS +8 -0
  2. package/LICENSE +202 -0
  3. package/LICENSING.md +20 -0
  4. package/NOTICE +6 -0
  5. package/README.md +294 -0
  6. package/dist/configuration-validation.d.ts +19 -0
  7. package/dist/configuration-validation.d.ts.map +1 -0
  8. package/dist/configuration-validation.js +298 -0
  9. package/dist/content.d.ts +44 -0
  10. package/dist/content.d.ts.map +1 -0
  11. package/dist/content.js +738 -0
  12. package/dist/contracts.d.ts +10 -0
  13. package/dist/contracts.d.ts.map +1 -0
  14. package/dist/contracts.js +106 -0
  15. package/dist/defaults.d.ts +7 -0
  16. package/dist/defaults.d.ts.map +1 -0
  17. package/dist/defaults.js +6 -0
  18. package/dist/diagnostics.d.ts +25 -0
  19. package/dist/diagnostics.d.ts.map +1 -0
  20. package/dist/diagnostics.js +122 -0
  21. package/dist/direction.d.ts +3 -0
  22. package/dist/direction.d.ts.map +1 -0
  23. package/dist/direction.js +6 -0
  24. package/dist/errors.d.ts +15 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +53 -0
  27. package/dist/events.d.ts +5 -0
  28. package/dist/events.d.ts.map +1 -0
  29. package/dist/events.js +60 -0
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +3 -0
  33. package/dist/input.d.ts +31 -0
  34. package/dist/input.d.ts.map +1 -0
  35. package/dist/input.js +215 -0
  36. package/dist/json.d.ts +3 -0
  37. package/dist/json.d.ts.map +1 -0
  38. package/dist/json.js +109 -0
  39. package/dist/loader.d.ts +33 -0
  40. package/dist/loader.d.ts.map +1 -0
  41. package/dist/loader.js +477 -0
  42. package/dist/locomotion.d.ts +8 -0
  43. package/dist/locomotion.d.ts.map +1 -0
  44. package/dist/locomotion.js +29 -0
  45. package/dist/normalized.d.ts +5 -0
  46. package/dist/normalized.d.ts.map +1 -0
  47. package/dist/normalized.js +266 -0
  48. package/dist/overrides.d.ts +29 -0
  49. package/dist/overrides.d.ts.map +1 -0
  50. package/dist/overrides.js +296 -0
  51. package/dist/own-data.d.ts +18 -0
  52. package/dist/own-data.d.ts.map +1 -0
  53. package/dist/own-data.js +205 -0
  54. package/dist/pack-api.d.ts +9 -0
  55. package/dist/pack-api.d.ts.map +1 -0
  56. package/dist/pack-api.js +6 -0
  57. package/dist/pack-shared.d.ts +28 -0
  58. package/dist/pack-shared.d.ts.map +1 -0
  59. package/dist/pack-shared.js +408 -0
  60. package/dist/pack.d.ts +6 -0
  61. package/dist/pack.d.ts.map +1 -0
  62. package/dist/pack.js +316 -0
  63. package/dist/peekling.css +1 -0
  64. package/dist/peekling.css.sri +1 -0
  65. package/dist/peekling.js +7469 -0
  66. package/dist/peekling.js.sri +1 -0
  67. package/dist/peekling.min.js +2 -0
  68. package/dist/peekling.min.js.sri +1 -0
  69. package/dist/plan-compiler.d.ts +82 -0
  70. package/dist/plan-compiler.d.ts.map +1 -0
  71. package/dist/plan-compiler.js +724 -0
  72. package/dist/plan.d.ts +21 -0
  73. package/dist/plan.d.ts.map +1 -0
  74. package/dist/plan.js +287 -0
  75. package/dist/preflight-api.d.ts +3 -0
  76. package/dist/preflight-api.d.ts.map +1 -0
  77. package/dist/preflight-api.js +1 -0
  78. package/dist/preflight.d.ts +22 -0
  79. package/dist/preflight.d.ts.map +1 -0
  80. package/dist/preflight.js +158 -0
  81. package/dist/registry.d.ts +9 -0
  82. package/dist/registry.d.ts.map +1 -0
  83. package/dist/registry.js +24 -0
  84. package/dist/renderer.d.ts +16 -0
  85. package/dist/renderer.d.ts.map +1 -0
  86. package/dist/renderer.js +176 -0
  87. package/dist/resolver.d.ts +3 -0
  88. package/dist/resolver.d.ts.map +1 -0
  89. package/dist/resolver.js +30 -0
  90. package/dist/runtime-diagnostics.d.ts +3 -0
  91. package/dist/runtime-diagnostics.d.ts.map +1 -0
  92. package/dist/runtime-diagnostics.js +5 -0
  93. package/dist/runtime-validation.d.ts +6 -0
  94. package/dist/runtime-validation.d.ts.map +1 -0
  95. package/dist/runtime-validation.js +104 -0
  96. package/dist/runtime.d.ts +87 -0
  97. package/dist/runtime.d.ts.map +1 -0
  98. package/dist/runtime.js +1015 -0
  99. package/dist/sections.d.ts +15 -0
  100. package/dist/sections.d.ts.map +1 -0
  101. package/dist/sections.js +221 -0
  102. package/dist/styles.d.ts +18 -0
  103. package/dist/styles.d.ts.map +1 -0
  104. package/dist/styles.js +132 -0
  105. package/dist/tooling-preflight.d.ts +23 -0
  106. package/dist/tooling-preflight.d.ts.map +1 -0
  107. package/dist/tooling-preflight.js +207 -0
  108. package/dist/tooling-validation.d.ts +8 -0
  109. package/dist/tooling-validation.d.ts.map +1 -0
  110. package/dist/tooling-validation.js +94 -0
  111. package/dist/types.d.ts +403 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +29 -0
  114. package/dist/visibility.d.ts +12 -0
  115. package/dist/visibility.d.ts.map +1 -0
  116. package/dist/visibility.js +333 -0
  117. package/dist/web-component.d.ts +31 -0
  118. package/dist/web-component.d.ts.map +1 -0
  119. package/dist/web-component.js +236 -0
  120. package/package.json +74 -0
package/dist/pack.js ADDED
@@ -0,0 +1,316 @@
1
+ import { addPackIssue, packIssue, PackValidationError } from "./errors.js";
2
+ import { DEFAULT_NATIVE_SCALE } from "./defaults.js";
3
+ import { parseDataText } from "./json.js";
4
+ import { ASSET_PATH_PATTERN, NAME_PATTERN, SEMVER_PATTERN, SPDX_LICENSE_PATTERN, } from "./contracts.js";
5
+ import { closed, record as object, validateDensityVariants, validateMotionKeyframes, validateSha256, validateStateMap, } from "./pack-shared.js";
6
+ import { NATIVE_CELL_SIZE, NATIVE_COLUMNS, NATIVE_DENSITIES, NATIVE_DIRECTIONS, NATIVE_LOGICAL_SIZES, } from "./types.js";
7
+ import { OwnDataError, snapshotPackData } from "./own-data.js";
8
+ const MAX_ATLAS_BYTES = 4 * 1024 * 1024;
9
+ export const MAX_ATLAS_SIDE = 4096;
10
+ const MAX_STRING = 256;
11
+ const METADATA_TAG_PATTERN = /^[a-z][a-z0-9._-]{0,63}$/;
12
+ function safeString(value, field, issues, maximum = MAX_STRING) {
13
+ if (typeof value !== "string" ||
14
+ value.length === 0 ||
15
+ value.length > maximum) {
16
+ addPackIssue(issues, field, `${field} must be 1-${maximum} characters`);
17
+ return undefined;
18
+ }
19
+ if (/[\u0000-\u001f\u007f]/.test(value)) {
20
+ addPackIssue(issues, field, `${field} contains control characters`);
21
+ return undefined;
22
+ }
23
+ return value;
24
+ }
25
+ export function parseManifestText(text) {
26
+ return parseDataText(text, "character.json");
27
+ }
28
+ export function validateNativePack(input, geometry, preferredDensity = 1) {
29
+ const issues = [];
30
+ try {
31
+ input = snapshotPackData(input);
32
+ }
33
+ catch (cause) {
34
+ if (cause instanceof OwnDataError) {
35
+ throw new PackValidationError([cause.message], cause.issueCode ? [cause.issueCode] : []);
36
+ }
37
+ throw cause;
38
+ }
39
+ if (!object(input))
40
+ throw new PackValidationError([
41
+ packIssue("manifest", "manifest must be an object"),
42
+ ]);
43
+ closed(input, [
44
+ "format",
45
+ "name",
46
+ "version",
47
+ "license",
48
+ "metadata",
49
+ "assets",
50
+ "states",
51
+ "capabilities",
52
+ "defaults",
53
+ ], "manifest", issues);
54
+ if (input.format !== 1)
55
+ addPackIssue(issues, "format", "format must be the integer 1");
56
+ const name = safeString(input.name, "name", issues, 64);
57
+ if (name && !NAME_PATTERN.test(name))
58
+ addPackIssue(issues, "name", "name must be a lowercase ID");
59
+ const version = safeString(input.version, "version", issues, 64);
60
+ const license = safeString(input.license, "license", issues, 128);
61
+ if (version && !SEMVER_PATTERN.test(version))
62
+ addPackIssue(issues, "version", "version must be SemVer 2.0");
63
+ if (license && !SPDX_LICENSE_PATTERN.test(license))
64
+ addPackIssue(issues, "license", "license must be SPDX or LicenseRef");
65
+ let atlasSrc;
66
+ let atlasSha256;
67
+ let rows = 0;
68
+ let density = 1;
69
+ let logicalCellSize = NATIVE_CELL_SIZE;
70
+ let sourceCellSize = NATIVE_CELL_SIZE;
71
+ let lineage;
72
+ let variants;
73
+ if (!object(input.assets)) {
74
+ addPackIssue(issues, "assets", "assets must describe an atlas or variants");
75
+ }
76
+ else if (object(input.assets.atlas)) {
77
+ closed(input.assets, ["atlas"], "assets", issues);
78
+ const atlas = input.assets.atlas;
79
+ closed(atlas, [
80
+ "src",
81
+ "columns",
82
+ "rows",
83
+ "density",
84
+ "logicalCellSize",
85
+ "sourceCellSize",
86
+ "sha256",
87
+ ], "assets.atlas", issues);
88
+ atlasSrc = safeString(atlas.src, "assets.atlas.src", issues);
89
+ if (validateSha256(atlas.sha256, "assets.atlas.sha256", issues)) {
90
+ atlasSha256 = atlas.sha256;
91
+ }
92
+ if (atlasSrc &&
93
+ (!ASSET_PATH_PATTERN.test(atlasSrc) || !/\.png$/i.test(atlasSrc))) {
94
+ addPackIssue(issues, "assets.atlas.src", "assets.atlas.src must be a relative in-pack PNG path");
95
+ }
96
+ if (atlas.columns !== NATIVE_COLUMNS) {
97
+ addPackIssue(issues, "assets.atlas.columns", `assets.atlas.columns must be ${NATIVE_COLUMNS}`);
98
+ }
99
+ const densityFields = [
100
+ atlas.density,
101
+ atlas.logicalCellSize,
102
+ atlas.sourceCellSize,
103
+ ];
104
+ const hasDensityFields = densityFields.some((value) => value !== undefined);
105
+ const hasAllDensityFields = densityFields.every((value) => value !== undefined);
106
+ if (hasDensityFields && !hasAllDensityFields) {
107
+ addPackIssue(issues, "assets.atlas.density", "assets.atlas density and sizes must appear together");
108
+ }
109
+ if (hasAllDensityFields) {
110
+ if (!NATIVE_DENSITIES.includes(atlas.density)) {
111
+ addPackIssue(issues, "assets.atlas.density", "assets.atlas.density must be 1, 2, or 4");
112
+ }
113
+ else {
114
+ density = atlas.density;
115
+ }
116
+ if (!NATIVE_LOGICAL_SIZES.includes(atlas.logicalCellSize)) {
117
+ addPackIssue(issues, "assets.atlas.logicalCellSize", "assets.atlas.logicalCellSize must be 32 or 64");
118
+ }
119
+ else {
120
+ logicalCellSize = atlas.logicalCellSize;
121
+ }
122
+ if (!Number.isInteger(atlas.sourceCellSize) ||
123
+ atlas.sourceCellSize !== logicalCellSize * density) {
124
+ addPackIssue(issues, "assets.atlas.sourceCellSize", "assets.atlas.sourceCellSize must equal logical size * density");
125
+ }
126
+ else {
127
+ sourceCellSize = atlas.sourceCellSize;
128
+ }
129
+ }
130
+ if (!Number.isInteger(atlas.rows) ||
131
+ atlas.rows < 2 ||
132
+ atlas.rows > MAX_ATLAS_SIDE / sourceCellSize) {
133
+ addPackIssue(issues, "assets.atlas.rows", `assets.atlas.rows exceeds ${MAX_ATLAS_SIDE}px at density ${density}`);
134
+ }
135
+ else {
136
+ rows = atlas.rows;
137
+ }
138
+ }
139
+ else if (object(input.assets.atlases)) {
140
+ closed(input.assets, ["atlases"], "assets", issues);
141
+ const set = input.assets.atlases;
142
+ closed(set, ["columns", "rows", "logicalCellSize", "lineage", "variants"], "assets.atlases", issues);
143
+ if (set.columns !== NATIVE_COLUMNS)
144
+ addPackIssue(issues, "assets.atlases.columns", `assets.atlases.columns must be ${NATIVE_COLUMNS}`);
145
+ if (!NATIVE_LOGICAL_SIZES.includes(set.logicalCellSize)) {
146
+ addPackIssue(issues, "assets.atlases.logicalCellSize", "assets.atlases.logicalCellSize must be 32 or 64");
147
+ }
148
+ else
149
+ logicalCellSize = set.logicalCellSize;
150
+ lineage = safeString(set.lineage, "assets.atlases.lineage", issues, 128);
151
+ if (!lineage || !/^[a-z0-9][a-z0-9._-]{2,127}$/.test(lineage))
152
+ addPackIssue(issues, "assets.atlases.lineage", "assets.atlases.lineage must be a safe ID");
153
+ variants = validateDensityVariants(set.variants, {
154
+ path: "assets.atlases.variants",
155
+ logicalWidth: logicalCellSize,
156
+ logicalHeight: logicalCellSize,
157
+ native: true,
158
+ }, issues);
159
+ const chosen = variants.length
160
+ ? selectNativeDensity(variants.map((item) => item.density), preferredDensity)
161
+ : undefined;
162
+ const selected = variants.find((item) => item.density === chosen);
163
+ if (selected) {
164
+ atlasSrc = selected.src;
165
+ atlasSha256 = selected.sha256;
166
+ density = selected.density;
167
+ sourceCellSize = selected.cellWidth;
168
+ }
169
+ if (!Number.isInteger(set.rows) ||
170
+ set.rows < 2 ||
171
+ set.rows > MAX_ATLAS_SIDE / sourceCellSize)
172
+ addPackIssue(issues, "assets.atlases.rows", `assets.atlases.rows exceeds ${MAX_ATLAS_SIDE}px`);
173
+ else
174
+ rows = set.rows;
175
+ }
176
+ else {
177
+ addPackIssue(issues, "assets", "assets must contain atlas or atlases");
178
+ }
179
+ const states = validateStateMap(input.states, rows * NATIVE_COLUMNS, issues);
180
+ const directionalStates = Object.create(null);
181
+ let locomotionMotion;
182
+ if (input.capabilities !== undefined) {
183
+ if (object(input.capabilities))
184
+ closed(input.capabilities, ["locomotion"], "capabilities", issues);
185
+ const locomotion = object(input.capabilities)
186
+ ? input.capabilities.locomotion
187
+ : undefined;
188
+ if (!object(locomotion) || !object(locomotion.directions)) {
189
+ addPackIssue(issues, "capabilities.locomotion.directions", "locomotion.directions must be an object");
190
+ }
191
+ else {
192
+ closed(locomotion, ["directions", "motion"], "capabilities.locomotion", issues);
193
+ closed(locomotion.directions, NATIVE_DIRECTIONS, "capabilities.locomotion.directions", issues);
194
+ for (const direction of NATIVE_DIRECTIONS) {
195
+ const target = locomotion.directions[direction];
196
+ if (typeof target !== "string" || !states[target])
197
+ addPackIssue(issues, `capabilities.locomotion.directions.${direction}`, `capabilities.locomotion.directions.${direction} must name a valid state`);
198
+ else
199
+ directionalStates[direction] = target;
200
+ }
201
+ if (locomotion.motion !== undefined) {
202
+ const keyframes = object(locomotion.motion)
203
+ ? locomotion.motion.keyframes
204
+ : undefined;
205
+ if (object(locomotion.motion)) {
206
+ closed(locomotion.motion, ["keyframes"], "capabilities.locomotion.motion", issues);
207
+ }
208
+ const parsed = validateMotionKeyframes(keyframes, "capabilities.locomotion.motion.keyframes", issues);
209
+ if (Array.isArray(keyframes) && parsed.length === keyframes.length)
210
+ locomotionMotion = parsed;
211
+ }
212
+ }
213
+ }
214
+ let scale = DEFAULT_NATIVE_SCALE;
215
+ if (input.defaults !== undefined) {
216
+ if (!object(input.defaults)) {
217
+ addPackIssue(issues, "defaults", "defaults must be an object");
218
+ }
219
+ else {
220
+ closed(input.defaults, ["scale"], "defaults", issues);
221
+ if (input.defaults.scale !== undefined) {
222
+ if (!Number.isInteger(input.defaults.scale) ||
223
+ input.defaults.scale < 1 ||
224
+ input.defaults.scale > 4) {
225
+ addPackIssue(issues, "defaults.scale", "defaults.scale must be an integer from 1 through 4");
226
+ }
227
+ else {
228
+ scale = input.defaults.scale;
229
+ }
230
+ }
231
+ }
232
+ }
233
+ if (!object(input.metadata)) {
234
+ addPackIssue(issues, "metadata", "metadata must be an object with a description");
235
+ }
236
+ else {
237
+ closed(input.metadata, ["title", "author", "description", "tags"], "metadata", issues);
238
+ safeString(input.metadata.description, "metadata.description", issues, 500);
239
+ if (typeof input.metadata.description === "string" &&
240
+ /:\/\//.test(input.metadata.description)) {
241
+ addPackIssue(issues, "metadata.description", "metadata.description must not contain a URL");
242
+ }
243
+ for (const key of ["title", "author"]) {
244
+ if (input.metadata[key] !== undefined) {
245
+ safeString(input.metadata[key], `metadata.${key}`, issues, 120);
246
+ if (typeof input.metadata[key] === "string" &&
247
+ /:\/\//.test(input.metadata[key])) {
248
+ addPackIssue(issues, `metadata.${key}`, `metadata.${key} must not contain a URL`);
249
+ }
250
+ }
251
+ }
252
+ if (input.metadata.tags !== undefined &&
253
+ (!Array.isArray(input.metadata.tags) ||
254
+ input.metadata.tags.length > 16 ||
255
+ input.metadata.tags.some((tag) => typeof tag !== "string" || !METADATA_TAG_PATTERN.test(tag)))) {
256
+ addPackIssue(issues, "metadata.tags", "metadata.tags allows 16 lowercase IDs");
257
+ }
258
+ }
259
+ if (geometry) {
260
+ const expectedWidth = NATIVE_COLUMNS * sourceCellSize;
261
+ const expectedHeight = rows * sourceCellSize;
262
+ if (geometry.width !== expectedWidth ||
263
+ geometry.height !== expectedHeight) {
264
+ addPackIssue(issues, "atlas.dimensions", `atlas must be exactly ${expectedWidth}x${expectedHeight}`);
265
+ }
266
+ if (geometry.width > MAX_ATLAS_SIDE ||
267
+ geometry.height > MAX_ATLAS_SIDE ||
268
+ (geometry.byteLength !== undefined &&
269
+ geometry.byteLength > MAX_ATLAS_BYTES)) {
270
+ addPackIssue(issues, "atlas.size", "atlas exceeds native resource limits");
271
+ }
272
+ }
273
+ if (issues.length ||
274
+ !name ||
275
+ !version ||
276
+ !license ||
277
+ !atlasSrc ||
278
+ !atlasSha256) {
279
+ throw new PackValidationError(issues.length
280
+ ? issues
281
+ : [packIssue("manifest.incomplete", "manifest is incomplete")]);
282
+ }
283
+ const manifest = input;
284
+ return {
285
+ name,
286
+ displayName: manifest.metadata.title ?? name,
287
+ version,
288
+ license,
289
+ atlas: {
290
+ src: atlasSrc,
291
+ sha256: atlasSha256,
292
+ columns: NATIVE_COLUMNS,
293
+ rows,
294
+ cellWidth: sourceCellSize,
295
+ cellHeight: sourceCellSize,
296
+ logicalWidth: logicalCellSize,
297
+ logicalHeight: logicalCellSize,
298
+ density: density,
299
+ ...(lineage ? { lineage } : {}),
300
+ ...(variants ? { variants } : {}),
301
+ },
302
+ states,
303
+ defaultScale: scale,
304
+ ...(Object.keys(directionalStates).length ? { directionalStates } : {}),
305
+ ...(locomotionMotion ? { locomotionMotion } : {}),
306
+ ...(manifest.metadata ? { source: { metadata: manifest.metadata } } : {}),
307
+ };
308
+ }
309
+ export function selectNativeDensity(available, required) {
310
+ const sorted = [...new Set(available)].sort((a, b) => a - b);
311
+ if (!sorted.length)
312
+ throw new PackValidationError([
313
+ packIssue("atlas.variants", "atlas variant set is empty"),
314
+ ]);
315
+ return (sorted.find((value) => value >= required) ?? sorted.at(-1));
316
+ }
@@ -0,0 +1 @@
1
+ :host{all:initial!important;position:fixed!important;inset:0!important;pointer-events:none!important}:host([data-peekling-host][hidden]){display:none!important}:host([data-peekling-host]){z-index:2147483646!important;contain:strict!important;overflow:hidden!important}.sprite{display:block;position:absolute;background-repeat:no-repeat;transform-origin:0 0}:host([data-peekling-content]){z-index:2147483645!important;color:var(--peekling-surface-color, #262626)!important;font:500 14px/1.4 system-ui!important}.surface{position:absolute;box-sizing:border-box;width:min(var(--peekling-surface-width, 320px),calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;padding:var(--peekling-surface-padding, 12px 14px);border:1px solid var(--peekling-surface-border, #d9d9d3);border-radius:var(--peekling-surface-radius, 14px);background:var(--peekling-surface-background, #fafafa);pointer-events:auto}.title{display:block}.surface p{margin:0}.surface a{display:inline-flex;min-width:44px;min-height:44px;align-items:center;justify-content:center;margin-top:6px;color:var(--peekling-surface-link, #174f00)}.surface a:focus-visible{outline:3px solid;outline-offset:3px}:host([data-peekling-controls]){z-index:2147483647!important;color:#262626!important;font:600 14px/1.25 system-ui!important}.peekling-visibility-trigger{position:fixed;right:0;bottom:0;width:64px;height:64px;border:0;background:transparent;opacity:0;pointer-events:none}.peekling-visibility-trigger:focus-visible{opacity:1;outline:3px solid;background:#fafafa}.peekling-visibility-panel{position:fixed;right:16px;bottom:16px;box-sizing:border-box;width:min(272px,calc(100vw - 32px));padding:16px;border:1px solid #d9d9d3;border-radius:18px;background:#fafafa;pointer-events:auto}.peekling-visibility-panel h2{margin:0 0 12px}.peekling-visibility-option{display:block;width:100%;min-height:44px;padding:10px 12px;border:0;background:transparent;color:inherit;font:inherit}.peekling-visibility-option:hover,.peekling-visibility-option:focus-visible{outline:2px solid}
@@ -0,0 +1 @@
1
+ sha256-w8BENjaJ/B1wtpk3iuh7jT++FlbT5+fx5BBlvePx1qo=