@zylem/ui 0.9.8 → 0.9.9

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/etc/ui.api.md CHANGED
@@ -170,6 +170,9 @@ export const CAMERA_ICONS: readonly [{
170
170
  readonly Icon: Component<ZylemIconProps>;
171
171
  }];
172
172
 
173
+ // @public (undocumented)
174
+ export const CAMERA_TOGGLE_IDS: readonly ["game", "perspective", "iso-left-top", "top", "iso-right-top", "left", "free", "right", "iso-left-bottom", "bottom", "iso-right-bottom"];
175
+
173
176
  // @public
174
177
  export const CAMERA_VIEWS: readonly [{
175
178
  readonly name: "view-iso-left-top";
@@ -229,6 +232,22 @@ export const cameraIconNodes: {
229
232
  readonly 'view-iso-left-bottom': IconNode;
230
233
  };
231
234
 
235
+ // @public
236
+ export function CameraToggle(props: CameraToggleProps): JSX;
237
+
238
+ // @public (undocumented)
239
+ export type CameraToggleId = (typeof CAMERA_TOGGLE_IDS)[number];
240
+
241
+ // @public (undocumented)
242
+ export interface CameraToggleProps {
243
+ on?: boolean | undefined;
244
+ onAction?: (() => void) | undefined;
245
+ // (undocumented)
246
+ onChange: (id: CameraToggleId) => void;
247
+ placement?: MenuButtonProps['placement'];
248
+ value: CameraToggleId;
249
+ }
250
+
232
251
  // @public
233
252
  export function Card(props: CardProps): JSX.Element;
234
253
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zylem/ui",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Design tokens, global styles, and Solid components for Zylem, built with vanilla-extract",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,115 @@
1
+ import { For, Show, type Component } from 'solid-js';
2
+ import { Dynamic } from 'solid-js/web';
3
+ import {
4
+ FreePerspective,
5
+ GameCamera,
6
+ Perspective,
7
+ ViewBottom,
8
+ ViewIsoLeftBottom,
9
+ ViewIsoLeftTop,
10
+ ViewIsoRightBottom,
11
+ ViewIsoRightTop,
12
+ ViewLeft,
13
+ ViewRight,
14
+ ViewTop,
15
+ } from '../../icons';
16
+ import { MenuButton, type MenuButtonProps } from '../MenuButton/MenuButton';
17
+ import { ToolbarButton } from '../ToolbarButton/ToolbarButton';
18
+
19
+ /** Game and perspective sit above the cube. The square is row-major. */
20
+ const HEADER = ['game', 'perspective'] as const;
21
+ const SQUARE = [
22
+ 'iso-left-top',
23
+ 'top',
24
+ 'iso-right-top',
25
+ 'left',
26
+ 'free',
27
+ 'right',
28
+ 'iso-left-bottom',
29
+ 'bottom',
30
+ 'iso-right-bottom',
31
+ ] as const;
32
+
33
+ export const CAMERA_TOGGLE_IDS = [...HEADER, ...SQUARE] as const;
34
+
35
+ export type CameraToggleId = (typeof CAMERA_TOGGLE_IDS)[number];
36
+
37
+ const VIEWS: Record<CameraToggleId, { label: string; icon: Component<{ class?: string }> }> = {
38
+ game: { label: 'Game camera', icon: GameCamera },
39
+ perspective: { label: 'Perspective', icon: Perspective },
40
+ 'iso-left-top': { label: 'Iso left/top', icon: ViewIsoLeftTop },
41
+ top: { label: 'Top', icon: ViewTop },
42
+ 'iso-right-top': { label: 'Iso right/top', icon: ViewIsoRightTop },
43
+ left: { label: 'Left', icon: ViewLeft },
44
+ free: { label: 'Free camera', icon: FreePerspective },
45
+ right: { label: 'Right', icon: ViewRight },
46
+ 'iso-left-bottom': { label: 'Iso left/bottom', icon: ViewIsoLeftBottom },
47
+ bottom: { label: 'Bottom', icon: ViewBottom },
48
+ 'iso-right-bottom': { label: 'Iso right/bottom', icon: ViewIsoRightBottom },
49
+ };
50
+
51
+ export interface CameraToggleProps {
52
+ /** The view the face shows. */
53
+ value: CameraToggleId;
54
+ onChange: (id: CameraToggleId) => void;
55
+ /**
56
+ * Draws the face as an on/off toggle. Electric blue while an editor camera
57
+ * is showing; the game camera is the off state.
58
+ */
59
+ on?: boolean | undefined;
60
+ /** Splits the button: the face fires this and the chevron opens the cube. */
61
+ onAction?: (() => void) | undefined;
62
+ /** Where the cube opens. Defaults to dropping down from the face. */
63
+ placement?: MenuButtonProps['placement'];
64
+ }
65
+
66
+ /**
67
+ * One camera button. The face is the current view. The chevron opens a square:
68
+ * free camera in the middle, orthographic views on the edges, isometric views
69
+ * on the corners, with the game camera and perspective on the row above.
70
+ */
71
+ export function CameraToggle(props: CameraToggleProps) {
72
+ const current = () => VIEWS[props.value] ?? VIEWS.game;
73
+
74
+ const cell = (id: CameraToggleId, close: () => void) => {
75
+ const view = VIEWS[id];
76
+ return (
77
+ <ToolbarButton
78
+ label={view.label}
79
+ selected={props.value === id}
80
+ onClick={() => {
81
+ props.onChange(id);
82
+ close();
83
+ }}
84
+ >
85
+ <Dynamic component={view.icon} class="zylem-icon" />
86
+ </ToolbarButton>
87
+ );
88
+ };
89
+
90
+ return (
91
+ <Show when={current()} keyed>
92
+ {(view) => (
93
+ <MenuButton
94
+ label={view.label}
95
+ selected={props.on === undefined}
96
+ on={props.on}
97
+ onAction={props.onAction}
98
+ placement={props.placement ?? 'bottom-start'}
99
+ menu={(close) => (
100
+ <div class="zylem-menu-button__compass">
101
+ <div class="zylem-menu-button__compass-row">
102
+ <For each={HEADER}>{(id) => cell(id, close)}</For>
103
+ </div>
104
+ <div class="zylem-menu-button__compass-square">
105
+ <For each={SQUARE}>{(id) => cell(id, close)}</For>
106
+ </div>
107
+ </div>
108
+ )}
109
+ >
110
+ <Dynamic component={view.icon} class="zylem-icon" />
111
+ </MenuButton>
112
+ )}
113
+ </Show>
114
+ );
115
+ }
@@ -100,6 +100,12 @@ export {
100
100
  type ToolbarDropdownItem,
101
101
  type ToolbarDropdownMenuProps,
102
102
  } from './ToolbarDropdownMenu/ToolbarDropdownMenu';
103
+ export {
104
+ CameraToggle,
105
+ CAMERA_TOGGLE_IDS,
106
+ type CameraToggleId,
107
+ type CameraToggleProps,
108
+ } from './CameraToggle/CameraToggle';
103
109
  export { ItemPicker, type ItemPickerProps } from './ItemPicker/ItemPicker';
104
110
  export {
105
111
  filterItems,