@cratis/scene.react 3.1.0 → 3.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/core/ScreenplayCoreComponents.tsx +72 -0
- package/core/coreComponents.ts +24 -0
- package/core/corePackage.ts +16 -1
- package/core/index.ts +1 -0
- package/dist/cjs/NavBar/NavBar.js.map +1 -1
- package/dist/cjs/NavBar/extractNavigationItem.js.map +1 -1
- package/dist/cjs/SceneElementView.js.map +1 -1
- package/dist/cjs/core/CoreButton.js.map +1 -1
- package/dist/cjs/core/CoreCard.js.map +1 -1
- package/dist/cjs/core/CoreText.js.map +1 -1
- package/dist/cjs/core/ScreenplayCoreComponents.js +128 -0
- package/dist/cjs/core/ScreenplayCoreComponents.js.map +1 -0
- package/dist/cjs/core/coreComponents.js +13 -1
- package/dist/cjs/core/coreComponents.js.map +1 -1
- package/dist/cjs/core/corePackage.js +12 -1
- package/dist/cjs/core/corePackage.js.map +1 -1
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/packages/ScenePackageBundle.js.map +1 -1
- package/dist/cjs/renderer/UnresolvedComponent.js.map +1 -1
- package/dist/cjs/renderer/createReactRenderer.js.map +1 -1
- package/dist/cjs/renderer/panelLayout.js +25 -0
- package/dist/cjs/renderer/panelLayout.js.map +1 -1
- package/dist/cjs/theme/SceneThemeProvider.js.map +1 -1
- package/dist/cjs/theme/themeTokens.js.map +1 -1
- package/dist/esm/NavBar/NavBar.js.map +1 -1
- package/dist/esm/NavBar/extractNavigationItem.js.map +1 -1
- package/dist/esm/SceneElementView.js.map +1 -1
- package/dist/esm/core/CoreButton.js.map +1 -1
- package/dist/esm/core/CoreCard.js.map +1 -1
- package/dist/esm/core/CoreText.js.map +1 -1
- package/dist/esm/core/ScreenplayCoreComponents.d.ts +13 -0
- package/dist/esm/core/ScreenplayCoreComponents.d.ts.map +1 -0
- package/dist/esm/core/ScreenplayCoreComponents.js +116 -0
- package/dist/esm/core/ScreenplayCoreComponents.js.map +1 -0
- package/dist/esm/core/coreComponents.d.ts.map +1 -1
- package/dist/esm/core/coreComponents.js +13 -1
- package/dist/esm/core/coreComponents.js.map +1 -1
- package/dist/esm/core/corePackage.d.ts.map +1 -1
- package/dist/esm/core/corePackage.js +12 -1
- package/dist/esm/core/corePackage.js.map +1 -1
- package/dist/esm/core/index.d.ts +1 -0
- package/dist/esm/core/index.d.ts.map +1 -1
- package/dist/esm/core/index.js +1 -0
- package/dist/esm/core/index.js.map +1 -1
- package/dist/esm/for_ScreenplayCoreComponents/when_rendering_a_translated_screen.d.ts +2 -0
- package/dist/esm/for_ScreenplayCoreComponents/when_rendering_a_translated_screen.d.ts.map +1 -0
- package/dist/esm/for_ScreenplayCoreComponents/when_rendering_a_translated_screen.js +46 -0
- package/dist/esm/for_ScreenplayCoreComponents/when_rendering_a_translated_screen.js.map +1 -0
- package/dist/esm/for_panelLayout/when_arranging_a_panel.js +19 -0
- package/dist/esm/for_panelLayout/when_arranging_a_panel.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/packages/ScenePackageBundle.js.map +1 -1
- package/dist/esm/renderer/UnresolvedComponent.js.map +1 -1
- package/dist/esm/renderer/createReactRenderer.js.map +1 -1
- package/dist/esm/renderer/panelLayout.d.ts.map +1 -1
- package/dist/esm/renderer/panelLayout.js +26 -1
- package/dist/esm/renderer/panelLayout.js.map +1 -1
- package/dist/esm/theme/SceneThemeProvider.js.map +1 -1
- package/dist/esm/theme/themeTokens.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/for_ScreenplayCoreComponents/when_rendering_a_translated_screen.tsx +60 -0
- package/for_panelLayout/when_arranging_a_panel.ts +24 -1
- package/package.json +11 -11
- package/renderer/panelLayout.ts +22 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { expect } from 'chai';
|
|
5
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
6
|
+
import { Control, ExternalComponent, HorizontalAlignment, VerticalAlignment, Visibility } from '@cratis/scene.model';
|
|
7
|
+
import { SceneElementView } from '../SceneElementView';
|
|
8
|
+
import { coreComponents } from '../core';
|
|
9
|
+
|
|
10
|
+
function control(id: string): Control {
|
|
11
|
+
return {
|
|
12
|
+
id,
|
|
13
|
+
name: id,
|
|
14
|
+
properties: {},
|
|
15
|
+
visibility: Visibility.Visible,
|
|
16
|
+
isEnabled: true,
|
|
17
|
+
opacity: 1,
|
|
18
|
+
size: {},
|
|
19
|
+
zIndex: 0,
|
|
20
|
+
minimumSize: {},
|
|
21
|
+
maximumSize: {},
|
|
22
|
+
margin: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
23
|
+
horizontalAlignment: HorizontalAlignment.Stretch,
|
|
24
|
+
verticalAlignment: VerticalAlignment.Stretch,
|
|
25
|
+
borderThickness: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
26
|
+
padding: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
27
|
+
tabIndex: 0,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const component = (
|
|
32
|
+
id: string,
|
|
33
|
+
componentName: string,
|
|
34
|
+
properties: Record<string, unknown> = {},
|
|
35
|
+
slots: Record<string, ExternalComponent[]> = {},
|
|
36
|
+
): ExternalComponent => ({ ...control(id), componentName, properties, slots });
|
|
37
|
+
|
|
38
|
+
describe('when rendering a translated Screenplay screen', () => {
|
|
39
|
+
const title = component('title', 'core:title', { text: 'Invoices' });
|
|
40
|
+
const action = component('create', 'core:action', { command: 'CreateInvoice', label: 'Create invoice' });
|
|
41
|
+
const section = component('section', 'core:section', { name: 'Open invoices' }, { content: [title, action] });
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
render(<SceneElementView element={section} registry={coreComponents} resolveBinding={() => undefined} />);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should render the section heading', () => expect(screen.getByRole('heading', { name: 'Open invoices' })).to.exist);
|
|
48
|
+
it('should render the translated title', () => expect(screen.getByRole('heading', { name: 'Invoices' })).to.exist);
|
|
49
|
+
it('should render the modeled action', () => expect(screen.getByRole('button', { name: 'Create invoice' })).to.exist);
|
|
50
|
+
|
|
51
|
+
it('should announce the modeled command to the host', () => {
|
|
52
|
+
let command = '';
|
|
53
|
+
const listener = (event: Event) => { command = (event as CustomEvent).detail.command; };
|
|
54
|
+
globalThis.addEventListener('cratis.scene.command', listener, { once: true });
|
|
55
|
+
|
|
56
|
+
fireEvent.click(screen.getByRole('button', { name: 'Create invoice' }));
|
|
57
|
+
|
|
58
|
+
command.should.equal('CreateInvoice');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import { ColumnDefinition, Dock, DockPanel, Grid, GridUnitType, HorizontalAlignment, Orientation, RowDefinition, SceneElement, StackPanel, VerticalAlignment, Visibility, WrapPanel } from '@cratis/scene.model';
|
|
4
|
+
import { Canvas, ColumnDefinition, Dock, DockPanel, Grid, GridUnitType, HorizontalAlignment, Orientation, RowDefinition, SceneElement, StackPanel, VerticalAlignment, Visibility, WrapPanel } from '@cratis/scene.model';
|
|
5
5
|
import { childStyle, panelStyle } from '../renderer/panelLayout';
|
|
6
6
|
|
|
7
7
|
const base = {
|
|
@@ -28,6 +28,29 @@ const row = (over: Partial<RowDefinition> = {}): RowDefinition => ({ height: sta
|
|
|
28
28
|
const column = (over: Partial<ColumnDefinition> = {}): ColumnDefinition => ({ width: star(1), minimumWidth: 0, maximumWidth: Number.POSITIVE_INFINITY, ...over });
|
|
29
29
|
|
|
30
30
|
describe('when arranging a panel', () => {
|
|
31
|
+
it('should make a canvas the coordinate space its children are placed against', () => {
|
|
32
|
+
const panel: Canvas = { ...base, extent: {} };
|
|
33
|
+
panelStyle(panel)!.position!.should.equal('relative');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should size a canvas to its extent', () => {
|
|
37
|
+
const panel: Canvas = { ...base, extent: { width: 1280, height: 800 } };
|
|
38
|
+
const style = panelStyle(panel)!;
|
|
39
|
+
[style.width, style.height].should.have.members([1280, 800]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should place a canvas child at the edges it names', () => {
|
|
43
|
+
const panel: Canvas = { ...base, extent: {} };
|
|
44
|
+
const style = childStyle(panel, child({ 'Canvas.Left': 40, 'Canvas.Top': 24 }), 0)!;
|
|
45
|
+
style.position!.should.equal('absolute');
|
|
46
|
+
[style.left, style.top].should.have.members([40, 24]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should leave a canvas child that names no edge in flow', () => {
|
|
50
|
+
const panel: Canvas = { ...base, extent: {} };
|
|
51
|
+
(childStyle(panel, child(), 0) === undefined).should.be.true;
|
|
52
|
+
});
|
|
53
|
+
|
|
31
54
|
it('should lay a stack panel out along its orientation', () => {
|
|
32
55
|
const panel: StackPanel = { ...base, orientation: Orientation.Horizontal, spacing: 8 };
|
|
33
56
|
panelStyle(panel)!.flexDirection!.should.equal('row');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cratis/scene.react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "The React renderer implementing Scene.Engine's Renderer contract against real React/DOM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cratis",
|
|
@@ -50,18 +50,18 @@
|
|
|
50
50
|
"build-storybook": "storybook build"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@cratis/scene.engine": "3.
|
|
54
|
-
"@cratis/scene.model": "3.
|
|
53
|
+
"@cratis/scene.engine": "3.3.0",
|
|
54
|
+
"@cratis/scene.model": "3.3.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@cratis/scene.engine": "3.
|
|
58
|
-
"@cratis/scene.model": "3.
|
|
59
|
-
"@storybook/addon-links": "^10.
|
|
60
|
-
"@storybook/react": "^10.
|
|
61
|
-
"@storybook/react-vite": "^10.
|
|
62
|
-
"react": "^19.
|
|
63
|
-
"react-dom": "^19.
|
|
64
|
-
"storybook": "^10.
|
|
57
|
+
"@cratis/scene.engine": "3.3.0",
|
|
58
|
+
"@cratis/scene.model": "3.3.0",
|
|
59
|
+
"@storybook/addon-links": "^10.6.0",
|
|
60
|
+
"@storybook/react": "^10.6.0",
|
|
61
|
+
"@storybook/react-vite": "^10.6.0",
|
|
62
|
+
"react": "^19.3.0",
|
|
63
|
+
"react-dom": "^19.3.0",
|
|
64
|
+
"storybook": "^10.6.0"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"react": "^18.0.0 || ^19.0.0",
|
package/renderer/panelLayout.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
4
|
import type { CSSProperties } from 'react';
|
|
5
|
-
import { isDockPanel, isGrid, isStackPanel, isWrapPanel } from '@cratis/scene.engine';
|
|
5
|
+
import { isCanvas, isDockPanel, isGrid, isStackPanel, isWrapPanel } from '@cratis/scene.engine';
|
|
6
6
|
import { Dock, GridUnitType, Orientation } from '@cratis/scene.model';
|
|
7
7
|
import type { ColumnDefinition, GridLength, Panel, RowDefinition, SceneElement } from '@cratis/scene.model';
|
|
8
8
|
|
|
@@ -39,6 +39,16 @@ const number = (value: unknown): number | undefined => (typeof value === 'number
|
|
|
39
39
|
|
|
40
40
|
/** The CSS that arranges a panel's own children. */
|
|
41
41
|
export function panelStyle(panel: Panel): CSSProperties | undefined {
|
|
42
|
+
if (isCanvas(panel)) {
|
|
43
|
+
// Absolutely placed children need a positioned ancestor to be placed against, and the canvas is
|
|
44
|
+
// that ancestor rather than whatever happens to be above it.
|
|
45
|
+
return {
|
|
46
|
+
position: 'relative',
|
|
47
|
+
width: panel.extent?.width ?? undefined,
|
|
48
|
+
height: panel.extent?.height ?? undefined,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
if (isGrid(panel)) {
|
|
43
53
|
return {
|
|
44
54
|
display: 'grid',
|
|
@@ -77,6 +87,17 @@ export function panelStyle(panel: Panel): CSSProperties | undefined {
|
|
|
77
87
|
export function childStyle(panel: Panel, child: SceneElement, index: number): CSSProperties | undefined {
|
|
78
88
|
const properties = child.properties ?? {};
|
|
79
89
|
|
|
90
|
+
if (isCanvas(panel)) {
|
|
91
|
+
const left = number(properties['Canvas.Left']);
|
|
92
|
+
const top = number(properties['Canvas.Top']);
|
|
93
|
+
const right = number(properties['Canvas.Right']);
|
|
94
|
+
const bottom = number(properties['Canvas.Bottom']);
|
|
95
|
+
// A child that names no edge is not placed by the canvas at all, so it keeps whatever flow the
|
|
96
|
+
// renderer would otherwise have given it rather than being pinned to the origin.
|
|
97
|
+
if (left === undefined && top === undefined && right === undefined && bottom === undefined) return undefined;
|
|
98
|
+
return { position: 'absolute', left, top, right, bottom };
|
|
99
|
+
}
|
|
100
|
+
|
|
80
101
|
if (isGrid(panel)) {
|
|
81
102
|
const row = number(properties['Grid.Row']);
|
|
82
103
|
const column = number(properties['Grid.Column']);
|