@caperjs/core 0.7.2 → 0.7.4

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 (68) hide show
  1. package/build/index.mjs +1 -1
  2. package/build/internal/buildFlags.mjs +63 -18
  3. package/build/internal/schema.mjs +53 -0
  4. package/build/plugins/pwa.mjs +13 -7
  5. package/cli/doctor.mjs +53 -2
  6. package/cli/doctor.test.mjs +80 -1
  7. package/cli/native.mjs +126 -15
  8. package/cli/native.test.mjs +219 -3
  9. package/extras/llms.txt +35 -3
  10. package/lib/{CaptionsPlugin-COrofpHN.js → CaptionsPlugin-CAgQBcA1.js} +7 -7
  11. package/lib/{CaptionsPlugin-COrofpHN.js.map → CaptionsPlugin-CAgQBcA1.js.map} +1 -1
  12. package/lib/{DataAdapter-T-22-_D1.js → DataAdapter-CbyqWMo-.js} +5 -5
  13. package/lib/{DataAdapter-T-22-_D1.js.map → DataAdapter-CbyqWMo-.js.map} +1 -1
  14. package/lib/{DebugRenderer-ZN692Pbg.js → DebugRenderer-Bdkpyyt6.js} +2 -2
  15. package/lib/{DebugRenderer-ZN692Pbg.js.map → DebugRenderer-Bdkpyyt6.js.map} +1 -1
  16. package/lib/{DevToolsPlugin-CQXFoj1T.js → DevToolsPlugin-Cq5HHN9K.js} +2 -2
  17. package/lib/{DevToolsPlugin-CQXFoj1T.js.map → DevToolsPlugin-Cq5HHN9K.js.map} +1 -1
  18. package/lib/{GSAPPlugin-CNkncyXS.js → GSAPPlugin-D-ujhVYo.js} +2 -2
  19. package/lib/{GSAPPlugin-CNkncyXS.js.map → GSAPPlugin-D-ujhVYo.js.map} +1 -1
  20. package/lib/{LayoutPlugin-BuJgr9bd.js → LayoutPlugin-DqbwBm-X.js} +4 -4
  21. package/lib/{LayoutPlugin-BuJgr9bd.js.map → LayoutPlugin-DqbwBm-X.js.map} +1 -1
  22. package/lib/{ScreenDebugPlugin-kz9Mr6j1.js → ScreenDebugPlugin-CyT8UxEa.js} +3 -3
  23. package/lib/{ScreenDebugPlugin-kz9Mr6j1.js.map → ScreenDebugPlugin-CyT8UxEa.js.map} +1 -1
  24. package/lib/{SpinePlugin-DDzD-Qxd.js → SpinePlugin-DyXJyA3x.js} +2 -2
  25. package/lib/{SpinePlugin-DDzD-Qxd.js.map → SpinePlugin-DyXJyA3x.js.map} +1 -1
  26. package/lib/{StatsPlugin-tyFGzVjy.js → StatsPlugin-CEhgzWby.js} +4 -4
  27. package/lib/{StatsPlugin-tyFGzVjy.js.map → StatsPlugin-CEhgzWby.js.map} +1 -1
  28. package/lib/{VoiceOverPlugin-rTNz_9eb.js → VoiceOverPlugin-CSpNZjpJ.js} +2 -2
  29. package/lib/{VoiceOverPlugin-rTNz_9eb.js.map → VoiceOverPlugin-CSpNZjpJ.js.map} +1 -1
  30. package/lib/caper.mjs +126 -129
  31. package/lib/caper.mjs.map +1 -1
  32. package/lib/{const-Cj14a5U2.js → const-Bca54QyV.js} +235 -227
  33. package/lib/{const-Cj14a5U2.js.map → const-Bca54QyV.js.map} +1 -1
  34. package/lib/core/Application.d.ts +4 -0
  35. package/lib/core/Application.d.ts.map +1 -1
  36. package/lib/core/interfaces/IApplicationOptions.d.ts +21 -0
  37. package/lib/core/interfaces/IApplicationOptions.d.ts.map +1 -1
  38. package/lib/plugins/OrientationPlugin.d.ts +57 -0
  39. package/lib/plugins/OrientationPlugin.d.ts.map +1 -0
  40. package/lib/plugins/OrientationPlugin.test.d.ts +2 -0
  41. package/lib/plugins/OrientationPlugin.test.d.ts.map +1 -0
  42. package/lib/plugins/defaults.d.ts.map +1 -1
  43. package/lib/plugins/index.d.ts +1 -0
  44. package/lib/plugins/index.d.ts.map +1 -1
  45. package/lib/{registries-DmNGVLAi.js → registries-C1nPl8B3.js} +593 -502
  46. package/lib/registries-C1nPl8B3.js.map +1 -0
  47. package/lib/ui/UICanvas.d.ts +10 -2
  48. package/lib/ui/UICanvas.d.ts.map +1 -1
  49. package/lib/utils/index.d.ts +1 -0
  50. package/lib/utils/index.d.ts.map +1 -1
  51. package/lib/utils/orientation.d.ts +44 -0
  52. package/lib/utils/orientation.test.d.ts +2 -0
  53. package/lib/utils/orientation.test.d.ts.map +1 -0
  54. package/package.json +1 -1
  55. package/src/core/Application.ts +10 -0
  56. package/src/core/interfaces/IApplicationOptions.ts +21 -0
  57. package/src/plugins/OrientationPlugin.test.ts +252 -0
  58. package/src/plugins/OrientationPlugin.ts +178 -0
  59. package/src/plugins/defaults.ts +6 -0
  60. package/src/plugins/index.ts +1 -0
  61. package/src/ui/UICanvas.test.ts +23 -1
  62. package/src/ui/UICanvas.ts +22 -3
  63. package/src/utils/index.ts +1 -0
  64. package/src/utils/orientation.d.ts +44 -0
  65. package/src/utils/orientation.js +37 -0
  66. package/src/utils/orientation.test.ts +30 -0
  67. package/src/version.ts +1 -1
  68. package/lib/registries-DmNGVLAi.js.map +0 -1
@@ -23,7 +23,7 @@ vi.mock('../core/Application', async () => {
23
23
  // constructed. See importOrder.containerFirst.test.ts.
24
24
  import '../mixins/factory/const';
25
25
  import { Signal } from '../signals';
26
- import { computeEffectivePadding, UICanvas } from './UICanvas';
26
+ import { computeEffectivePadding, resolveSafeArea, UICanvas } from './UICanvas';
27
27
 
28
28
  const zero = { top: 0, right: 0, bottom: 0, left: 0 };
29
29
 
@@ -51,6 +51,28 @@ describe('computeEffectivePadding', () => {
51
51
  });
52
52
  });
53
53
 
54
+ describe('resolveSafeArea', () => {
55
+ const insets = { top: 51, right: 4, bottom: 34, left: 4 };
56
+
57
+ it('keeps every inset when useSafeArea is true', () => {
58
+ expect(resolveSafeArea(insets, true)).toEqual(insets);
59
+ });
60
+
61
+ it('drops every inset when useSafeArea is false', () => {
62
+ expect(resolveSafeArea(insets, false)).toEqual(zero);
63
+ });
64
+
65
+ it('drops only the edges set to false, keeping the ones left out', () => {
66
+ expect(resolveSafeArea(insets, { top: false })).toEqual({ top: 0, right: 4, bottom: 34, left: 4 });
67
+ expect(resolveSafeArea(insets, { top: false, bottom: true, left: false })).toEqual({
68
+ top: 0,
69
+ right: 4,
70
+ bottom: 34,
71
+ left: 0,
72
+ });
73
+ });
74
+ });
75
+
54
76
  describe('UICanvas element reordering', () => {
55
77
  let app: any;
56
78
  let originalAppDescriptor: PropertyDescriptor | undefined;
@@ -73,11 +73,18 @@ export type UICanvasConfig = {
73
73
  padding: Padding;
74
74
  size: Size;
75
75
  useAppSize: boolean;
76
- useSafeArea: boolean;
76
+ useSafeArea: UICanvasSafeArea;
77
77
  layout?: Omit<LayoutOptions, 'target'> | null | boolean;
78
78
  autoLayoutChildren?: boolean;
79
79
  };
80
80
 
81
+ /**
82
+ * Which device safe-area insets the canvas pads by: `true` (all four, the default), `false`
83
+ * (none), or per edge, where an edge left out stays on. `{ top: false }` lets top-row UI sit
84
+ * in the camera strip of a punch-hole phone while the bottom still clears the gesture bar.
85
+ */
86
+ export type UICanvasSafeArea = boolean | Partial<Record<keyof Padding, boolean>>;
87
+
81
88
  export const UICanvasConfigKeys: (keyof UICanvasConfig)[] = [
82
89
  'debug',
83
90
  'padding',
@@ -92,7 +99,7 @@ export type UICanvasProps = {
92
99
  padding: Partial<Padding> | PointLike;
93
100
  size?: SizeLike;
94
101
  useAppSize?: boolean;
95
- useSafeArea?: boolean;
102
+ useSafeArea?: UICanvasSafeArea;
96
103
  layout?: Omit<LayoutOptions, 'target'> | null | boolean;
97
104
  autoLayoutChildren?: boolean;
98
105
  };
@@ -113,6 +120,18 @@ export function computeEffectivePadding(padding: Padding, safeArea: Padding): Pa
113
120
  };
114
121
  }
115
122
 
123
+ /** The safe-area insets `useSafeArea` keeps: all, none, or the edges not set to `false`. */
124
+ export function resolveSafeArea(safeArea: Padding, useSafeArea: UICanvasSafeArea): Padding {
125
+ if (useSafeArea === true) return { ...safeArea };
126
+ if (useSafeArea === false) return { ...zeroPadding };
127
+ return {
128
+ top: useSafeArea.top === false ? 0 : safeArea.top,
129
+ right: useSafeArea.right === false ? 0 : safeArea.right,
130
+ bottom: useSafeArea.bottom === false ? 0 : safeArea.bottom,
131
+ left: useSafeArea.left === false ? 0 : safeArea.left,
132
+ };
133
+ }
134
+
116
135
  const defaultLayout = {
117
136
  flexGrow: 0,
118
137
  flexShrink: 0,
@@ -449,7 +468,7 @@ export class UICanvas extends _UICanvas {
449
468
  private _applyPadding() {
450
469
  const padding = computeEffectivePadding(
451
470
  this.config.padding,
452
- this.config.useSafeArea ? this.app.safeArea : zeroPadding,
471
+ resolveSafeArea(this.app.safeArea, this.config.useSafeArea),
453
472
  );
454
473
  this.layout = {
455
474
  paddingLeft: padding.left,
@@ -13,6 +13,7 @@ export * from './math';
13
13
  export * from './misc';
14
14
  export * from './number';
15
15
  export * from './object';
16
+ export * from './orientation';
16
17
  export * from './padding';
17
18
  export * from './pixi';
18
19
  export * from './platform';
@@ -0,0 +1,44 @@
1
+ /** The orientation a game is locked to. */
2
+ export type OrientationLock = 'portrait' | 'landscape';
3
+
4
+ /** `orientation.overlay` in `caper.config.ts`: restyle or replace the web "rotate your device" overlay. */
5
+ export interface OrientationOverlayOptions {
6
+ /** Default: "Rotate your device" (portrait) / "Turn your device sideways" (landscape). */
7
+ text?: string;
8
+ /** CSS background. Default `#000`. */
9
+ background?: string;
10
+ /** CSS text color. Default `#fff`. */
11
+ color?: string;
12
+ /** CSS font family. Default: the system font. */
13
+ fontFamily?: string;
14
+ /** Class(es) added to the overlay so a game can style it with its own CSS. */
15
+ className?: string;
16
+ /** Build the whole overlay yourself; replaces the default element. Called once, when first shown. */
17
+ element?: () => HTMLElement;
18
+ }
19
+
20
+ /**
21
+ * `orientation` in `caper.config.ts`: a lock, or `{ lock, overlay }`. The string
22
+ * form is shorthand for `{ lock }` with the default overlay. `overlay: false`
23
+ * turns off the web overlay and its pause.
24
+ */
25
+ export type OrientationConfig =
26
+ | OrientationLock
27
+ | {
28
+ lock: OrientationLock;
29
+ overlay?: false | OrientationOverlayOptions;
30
+ };
31
+
32
+ /** `orientation` normalized by `resolveOrientation`. */
33
+ export interface ResolvedOrientation {
34
+ lock: OrientationLock;
35
+ /** `false` (no overlay, no pause) or the overlay options (`{}` for the default look). */
36
+ overlay: false | OrientationOverlayOptions;
37
+ }
38
+
39
+ /**
40
+ * `orientation` as `{ lock, overlay }`, or `null` when unset. The string form is
41
+ * shorthand for `{ lock }`; a missing `overlay` means the default overlay (`{}`).
42
+ * Throws a `TypeError` on anything else.
43
+ */
44
+ export declare function resolveOrientation(orientation: unknown): ResolvedOrientation | null;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The one normalizer for `caper.config.ts`'s `orientation`, shared by the
3
+ * runtime `orientation` plugin, the native CLI, `caper doctor` and the PWA
4
+ * default. Plain ESM with a hand-written `orientation.d.ts` beside it, so the
5
+ * Node CLI (`cli/`, `build/`) can import it without a TypeScript step. Keep it
6
+ * dependency-free and free of browser globals.
7
+ */
8
+
9
+ const LOCKS = ['portrait', 'landscape'];
10
+
11
+ /**
12
+ * `orientation` as `{ lock, overlay }`, or `null` when unset. The string form is
13
+ * shorthand for `{ lock }`; a missing `overlay` means the default overlay (`{}`).
14
+ * Throws on anything else.
15
+ *
16
+ * @param {unknown} orientation
17
+ */
18
+ export function resolveOrientation(orientation) {
19
+ if (orientation === undefined || orientation === null) return null;
20
+ if (typeof orientation === 'string') {
21
+ if (!LOCKS.includes(orientation)) {
22
+ throw new TypeError(`orientation must be 'portrait' or 'landscape' (got ${JSON.stringify(orientation)})`);
23
+ }
24
+ return { lock: orientation, overlay: {} };
25
+ }
26
+ if (typeof orientation === 'object' && !Array.isArray(orientation)) {
27
+ const { lock, overlay } = orientation;
28
+ if (!LOCKS.includes(lock)) {
29
+ throw new TypeError(`orientation.lock must be 'portrait' or 'landscape' (got ${JSON.stringify(lock)})`);
30
+ }
31
+ if (overlay !== undefined && overlay !== false && (overlay === null || typeof overlay !== 'object')) {
32
+ throw new TypeError(`orientation.overlay must be false or an object (got ${JSON.stringify(overlay)})`);
33
+ }
34
+ return { lock, overlay: overlay ?? {} };
35
+ }
36
+ throw new TypeError(`orientation must be 'portrait', 'landscape', or { lock, overlay? } (got ${JSON.stringify(orientation)})`);
37
+ }
@@ -0,0 +1,30 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { resolveOrientation } from './orientation';
3
+
4
+ describe('resolveOrientation', () => {
5
+ it('is null when unset', () => {
6
+ expect(resolveOrientation(undefined)).toBeNull();
7
+ expect(resolveOrientation(null)).toBeNull();
8
+ });
9
+
10
+ it.each(['portrait', 'landscape'] as const)('expands the %s shorthand with the default overlay', (lock) => {
11
+ expect(resolveOrientation(lock)).toEqual({ lock, overlay: {} });
12
+ });
13
+
14
+ it('keeps the object form, defaulting the overlay', () => {
15
+ expect(resolveOrientation({ lock: 'landscape' })).toEqual({ lock: 'landscape', overlay: {} });
16
+ });
17
+
18
+ it('passes overlay options and false through', () => {
19
+ const overlay = { text: 'Hold your phone upright to play' };
20
+ expect(resolveOrientation({ lock: 'portrait', overlay })).toEqual({ lock: 'portrait', overlay });
21
+ expect(resolveOrientation({ lock: 'portrait', overlay: false })).toEqual({ lock: 'portrait', overlay: false });
22
+ });
23
+
24
+ it.each(['any', 'Portrait', 1, true, {}, { lock: 'any' }, { overlay: false }, { lock: 'portrait', overlay: 'off' }])(
25
+ 'throws on %o',
26
+ (value) => {
27
+ expect(() => resolveOrientation(value)).toThrow(/orientation/);
28
+ },
29
+ );
30
+ });
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated during the build process.
2
- export const version: string = '0.7.2';
2
+ export const version: string = '0.7.4';
3
3
  export const pixiVersion: string = '8.22.0';