@almadar/ui 5.29.0 → 5.31.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/dist/avl/index.cjs +933 -6749
- package/dist/avl/index.js +934 -6750
- package/dist/components/core/atoms/Card.d.ts +2 -0
- package/dist/components/core/atoms/Input.d.ts +2 -0
- package/dist/components/core/atoms/Select.d.ts +18 -6
- package/dist/components/core/atoms/Spinner.d.ts +2 -0
- package/dist/components/core/atoms/index.d.ts +1 -1
- package/dist/components/core/molecules/DocumentViewer.d.ts +0 -2
- package/dist/components/core/molecules/Header.d.ts +0 -4
- package/dist/components/core/molecules/JsonTreeEditor.d.ts +3 -8
- package/dist/components/core/molecules/Menu.d.ts +4 -0
- package/dist/components/core/molecules/Navigation.d.ts +0 -2
- package/dist/components/core/molecules/PageHeader.d.ts +0 -2
- package/dist/components/core/molecules/PropertyInspector.d.ts +8 -1
- package/dist/components/core/molecules/index.d.ts +1 -1
- package/dist/components/core/organisms/index.d.ts +0 -1
- package/dist/components/core/templates/index.d.ts +0 -3
- package/dist/components/game/molecules/index.d.ts +0 -1
- package/dist/components/game/molecules/three/index.cjs +27 -2
- package/dist/components/game/molecules/three/index.js +27 -2
- package/dist/components/game/molecules/three/patterns.d.ts +20 -0
- package/dist/components/game/organisms/TraitSlot.d.ts +3 -1
- package/dist/components/game/organisms/types/isometric.d.ts +2 -0
- package/dist/components/index.cjs +1198 -1062
- package/dist/components/index.js +1201 -1064
- package/dist/docs/index.cjs +205 -172
- package/dist/docs/index.d.cts +4 -0
- package/dist/docs/index.js +146 -113
- package/dist/marketing/index.cjs +91 -54
- package/dist/marketing/index.d.cts +2 -0
- package/dist/marketing/index.js +58 -21
- package/dist/providers/index.cjs +563 -275
- package/dist/providers/index.js +563 -275
- package/dist/renderer/pattern-resolver.d.ts +2 -5
- package/dist/runtime/index.cjs +563 -275
- package/dist/runtime/index.js +563 -275
- package/package.json +16 -2
|
@@ -23,6 +23,8 @@ export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
23
23
|
children?: React.ReactNode;
|
|
24
24
|
/** Declarative event key emitted on click for trait dispatch */
|
|
25
25
|
action?: EventKey;
|
|
26
|
+
/** Shows a skeleton/spinner overlay while true. */
|
|
27
|
+
loading?: boolean;
|
|
26
28
|
}
|
|
27
29
|
export declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
|
|
28
30
|
export declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -18,6 +18,8 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
|
|
|
18
18
|
action?: EventKey;
|
|
19
19
|
/** Input type - supports 'select' and 'textarea' in addition to standard types */
|
|
20
20
|
inputType?: "text" | "email" | "password" | "number" | "tel" | "url" | "search" | "date" | "datetime-local" | "time" | "checkbox" | "select" | "textarea";
|
|
21
|
+
label?: string;
|
|
22
|
+
helperText?: string;
|
|
21
23
|
error?: string;
|
|
22
24
|
leftIcon?: IconInput;
|
|
23
25
|
rightIcon?: IconInput;
|
|
@@ -5,20 +5,32 @@ export interface SelectOption {
|
|
|
5
5
|
label: string;
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
}
|
|
8
|
-
export interface
|
|
8
|
+
export interface SelectOptionGroup {
|
|
9
|
+
label: string;
|
|
10
|
+
options: SelectOption[];
|
|
11
|
+
}
|
|
12
|
+
export interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "children" | "onChange" | "multiple"> {
|
|
9
13
|
/** Additional CSS classes applied to the root element. */
|
|
10
14
|
className?: string;
|
|
11
|
-
/** Select options */
|
|
12
|
-
options
|
|
15
|
+
/** Select options (flat list) */
|
|
16
|
+
options?: SelectOption[];
|
|
17
|
+
/** Grouped options — rendered as <optgroup> in native mode, sections in rich mode. */
|
|
18
|
+
groups?: SelectOptionGroup[];
|
|
13
19
|
/** Placeholder text */
|
|
14
20
|
placeholder?: string;
|
|
15
|
-
/** Current value */
|
|
16
|
-
value?: string;
|
|
21
|
+
/** Current value (string for single, string[] for multiple) */
|
|
22
|
+
value?: string | string[];
|
|
17
23
|
/** Declarative event name for trait dispatch */
|
|
18
24
|
action?: EventKey;
|
|
19
25
|
/** Error message */
|
|
20
26
|
error?: string;
|
|
27
|
+
/** Allow selecting multiple values — activates the rich dropdown. */
|
|
28
|
+
multiple?: boolean;
|
|
29
|
+
/** Show a search input inside the dropdown — activates the rich dropdown. */
|
|
30
|
+
searchable?: boolean;
|
|
31
|
+
/** Show a clear button when a value is selected. */
|
|
32
|
+
clearable?: boolean;
|
|
21
33
|
/** onChange handler or declarative event key for trait dispatch */
|
|
22
|
-
onChange?:
|
|
34
|
+
onChange?: ((value: string | string[]) => void) | EventKey;
|
|
23
35
|
}
|
|
24
36
|
export declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLSelectElement>>;
|
|
@@ -4,5 +4,7 @@ export interface SpinnerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
4
4
|
/** Additional CSS classes applied to the root element. */
|
|
5
5
|
className?: string;
|
|
6
6
|
size?: SpinnerSize;
|
|
7
|
+
/** Renders a centered overlay backdrop instead of inline. */
|
|
8
|
+
overlay?: boolean;
|
|
7
9
|
}
|
|
8
10
|
export declare const Spinner: React.ForwardRefExoticComponent<SpinnerProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -3,7 +3,7 @@ export { Button, type ButtonProps } from "./Button";
|
|
|
3
3
|
export { Input, type InputProps } from "./Input";
|
|
4
4
|
export { Label, type LabelProps } from "./Label";
|
|
5
5
|
export { Textarea, type TextareaProps } from "./Textarea";
|
|
6
|
-
export { Select, type SelectProps, type SelectOption } from "./Select";
|
|
6
|
+
export { Select, type SelectProps, type SelectOption, type SelectOptionGroup } from "./Select";
|
|
7
7
|
export { Checkbox, type CheckboxProps } from "./Checkbox";
|
|
8
8
|
export { Card, CardHeader, CardTitle, CardContent, CardBody, CardFooter, type CardProps, } from "./Card";
|
|
9
9
|
export { Badge, type BadgeProps, type BadgeVariant } from "./Badge";
|
|
@@ -51,8 +51,6 @@ export interface DocumentViewerProps {
|
|
|
51
51
|
actions?: readonly DocumentAction[];
|
|
52
52
|
/** Multiple documents (tabbed view) */
|
|
53
53
|
documents?: readonly DocumentItem[];
|
|
54
|
-
/** Entity name for schema-driven auto-fetch */
|
|
55
|
-
entity?: string;
|
|
56
54
|
/** Loading state */
|
|
57
55
|
isLoading?: boolean;
|
|
58
56
|
/** Error state */
|
|
@@ -109,9 +109,5 @@ export interface HeaderProps {
|
|
|
109
109
|
* Error state (closed circuit)
|
|
110
110
|
*/
|
|
111
111
|
error?: UiError | null;
|
|
112
|
-
/**
|
|
113
|
-
* Entity name for schema-driven auto-fetch (closed circuit)
|
|
114
|
-
*/
|
|
115
|
-
entity?: string;
|
|
116
112
|
}
|
|
117
113
|
export declare const Header: React.FC<HeaderProps>;
|
|
@@ -3,16 +3,11 @@ import type { TraitConfigValue } from '@almadar/core';
|
|
|
3
3
|
export interface JsonTreeEditorProps {
|
|
4
4
|
/** Current value (object / array / scalar). */
|
|
5
5
|
value: TraitConfigValue;
|
|
6
|
-
/** Fired with the next value on any edit. */
|
|
6
|
+
/** Fired with the next value on any edit. Unused in readonly mode. */
|
|
7
7
|
onChange: (next: TraitConfigValue) => void;
|
|
8
8
|
/** Additional CSS classes. */
|
|
9
9
|
className?: string;
|
|
10
|
+
/** Suppresses all edit controls — renders a read-only viewer. */
|
|
11
|
+
readonly?: boolean;
|
|
10
12
|
}
|
|
11
|
-
/**
|
|
12
|
-
* JsonTreeEditor — a visual, collapsible tree editor for any `TraitConfigValue`
|
|
13
|
-
* (object / array / nested / scalar). Replaces raw `JSON.stringify` text editing:
|
|
14
|
-
* each node renders a typed inline control, containers collapse, and rows can be
|
|
15
|
-
* added, removed, retyped, and (for objects) re-keyed. Self-contained — styled
|
|
16
|
-
* purely with `@almadar/ui` atoms + design tokens.
|
|
17
|
-
*/
|
|
18
13
|
export declare const JsonTreeEditor: React.FC<JsonTreeEditorProps>;
|
|
@@ -36,5 +36,9 @@ export interface MenuProps {
|
|
|
36
36
|
position?: MenuPosition;
|
|
37
37
|
/** Additional CSS classes */
|
|
38
38
|
className?: string;
|
|
39
|
+
/** Optional slot rendered above the items. */
|
|
40
|
+
header?: React.ReactNode;
|
|
41
|
+
/** Optional slot rendered below the items. */
|
|
42
|
+
footer?: React.ReactNode;
|
|
39
43
|
}
|
|
40
44
|
export declare const Menu: React.FC<MenuProps>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { DeclaredTraitConfig, TraitConfig, TraitConfigValue, AssetCatalog } from '@almadar/core';
|
|
2
|
+
import type { DeclaredTraitConfig, ConfigFieldDeclaration, TraitConfig, TraitConfigValue, AssetCatalog } from '@almadar/core';
|
|
3
3
|
import type { DisplayStateProps } from '../organisms/types';
|
|
4
4
|
/**
|
|
5
5
|
* PropertyInspector — Storybook-style controls panel for a trait's `config`.
|
|
@@ -26,4 +26,11 @@ export interface PropertyInspectorProps extends DisplayStateProps {
|
|
|
26
26
|
/** Browsable asset catalog supplied to `asset`-typed fields' AssetPicker. */
|
|
27
27
|
assets?: AssetCatalog;
|
|
28
28
|
}
|
|
29
|
+
export declare function FieldControl({ name, decl, value, onChange, assets, }: {
|
|
30
|
+
name: string;
|
|
31
|
+
decl: ConfigFieldDeclaration;
|
|
32
|
+
value: TraitConfigValue | undefined;
|
|
33
|
+
onChange: (field: string, value: TraitConfigValue) => void;
|
|
34
|
+
assets?: AssetCatalog;
|
|
35
|
+
}): React.ReactElement;
|
|
29
36
|
export declare const PropertyInspector: React.FC<PropertyInspectorProps>;
|
|
@@ -15,7 +15,7 @@ export { FilterGroup, type FilterGroupProps, type FilterDefinition } from './Fil
|
|
|
15
15
|
export { Card as ActionCard, type CardProps as ActionCardProps, type CardAction } from './Card';
|
|
16
16
|
export { Container, type ContainerProps } from './Container';
|
|
17
17
|
export { Flex, type FlexProps } from './Flex';
|
|
18
|
-
export { FloatingActionButton, type FloatingActionButtonProps } from './FloatingActionButton';
|
|
18
|
+
export { FloatingActionButton, type FloatingActionButtonProps, type FloatingAction } from './FloatingActionButton';
|
|
19
19
|
export { Grid, type GridProps } from './Grid';
|
|
20
20
|
export { InputGroup, type InputGroupProps } from './InputGroup';
|
|
21
21
|
export { Menu, type MenuProps, type MenuItem } from './Menu';
|
|
@@ -26,4 +26,3 @@ export { StepFlowOrganism, type StepFlowOrganismProps, } from "../../marketing/o
|
|
|
26
26
|
export { ShowcaseOrganism, type ShowcaseOrganismProps, } from "../../marketing/organisms/ShowcaseOrganism";
|
|
27
27
|
export { TeamOrganism, type TeamOrganismProps, } from "../../marketing/organisms/TeamOrganism";
|
|
28
28
|
export { CaseStudyOrganism, type CaseStudyOrganismProps, } from "../../marketing/organisms/CaseStudyOrganism";
|
|
29
|
-
export { FeatureRenderer, type FeatureRendererProps } from '../../game/molecules/three/renderers/FeatureRenderer';
|
|
@@ -12,6 +12,3 @@ export { LandingPageTemplate, type LandingPageTemplateProps, type LandingPageEnt
|
|
|
12
12
|
export { PricingPageTemplate, type PricingPageTemplateProps, type PricingPageEntity, } from '../../marketing/templates/PricingPageTemplate';
|
|
13
13
|
export { FeatureDetailPageTemplate, type FeatureDetailPageTemplateProps, type FeatureDetailPageEntity, type FeatureDetailSection, } from '../../marketing/templates/FeatureDetailPageTemplate';
|
|
14
14
|
export { AboutPageTemplate, type AboutPageTemplateProps, type AboutPageEntity, } from '../../marketing/templates/AboutPageTemplate';
|
|
15
|
-
export type { GameCanvas3DBattleTemplate, GameCanvas3DBattleTemplateProps } from '../../game/templates/GameCanvas3DBattleTemplate';
|
|
16
|
-
export type { GameCanvas3DCastleTemplate, GameCanvas3DCastleTemplateProps } from '../../game/templates/GameCanvas3DCastleTemplate';
|
|
17
|
-
export type { GameCanvas3DWorldMapTemplate, GameCanvas3DWorldMapTemplateProps } from '../../game/templates/GameCanvas3DWorldMapTemplate';
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
|
-
export type { GameCanvas3D, GameCanvas3DProps, GameCanvas3DHandle, GameEvent, CameraMode, MapOrientation, OverlayControl } from './GameCanvas3D';
|
|
9
8
|
export { DPad, type DPadProps, type DPadDirection } from './DPad';
|
|
10
9
|
export { ActionButtons, type ActionButtonsProps, type ActionButtonConfig } from './ActionButtons';
|
|
11
10
|
export { StatBadge, type StatBadgeProps } from './StatBadge';
|
|
@@ -1756,6 +1756,30 @@ function TileRenderer({
|
|
|
1756
1756
|
const x = (tile.x - offsetX) * cellSize;
|
|
1757
1757
|
const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
|
|
1758
1758
|
const y = (tile.elevation ?? 0) * 0.1;
|
|
1759
|
+
const position = [x, y, z];
|
|
1760
|
+
if (tile.modelUrl) {
|
|
1761
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1762
|
+
"group",
|
|
1763
|
+
{
|
|
1764
|
+
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
1765
|
+
onClick: () => onTileClick?.(tile),
|
|
1766
|
+
onPointerEnter: () => onTileHover?.(tile),
|
|
1767
|
+
onPointerLeave: () => onTileHover?.(null),
|
|
1768
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1769
|
+
ModelLoader,
|
|
1770
|
+
{
|
|
1771
|
+
url: tile.modelUrl,
|
|
1772
|
+
position,
|
|
1773
|
+
scale: cellSize * 0.9,
|
|
1774
|
+
fallbackGeometry: "box",
|
|
1775
|
+
castShadow: true,
|
|
1776
|
+
receiveShadow: true
|
|
1777
|
+
}
|
|
1778
|
+
)
|
|
1779
|
+
},
|
|
1780
|
+
tile.id ?? `tile-${tile.x}-${tile.y}`
|
|
1781
|
+
);
|
|
1782
|
+
}
|
|
1759
1783
|
const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
|
|
1760
1784
|
const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
|
|
1761
1785
|
const isValidMove = validMoves.some(
|
|
@@ -1771,7 +1795,7 @@ function TileRenderer({
|
|
|
1771
1795
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1772
1796
|
"mesh",
|
|
1773
1797
|
{
|
|
1774
|
-
position
|
|
1798
|
+
position,
|
|
1775
1799
|
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
1776
1800
|
onClick: () => onTileClick?.(tile),
|
|
1777
1801
|
onPointerEnter: () => onTileHover?.(tile),
|
|
@@ -1793,7 +1817,8 @@ function TileRenderer({
|
|
|
1793
1817
|
);
|
|
1794
1818
|
});
|
|
1795
1819
|
};
|
|
1796
|
-
|
|
1820
|
+
const hasModelTiles = tiles.some((t) => t.modelUrl);
|
|
1821
|
+
if (useInstancing && tiles.length > 0 && !hasModelTiles) {
|
|
1797
1822
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1798
1823
|
"instancedMesh",
|
|
1799
1824
|
{
|
|
@@ -1732,6 +1732,30 @@ function TileRenderer({
|
|
|
1732
1732
|
const x = (tile.x - offsetX) * cellSize;
|
|
1733
1733
|
const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
|
|
1734
1734
|
const y = (tile.elevation ?? 0) * 0.1;
|
|
1735
|
+
const position = [x, y, z];
|
|
1736
|
+
if (tile.modelUrl) {
|
|
1737
|
+
return /* @__PURE__ */ jsx(
|
|
1738
|
+
"group",
|
|
1739
|
+
{
|
|
1740
|
+
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
1741
|
+
onClick: () => onTileClick?.(tile),
|
|
1742
|
+
onPointerEnter: () => onTileHover?.(tile),
|
|
1743
|
+
onPointerLeave: () => onTileHover?.(null),
|
|
1744
|
+
children: /* @__PURE__ */ jsx(
|
|
1745
|
+
ModelLoader,
|
|
1746
|
+
{
|
|
1747
|
+
url: tile.modelUrl,
|
|
1748
|
+
position,
|
|
1749
|
+
scale: cellSize * 0.9,
|
|
1750
|
+
fallbackGeometry: "box",
|
|
1751
|
+
castShadow: true,
|
|
1752
|
+
receiveShadow: true
|
|
1753
|
+
}
|
|
1754
|
+
)
|
|
1755
|
+
},
|
|
1756
|
+
tile.id ?? `tile-${tile.x}-${tile.y}`
|
|
1757
|
+
);
|
|
1758
|
+
}
|
|
1735
1759
|
const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
|
|
1736
1760
|
const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
|
|
1737
1761
|
const isValidMove = validMoves.some(
|
|
@@ -1747,7 +1771,7 @@ function TileRenderer({
|
|
|
1747
1771
|
return /* @__PURE__ */ jsxs(
|
|
1748
1772
|
"mesh",
|
|
1749
1773
|
{
|
|
1750
|
-
position
|
|
1774
|
+
position,
|
|
1751
1775
|
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
1752
1776
|
onClick: () => onTileClick?.(tile),
|
|
1753
1777
|
onPointerEnter: () => onTileHover?.(tile),
|
|
@@ -1769,7 +1793,8 @@ function TileRenderer({
|
|
|
1769
1793
|
);
|
|
1770
1794
|
});
|
|
1771
1795
|
};
|
|
1772
|
-
|
|
1796
|
+
const hasModelTiles = tiles.some((t) => t.modelUrl);
|
|
1797
|
+
if (useInstancing && tiles.length > 0 && !hasModelTiles) {
|
|
1773
1798
|
return /* @__PURE__ */ jsx(
|
|
1774
1799
|
"instancedMesh",
|
|
1775
1800
|
{
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public 3D render-ui pattern components.
|
|
3
|
+
*
|
|
4
|
+
* These are the three.js-backed components that authors target from `render-ui`
|
|
5
|
+
* effects. They are code-split behind the optional
|
|
6
|
+
* `@almadar/ui/components/molecules/game/three` subpath and are NEVER exported
|
|
7
|
+
* from the main `@almadar/ui` barrel — that would pull @react-three/fiber into
|
|
8
|
+
* every app's main bundle.
|
|
9
|
+
*
|
|
10
|
+
* The pattern scanner (tools/almadar-pattern-sync/scanner.ts) reads THIS file to
|
|
11
|
+
* register these as render-ui patterns. It is the curated public surface: 3D
|
|
12
|
+
* scene internals (Scene3D, Camera3D, Lighting3D, …) live in `./index.ts` for
|
|
13
|
+
* the lazy loader but are intentionally absent here so they don't become
|
|
14
|
+
* render-ui targets.
|
|
15
|
+
*/
|
|
16
|
+
export { GameCanvas3D } from '../GameCanvas3D';
|
|
17
|
+
export { GameCanvas3DBattleTemplate } from '../../templates/GameCanvas3DBattleTemplate';
|
|
18
|
+
export { GameCanvas3DCastleTemplate } from '../../templates/GameCanvas3DCastleTemplate';
|
|
19
|
+
export { GameCanvas3DWorldMapTemplate } from '../../templates/GameCanvas3DWorldMapTemplate';
|
|
20
|
+
export { FeatureRenderer } from './renderers/FeatureRenderer';
|
|
@@ -29,7 +29,9 @@ export type SlotItemData = {
|
|
|
29
29
|
description?: string;
|
|
30
30
|
/** Emoji or text icon */
|
|
31
31
|
iconEmoji?: string;
|
|
32
|
-
/** Image URL icon (takes precedence over iconEmoji)
|
|
32
|
+
/** Image URL icon (takes precedence over iconEmoji)
|
|
33
|
+
* @default https://almadar-kflow-assets.web.app/shared/platformer/items/platformPack_item001.png
|
|
34
|
+
*/
|
|
33
35
|
iconUrl?: AssetUrl;
|
|
34
36
|
/** Optional state machine for tooltip display */
|
|
35
37
|
stateMachine?: TraitStateMachineDefinition;
|
|
@@ -31,6 +31,8 @@ export interface IsometricTile {
|
|
|
31
31
|
tileType?: string;
|
|
32
32
|
/** Elevation offset for 3D rendering */
|
|
33
33
|
elevation?: number;
|
|
34
|
+
/** 3D model URL (GLB format) for GameCanvas3D — rendered via ModelLoader with box fallback */
|
|
35
|
+
modelUrl?: AssetUrl;
|
|
34
36
|
}
|
|
35
37
|
/** A unit positioned on the isometric grid */
|
|
36
38
|
export type IsometricUnit = {
|