@crewlethq/ui 0.31.1 → 0.32.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/README.md +21 -1
- package/dist/Canvas/Canvas.d.ts +48 -2
- package/dist/Canvas/ShortcutTip.d.ts +22 -0
- package/dist/Canvas/geometry.d.ts +13 -3
- package/dist/Canvas/index.d.ts +3 -1
- package/dist/Canvas/index.js +3 -1
- package/dist/{Canvas-YVXHMWLN.css → Canvas-LRVNW7XN.css} +39 -3
- package/dist/CanvasBoard/CanvasBoard.d.ts +75 -12
- package/dist/CanvasBoard/index.d.ts +2 -2
- package/dist/CanvasBoard/index.js +6 -2
- package/dist/{CanvasBoard-ZLPDINSM.css → CanvasBoard-MBZVBWDO.css} +135 -30
- package/dist/CanvasToolbar/CanvasToolbar.d.ts +48 -0
- package/dist/CanvasToolbar/index.d.ts +3 -0
- package/dist/CanvasToolbar/index.js +12 -0
- package/dist/CanvasToolbar-AE5MXH7T.css +32 -0
- package/dist/DataView/index.js +2 -2
- package/dist/PresenterView/index.js +2 -2
- package/dist/RichEditor/index.js +1 -1
- package/dist/SheetGrid/index.js +3 -3
- package/dist/SlideCompare/index.js +2 -2
- package/dist/SlideFilmstrip/index.js +2 -2
- package/dist/SlideGrid/index.js +2 -2
- package/dist/SlideStage/SlideStage.d.ts +6 -1
- package/dist/SlideStage/index.js +1 -1
- package/dist/TreeCanvas/index.js +4 -2
- package/dist/{chunk-ALMSY7RL.js → chunk-CRKFL423.js} +1 -1
- package/dist/{chunk-O63MWA4G.js → chunk-E6CR5PEV.js} +2 -1
- package/dist/chunk-E6EWK5YY.js +33 -0
- package/dist/{chunk-OGAAHVF6.js → chunk-MBNFJSZS.js} +1 -1
- package/dist/{chunk-OJ45PPCV.js → chunk-OTN35CI4.js} +113 -30
- package/dist/{chunk-JODJS7MR.js → chunk-PJD2KFHX.js} +243 -39
- package/dist/{chunk-LR5QTFOE.js → chunk-RV7SZAHR.js} +1 -1
- package/dist/{chunk-VOX3YRFO.js → chunk-V5IGUXMZ.js} +1 -1
- package/dist/{chunk-3C3BRIMY.js → chunk-VS3KOOOL.js} +1 -1
- package/dist/{chunk-S6VG5ZFZ.js → chunk-WTNUVQVI.js} +1 -1
- package/dist/generated/index.d.ts +1 -0
- package/dist/generated/index.js +40 -39
- package/dist/index.js +40 -39
- package/dist/styles.css +211 -35
- package/package.json +3 -3
- package/dist/{Editor-YZ7KG2RD.js → Editor-YWBUJAQU.js} +1 -1
- package/dist/{chunk-RODMM35O.js → chunk-3ZAFJ4GK.js} +1 -1
- package/dist/{chunk-CT4EZF62.js → chunk-LWXRD6L6.js} +2 -2
- /package/dist/{chunk-OC46246T.js → chunk-TF2P3OPS.js} +0 -0
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
|
|
|
54
54
|
| Arranging a page | `ArrangeBoard`, `ArrangeGrid`, `ArrangeFrame` (with `useGridResize`), `ArrangeGroup`, `ArrangeList`, and the reorder hooks under them (`useReorder`, `useReorderLists`, `moveKey`) |
|
|
55
55
|
| Application shell | `AppShell` with `AppShell.Rail`, `AppShell.Topbar`, `AppShell.AccountRow` and `useAppShell`, `AuthLayout`, `SidebarNav` and `NavItem`, `BrandLockup`, `SearchTrigger`, `PageHeader`, `Toolbar`, `Stack`, `Inline`, `Spacer`, `AutoGrid`, `ErrorBoundary`, `useShortcut`, `useFullscreen` |
|
|
56
56
|
| Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `ThemeGallery`, `ThemeSwatch`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences`, and the framework-free `applyTheme`, `applyPalette`, `applyDensity` with `THEME_PREFERENCES`, `DENSITY_PREFERENCES` and their guards |
|
|
57
|
-
| Artifacts | `SandboxedFrame`, `LinkInterstitial` and `openExternal`, `VersionTimeline`, `ShareDialog` with the role ladder (`ARTIFACT_ROLES`, `SHAREABLE_ROLES`, `roleAtLeast`), `PrincipalPicker`, `Principal` and `PrincipalAvatar`, `ArtifactCard` and `ArtifactKindGlyph`, `ArtifactBar` and `ArtifactVersionChip` (an open artifact's one slim bar), `ArtifactPanel` and `ArtifactWorkspace` (the panels it opens beside or over the artifact), `CanvasBoard` (a design's artboards and notes on a `Canvas`, with the visibility budget `liveBoards`), `CanvasSchematic` (a design's cover, drawn from its boards' frames), `AccessDeniedCard`, `ArtifactIcon` (with `artifactIconGlyph` and `ARTIFACT_ICON_WORDS`), the native gallery covers (`DocCover`, `SheetCover`, `DashboardCover`), `MergeConflicts`, the dashboard pieces (`WidgetFrame`, `DatasetSource` and `DatasetSourceList`), and `FrameProtocol` (the wire between a host page and an embedded artifact, with no React in it) |
|
|
57
|
+
| Artifacts | `SandboxedFrame`, `LinkInterstitial` and `openExternal`, `VersionTimeline`, `ShareDialog` with the role ladder (`ARTIFACT_ROLES`, `SHAREABLE_ROLES`, `roleAtLeast`), `PrincipalPicker`, `Principal` and `PrincipalAvatar`, `ArtifactCard` and `ArtifactKindGlyph`, `ArtifactBar` and `ArtifactVersionChip` (an open artifact's one slim bar), `ArtifactPanel` and `ArtifactWorkspace` (the panels it opens beside or over the artifact), `CanvasBoard` (a design's artboards and notes on a `Canvas`, with the visibility budget `liveBoards`), `CanvasToolbar` (a canvas's tool palette, with `toolForKey`), `CanvasSchematic` (a design's cover, drawn from its boards' frames), `AccessDeniedCard`, `ArtifactIcon` (with `artifactIconGlyph` and `ARTIFACT_ICON_WORDS`), the native gallery covers (`DocCover`, `SheetCover`, `DashboardCover`), `MergeConflicts`, the dashboard pieces (`WidgetFrame`, `DatasetSource` and `DatasetSourceList`), and `FrameProtocol` (the wire between a host page and an embedded artifact, with no React in it) |
|
|
58
58
|
| Sheets | `SheetGrid`, the cells on their own (`CheckboxCell`, `TextCell`, `LongTextCell`, `NumberCell`, `SelectCell`, `MultiSelectCell`, `PersonCell`, `StatusCell`, `DateCell`, `UrlCell`, `RatingCell`, and `SheetCell` for any type), `ChangeMark`, and `SheetModel` (every rule a sheet is drawn from, with no React in it: values, parsing, the keyboard model, TSV, the pending edits of D23) |
|
|
59
59
|
| Presence | `PresenceStack`, `PresenceRing` and `presenceHueClass`, `CursorFlag`, `LiveCursor`, `FollowBanner`, `PeopleRail` (with `peopleRailKey`), and `PresenceModel` (the roster order, one entry per person, the session hues from `PRESENCE_HUES`, with no React in it) |
|
|
60
60
|
| Presentations | `SlideStage` (a slide laid out at 1920 by 1080 and scaled to its box, with `SLIDE_WIDTH` and `SLIDE_HEIGHT`), `useSlideKeys` (the keys a show and a clicker send), `SlideFilmstrip`, `SlideGrid`, `SlideCompare` (with `SLIDE_COMPARE_LABELS`), `PresenterView` (with `formatStopwatch`) |
|
|
@@ -204,6 +204,26 @@ places:
|
|
|
204
204
|
- A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
|
|
205
205
|
when the content beneath it moves, and every panel anchored inside follows.
|
|
206
206
|
|
|
207
|
+
## Changes in 0.32.0
|
|
208
|
+
|
|
209
|
+
**A canvas title fits its box.** `CanvasBoard` sets a title note in a size fitted to its box both ways (three fifths of its height, smaller when its text would run past its width; `titleSize` is that rule on its own), and the text clips at the box where an unusually wide face still overruns it. A long heading used to run past its box over the boards beside it, at every zoom.
|
|
210
|
+
|
|
211
|
+
**`SlideStage` names what it holds.** `roleDescription` replaces the screen reader's "slide" for a stage that holds something else, such as a design's board shown at its own layout ("artboard").
|
|
212
|
+
|
|
213
|
+
**`CanvasBoard` works like a design tool.** A floating palette (`CanvasToolbar`) holds Move (`V`) and Hand (`H`, or Space held), and on an editable canvas with `onNoteCreate` also Text (`T`) and Sticky (`S`), which place a note where the field is clicked, open it for typing and hand back Move. Under Move a click selects a board or a note and a click on the field clears it; a double-click hands a live board's page the pointer (a single click used to), Escape gives it back and a second Escape clears the selection. What a press will do next ("Double-click to use this board", "Press Escape to return to the canvas") is said in the canvas's status note beside the zoom bar, no longer under the board. A board's edge is a one pixel hairline at every zoom, drawn outside the page so it no longer narrows it by two pixels; hover outlines a board in the accent (hovering its name does too) and selection outlines it thicker. A selected item shows four resize corners: the bottom right takes the arrow keys as the old corner did, and the other three are a pointer's extra reach. A note is dragged by its paper, retyped on a double-click and deleted with Delete while selected. The fit goes down to `CANVAS_BOARD_MIN_ZOOM` (0.02), so a design laid out across many full size boards is shown whole rather than clipped at a quarter. `toolbar={false}` leaves the palette out; its keys still work.
|
|
214
|
+
|
|
215
|
+
What to change:
|
|
216
|
+
|
|
217
|
+
- A caller that hands a board the pointer on a single click should expect a double-click now.
|
|
218
|
+
- A caller with its own "add a note" controls passes `onNoteCreate(kind, at)` instead, adds the note at that canvas point and returns its id.
|
|
219
|
+
- A sticky's paper and a title's box no longer clip, so their tools and corners show; their text clips instead.
|
|
220
|
+
|
|
221
|
+
**`CanvasToolbar` is a canvas's tool palette.** Toggle buttons in a `Toolbar`, one pressed, each with a tip naming its key; `toolForKey` matches a press to a tool, for the surface that owns the keys.
|
|
222
|
+
|
|
223
|
+
**`Canvas` takes a pointer, a fit floor and actual size.** `cursor` (`hand`, `pointer`, `crosshair` or `text`) picks the pointer the field shows, from drawn cursors (`CURSORS` in `@crewlethq/icons/glyphs`) with keyword fallbacks, and a pan always shows the closed hand. `minZoom` lowers the floor the fit stops at (`fitView` and `zoomLimits` take it as `floor`). Shift 0 shows actual size and Shift 1 fits, on every canvas; `controlsActualSize` adds a 1:1 control to the zoom bar. Each zoom control's tip names its key (`ShortcutTip`, for any control that has one). The handle adds `zoomTo(scale)` and `worldAt(clientPoint)`. With `refitOnResize` (on in `CanvasBoard`), a resize refits a view nobody has moved since its last fit, so a window made narrower no longer cuts the content off; a view the reader has panned or zoomed is kept, as before.
|
|
224
|
+
|
|
225
|
+
**`@crewlethq/icons` draws pointer cursors.** `CURSORS` holds the pointer, hand, grabbing, crosshair and text cursors as complete CSS `cursor` values, generated from the vendored Lucide glyphs (`hand`, `hand-grab` and `text-cursor` are new, with `type`) in black over a white halo, as every platform draws its own pointer.
|
|
226
|
+
|
|
207
227
|
## Changes in 0.31.1
|
|
208
228
|
|
|
209
229
|
**`EditingStatus` folds "Editing" on an artifact bar's narrow arrangement**, below 640px, and keeps its dot, so a phone's bar keeps the room for the title while Cancel and Save are there. The words stay in the status for a screen reader.
|
package/dist/Canvas/Canvas.d.ts
CHANGED
|
@@ -56,7 +56,13 @@
|
|
|
56
56
|
* - FIT HAPPENS ONCE, on the first layout that has both a measured viewport
|
|
57
57
|
* and content bounds, and again only on request. A data push that changes
|
|
58
58
|
* the content never moves the operator's view, and nothing is shown before
|
|
59
|
-
* that first fit.
|
|
59
|
+
* that first fit. With `refitOnResize`, a RESIZE refits a view nobody has
|
|
60
|
+
* moved since its last fit: that view was the whole content, and a window
|
|
61
|
+
* made narrower that kept the old zoom would cut the content off for a
|
|
62
|
+
* reader who never asked to look at less of it. Once the reader has panned
|
|
63
|
+
* or zoomed, a resize keeps their view and only keeps the content
|
|
64
|
+
* reachable. It is opt in because a screen that chooses its own views
|
|
65
|
+
* after a fit (a chart held at a legible zoom) decides its own refits.
|
|
60
66
|
* - MOTION ONLY ON REQUEST. A fit, a zoom button or a reveal eases; a drag, a
|
|
61
67
|
* pinch, a wheel and a relayout anchor never do, and under reduced motion
|
|
62
68
|
* nothing does. An easing lasts as long as its transition: a clamp that
|
|
@@ -85,6 +91,8 @@ export interface CanvasHandle {
|
|
|
85
91
|
fit(): void;
|
|
86
92
|
/** Zoom about the viewport centre. */
|
|
87
93
|
zoomBy(factor: number): void;
|
|
94
|
+
/** Zoom about the viewport centre to one scale, 1 being actual size, within the limits. */
|
|
95
|
+
zoomTo(scale: number): void;
|
|
88
96
|
/** Pan the least distance that brings a world rectangle into view. */
|
|
89
97
|
reveal(target: CanvasRect): void;
|
|
90
98
|
/** Keep a node still on screen across a relayout: see `anchorView`. */
|
|
@@ -125,12 +133,28 @@ export interface CanvasHandle {
|
|
|
125
133
|
restoreView(): void;
|
|
126
134
|
/** A world rectangle in viewport coordinates, for positioning an overlay. */
|
|
127
135
|
screenRect(target: CanvasRect): CanvasRect;
|
|
136
|
+
/**
|
|
137
|
+
* The world point under a point on the page, such as a click's
|
|
138
|
+
* `clientX` and `clientY`: where a tool that places something puts it.
|
|
139
|
+
*/
|
|
140
|
+
worldAt(client: CanvasPoint): CanvasPoint;
|
|
128
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* The pointer the field shows while nothing is being dragged.
|
|
144
|
+
*
|
|
145
|
+
* `hand` says the field pans, which is what a chart moved by dragging it
|
|
146
|
+
* wants. A surface with tools names the one its tool means: `pointer` for
|
|
147
|
+
* selecting, `crosshair` for placing a thing, `text` for placing text. A pan
|
|
148
|
+
* in progress always shows the closed hand, whatever the tool.
|
|
149
|
+
*/
|
|
150
|
+
export type CanvasCursor = 'hand' | 'pointer' | 'crosshair' | 'text';
|
|
129
151
|
/** Every string the canvas renders on its own. */
|
|
130
152
|
export interface CanvasLabels {
|
|
131
153
|
zoomIn: string;
|
|
132
154
|
zoomOut: string;
|
|
133
155
|
fit: string;
|
|
156
|
+
/** The control that shows the content at actual size. */
|
|
157
|
+
actualSize: string;
|
|
134
158
|
/**
|
|
135
159
|
* The zoom readout, given the zoom as a whole percentage. It is also what
|
|
136
160
|
* opens the box a reader types one into, so it says both.
|
|
@@ -184,6 +208,12 @@ export interface CanvasProps {
|
|
|
184
208
|
* acts on the canvas from 800px away is a control nobody finds.
|
|
185
209
|
*/
|
|
186
210
|
controlsExtra?: ReactNode | undefined;
|
|
211
|
+
/**
|
|
212
|
+
* A control in the zoom bar that shows the content at actual size, which
|
|
213
|
+
* Shift 0 does whether or not it is drawn. For a canvas of pages, where a
|
|
214
|
+
* page at its own size is a view a reader asks for by name.
|
|
215
|
+
*/
|
|
216
|
+
controlsActualSize?: boolean | undefined;
|
|
187
217
|
/**
|
|
188
218
|
* Bars of the caller's own, stacked under the control bar in the same
|
|
189
219
|
* corner: a switch between two drawings of the content, a note about a key.
|
|
@@ -231,6 +261,22 @@ export interface CanvasProps {
|
|
|
231
261
|
* is the page's own ground and nothing else.
|
|
232
262
|
*/
|
|
233
263
|
ground?: CanvasGround | undefined;
|
|
264
|
+
/**
|
|
265
|
+
* The smallest zoom a fit may take: see [fitView]. [CANVAS_MIN_ZOOM] unless
|
|
266
|
+
* it is named, which suits a chart of cards; a canvas of pages names a
|
|
267
|
+
* lower one, so that a fit shows all of a design however wide it is laid.
|
|
268
|
+
*/
|
|
269
|
+
minZoom?: number | undefined;
|
|
270
|
+
/** The pointer the field shows: see [CanvasCursor]. */
|
|
271
|
+
cursor?: CanvasCursor | undefined;
|
|
272
|
+
/**
|
|
273
|
+
* Refit on a resize while the view is still the last fit, rather than keep
|
|
274
|
+
* the zoom the old size was fitted at. For a surface whose fit is the view
|
|
275
|
+
* a reader expects back whatever the window does, such as a design's
|
|
276
|
+
* boards. Off by default: a screen that adjusts the view after each fit
|
|
277
|
+
* (holding a zoom, revealing a card) runs its own refit.
|
|
278
|
+
*/
|
|
279
|
+
refitOnResize?: boolean | undefined;
|
|
234
280
|
/**
|
|
235
281
|
* Whether one finger can pan the canvas at all.
|
|
236
282
|
*
|
|
@@ -257,4 +303,4 @@ export interface CanvasProps {
|
|
|
257
303
|
ref?: Ref<CanvasHandle> | undefined;
|
|
258
304
|
className?: string | undefined;
|
|
259
305
|
}
|
|
260
|
-
export declare function Canvas({ label, content, children, overlay, controls, controlsPlacement, controlsExtra, controlsBelow, hint, largestItemWidth, dimmed, ground, touch, labels, onReady, onViewChange, ref, className, }: CanvasProps): import("react").JSX.Element;
|
|
306
|
+
export declare function Canvas({ label, content, children, overlay, controls, controlsPlacement, controlsExtra, controlsActualSize, controlsBelow, hint, largestItemWidth, dimmed, ground, minZoom, cursor, refitOnResize, touch, labels, onReady, onViewChange, ref, className, }: CanvasProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A control's tooltip that names its keyboard shortcut: "Zoom in" and the key
|
|
3
|
+
* that does it, drawn as keycaps.
|
|
4
|
+
*
|
|
5
|
+
* Every control on a canvas has a key, and a reader who has to hover each one
|
|
6
|
+
* to learn its key is a reader who is told it the moment it is useful. The tip
|
|
7
|
+
* describes the control rather than naming it (see Tooltip), so a screen reader
|
|
8
|
+
* hears the control's own name and then its shortcut, which the keycaps read
|
|
9
|
+
* aloud through Kbd's spoken form.
|
|
10
|
+
*/
|
|
11
|
+
import type { ReactElement } from 'react';
|
|
12
|
+
import { type TooltipPlacement } from '../Tooltip/index.js';
|
|
13
|
+
export interface ShortcutTipProps {
|
|
14
|
+
/** What the control does: the words the tooltip opens with. */
|
|
15
|
+
label: string;
|
|
16
|
+
/** The keys of the shortcut, in Kbd's names: `['Shift', '1']`, `['V']`. */
|
|
17
|
+
keys: readonly string[];
|
|
18
|
+
placement?: TooltipPlacement | undefined;
|
|
19
|
+
/** Exactly one element: the control. */
|
|
20
|
+
children: ReactElement;
|
|
21
|
+
}
|
|
22
|
+
export declare function ShortcutTip({ label, keys, placement, children }: ShortcutTipProps): import("react").JSX.Element;
|
|
@@ -160,8 +160,10 @@ export declare const CANVAS_ZOOM_LIMITS: CanvasZoomLimits;
|
|
|
160
160
|
* width in world units of the widest one, which the chart above this knows
|
|
161
161
|
* because it measured every card; with none given the fixed ceiling stands. It
|
|
162
162
|
* never goes below that fixed ceiling and never above [CANVAS_ZOOM_CEILING].
|
|
163
|
+
*
|
|
164
|
+
* `floor` is the fit's own floor, passed through to [fitView].
|
|
163
165
|
*/
|
|
164
|
-
export declare function zoomLimits(content: CanvasRect | null, viewport: CanvasSize, largestItem?: number, padding?: number): CanvasZoomLimits;
|
|
166
|
+
export declare function zoomLimits(content: CanvasRect | null, viewport: CanvasSize, largestItem?: number, padding?: number, floor?: number): CanvasZoomLimits;
|
|
165
167
|
export declare function clampZoom(k: number, limits?: CanvasZoomLimits): number;
|
|
166
168
|
/** Where a world point is drawn, in viewport coordinates. */
|
|
167
169
|
export declare function toScreen(view: CanvasView, point: CanvasPoint): CanvasPoint;
|
|
@@ -177,8 +179,16 @@ export declare function zoomAt(view: CanvasView, factor: number, focus: CanvasPo
|
|
|
177
179
|
* screen on each axis. A view that already satisfies it comes back unchanged.
|
|
178
180
|
*/
|
|
179
181
|
export declare function clampPan(view: CanvasView, content: CanvasRect, viewport: CanvasSize, margin?: number): CanvasView;
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
+
/**
|
|
183
|
+
* The view that shows all of `content`, centred, at no more than actual size.
|
|
184
|
+
*
|
|
185
|
+
* `floor` is the smallest zoom the fit may take, [CANVAS_MIN_ZOOM] unless it
|
|
186
|
+
* is named. A chart of cards keeps that floor, because below it a card is a
|
|
187
|
+
* grey smudge and panning the overflow is the better view. A canvas of pages
|
|
188
|
+
* names a lower one: a design laid out across many 1440px boards is several
|
|
189
|
+
* screens wide, and a fit that stops at a quarter clips it on every side.
|
|
190
|
+
*/
|
|
191
|
+
export declare function fitView(content: CanvasRect, viewport: CanvasSize, padding?: number, floor?: number): CanvasView;
|
|
182
192
|
/** The smallest pan that brings world rectangle `target` inside the padded viewport. */
|
|
183
193
|
export declare function revealView(view: CanvasView, target: CanvasRect, viewport: CanvasSize, padding?: number): CanvasView;
|
|
184
194
|
/**
|
package/dist/Canvas/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import './Canvas.css';
|
|
2
2
|
export { Canvas } from './Canvas.js';
|
|
3
|
-
export type { CanvasGround, CanvasHandle, CanvasLabels, CanvasProps } from './Canvas.js';
|
|
3
|
+
export type { CanvasCursor, CanvasGround, CanvasHandle, CanvasLabels, CanvasProps } from './Canvas.js';
|
|
4
|
+
export { ShortcutTip } from './ShortcutTip.js';
|
|
5
|
+
export type { ShortcutTipProps } from './ShortcutTip.js';
|
|
4
6
|
export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, IDENTITY_VIEW, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits, } from './geometry.js';
|
|
5
7
|
export type { CanvasPoint, CanvasRect, CanvasSize, CanvasView, CanvasZoomLimits, PinchStart, WheelLike, } from './geometry.js';
|
package/dist/Canvas/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits } from '../chunk-
|
|
1
|
+
export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, ShortcutTip, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits } from '../chunk-OTN35CI4.js';
|
|
2
2
|
import '../chunk-VYOKRN2I.js';
|
|
3
|
+
import '../chunk-SMBKXWML.js';
|
|
4
|
+
import '../chunk-QWOPX2MN.js';
|
|
3
5
|
import '../chunk-HMPFGIWM.js';
|
|
4
6
|
import '../chunk-R25RGPUB.js';
|
|
5
7
|
import '../chunk-OG6CL3EB.js';
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
position: absolute;
|
|
38
38
|
inset: 0;
|
|
39
39
|
overflow: hidden;
|
|
40
|
-
cursor: grab;
|
|
40
|
+
cursor: var(--crewlet-canvas-cursor-hand, grab);
|
|
41
41
|
/* Until it is tapped, one finger belongs to the page's vertical scroll. */
|
|
42
42
|
touch-action: pan-y;
|
|
43
43
|
}
|
|
@@ -55,8 +55,28 @@
|
|
|
55
55
|
touch-action: none;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
/*
|
|
59
|
+
* THE POINTER SAYS WHAT A PRESS WILL DO. The drawings are the component's
|
|
60
|
+
* (`CURSORS`, written on the root), each falling back to its keyword. A pan in
|
|
61
|
+
* progress shows the closed hand whatever the tool, and it is set on the whole
|
|
62
|
+
* canvas rather than the field, so a drag that crosses a board or a note keeps
|
|
63
|
+
* the hand it started with.
|
|
64
|
+
*/
|
|
65
|
+
.crewlet-canvas[data-cursor='pointer'] .crewlet-canvas__viewport {
|
|
66
|
+
cursor: var(--crewlet-canvas-cursor-pointer, default);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.crewlet-canvas[data-cursor='crosshair'] .crewlet-canvas__viewport {
|
|
70
|
+
cursor: var(--crewlet-canvas-cursor-crosshair, crosshair);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.crewlet-canvas[data-cursor='text'] .crewlet-canvas__viewport {
|
|
74
|
+
cursor: var(--crewlet-canvas-cursor-text, text);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.crewlet-canvas[data-panning='true'] .crewlet-canvas__viewport,
|
|
78
|
+
.crewlet-canvas[data-panning='true'] .crewlet-canvas__viewport * {
|
|
79
|
+
cursor: var(--crewlet-canvas-cursor-grabbing, grabbing);
|
|
60
80
|
user-select: none;
|
|
61
81
|
}
|
|
62
82
|
|
|
@@ -261,6 +281,22 @@
|
|
|
261
281
|
border-radius: var(--radius-chip);
|
|
262
282
|
}
|
|
263
283
|
|
|
284
|
+
/* Actual size, as a ratio: the readout's own control, at the button step. */
|
|
285
|
+
.crewlet-canvas__actual {
|
|
286
|
+
width: var(--size-control-sm);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*
|
|
290
|
+
* A control's tip with its shortcut (ShortcutTip.tsx): the words, then the
|
|
291
|
+
* keycaps, on one line.
|
|
292
|
+
*/
|
|
293
|
+
.crewlet-shortcut-tip {
|
|
294
|
+
display: inline-flex;
|
|
295
|
+
align-items: center;
|
|
296
|
+
gap: var(--spacing-2);
|
|
297
|
+
white-space: nowrap;
|
|
298
|
+
}
|
|
299
|
+
|
|
264
300
|
.crewlet-canvas__zoom:hover:not(:disabled) {
|
|
265
301
|
color: var(--color-text-primary);
|
|
266
302
|
background: var(--color-surface-hover);
|
|
@@ -11,23 +11,40 @@
|
|
|
11
11
|
* [CANVAS_BOARD_MAX_LIVE] at once; every other board draws as a placeholder of
|
|
12
12
|
* its size, so a canvas of sixty boards runs a dozen pages, not sixty.
|
|
13
13
|
*
|
|
14
|
+
* TOOLS, AS A DESIGN TOOL HAS THEM (CanvasToolbar). Move (`V`) selects: a
|
|
15
|
+
* click on a board or a note selects it, a click on the field clears it, and
|
|
16
|
+
* the pointer is the arrow. Hand (`H`, or Space held) pans whatever is under
|
|
17
|
+
* the pointer, boards included, with the open hand. An editable canvas that
|
|
18
|
+
* can create notes adds Text (`T`) and Sticky (`S`): a click on the field
|
|
19
|
+
* places one there, opens it for typing, and hands back the Move tool. The
|
|
20
|
+
* pointer is always the tool's (the Canvas cursors), and a pan in progress is
|
|
21
|
+
* always the closed hand.
|
|
22
|
+
*
|
|
14
23
|
* A PAGE INSIDE A BOARD NEVER TAKES THE CANVAS'S POINTER BY SURPRISE. A live
|
|
15
24
|
* board is covered by a shield that pans the canvas like the field around it;
|
|
16
|
-
* a click
|
|
17
|
-
* receive the pointer. Escape gives the pointer back to the
|
|
25
|
+
* a click on it selects the board, a double-click activates it, and only then
|
|
26
|
+
* does the page receive the pointer. Escape gives the pointer back to the
|
|
27
|
+
* canvas, and a second Escape clears the selection.
|
|
28
|
+
*
|
|
29
|
+
* EDITING (`editable`). A board's name becomes its move handle and a selected
|
|
30
|
+
* item's corners its resize handles, by pointer or, on the bottom right
|
|
31
|
+
* corner, by the arrow keys (Shift for a larger step); a note is moved by its
|
|
32
|
+
* own paper or its handle, retyped on a double-click, and deleted with Delete
|
|
33
|
+
* while selected. Each finished gesture is reported once, with whole canvas
|
|
34
|
+
* pixels, and the caller decides what a change is (for a design, a new
|
|
35
|
+
* version of its canvas).
|
|
18
36
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* finished gesture is reported once, with whole canvas pixels, and the caller
|
|
23
|
-
* decides what a change is (for a design, a new version of its canvas).
|
|
37
|
+
* HOVER AND SELECTION ARE OUTLINES IN THE ACCENT, at one screen pixel and two,
|
|
38
|
+
* over a board's own hairline edge; hovering a board's name outlines its board,
|
|
39
|
+
* because the name is how a reader picks a board out of a crowded canvas.
|
|
24
40
|
*
|
|
25
|
-
* THE CHROME STAYS ONE SIZE ON SCREEN. Titles and handles
|
|
26
|
-
* by the zoom, so a board's label is readable
|
|
27
|
-
*
|
|
41
|
+
* THE CHROME STAYS ONE SIZE ON SCREEN. Titles, edges, outlines and handles
|
|
42
|
+
* are counter-scaled by the zoom, so a board's label is readable, its edge is
|
|
43
|
+
* a hairline and its handle is a full pointer target whatever the zoom, while
|
|
44
|
+
* the board itself scales with the canvas.
|
|
28
45
|
*/
|
|
29
46
|
import { type ReactNode, type Ref } from 'react';
|
|
30
|
-
import { type CanvasHandle, type CanvasLabels } from '../Canvas/index.js';
|
|
47
|
+
import { type CanvasHandle, type CanvasLabels, type CanvasPoint } from '../Canvas/index.js';
|
|
31
48
|
/** An artboard: an id, its frame in canvas pixels and its title. */
|
|
32
49
|
export interface CanvasBoardItem {
|
|
33
50
|
id: string;
|
|
@@ -41,6 +58,17 @@ export interface CanvasBoardItem {
|
|
|
41
58
|
export type CanvasNoteColor = 'yellow' | 'pink' | 'blue' | 'green' | 'purple';
|
|
42
59
|
/** Every sticky colour, the first being a sticky's default. */
|
|
43
60
|
export declare const CANVAS_NOTE_COLORS: readonly ["yellow", "pink", "blue", "green", "purple"];
|
|
61
|
+
/**
|
|
62
|
+
* The type size a title is set in, in canvas pixels: as large as its box's
|
|
63
|
+
* height allows (three fifths of it), and no larger than lets its text run
|
|
64
|
+
* the box's width on one line, measured at an average glyph of
|
|
65
|
+
* [TITLE_GLYPH_EM] of the size. A long title is set smaller rather than run
|
|
66
|
+
* past its box over the boards beside it; the box clips whatever an unusually
|
|
67
|
+
* wide face still overruns.
|
|
68
|
+
*/
|
|
69
|
+
export declare function titleSize(note: Pick<CanvasBoardNote, 'w' | 'h' | 'text'>): number;
|
|
70
|
+
/** The average advance of a title's glyph, as a share of its size. */
|
|
71
|
+
export declare const TITLE_GLYPH_EM = 0.58;
|
|
44
72
|
/** A note: a title over a group of boards, or a sticky beside them. */
|
|
45
73
|
export interface CanvasBoardNote {
|
|
46
74
|
id: string;
|
|
@@ -79,7 +107,32 @@ export interface CanvasBoardLabels {
|
|
|
79
107
|
paused: string;
|
|
80
108
|
/** Said by an active board, so a reader knows how to give the pointer back. */
|
|
81
109
|
active: string;
|
|
110
|
+
/** Said by a selected live board, so a reader knows how to use its page. */
|
|
111
|
+
interact: string;
|
|
112
|
+
/** The tool palette's name. */
|
|
113
|
+
tools: string;
|
|
114
|
+
/** Each tool's name. */
|
|
115
|
+
moveTool: string;
|
|
116
|
+
handTool: string;
|
|
117
|
+
textTool: string;
|
|
118
|
+
stickyTool: string;
|
|
82
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* The tools a board canvas offers. Move and Hand always; Text and Sticky only
|
|
122
|
+
* where a person may edit and the caller places notes (`onNoteCreate`).
|
|
123
|
+
*
|
|
124
|
+
* NO FRAME TOOL. A board is a page an agent or an upload made, with a file
|
|
125
|
+
* behind it, and an empty frame drawn here would be a board with nothing to
|
|
126
|
+
* render. NO COMMENT TOOL until a canvas has comments to anchor.
|
|
127
|
+
*/
|
|
128
|
+
export type CanvasBoardTool = 'move' | 'hand' | 'text' | 'sticky';
|
|
129
|
+
/**
|
|
130
|
+
* The smallest zoom a board canvas fits at. A design laid out across many
|
|
131
|
+
* full-size pages is many screens wide, and every board has to be on screen
|
|
132
|
+
* at the fit, so the floor is far below a chart's; the visibility budget is
|
|
133
|
+
* what keeps a canvas this far out cheap.
|
|
134
|
+
*/
|
|
135
|
+
export declare const CANVAS_BOARD_MIN_ZOOM = 0.02;
|
|
83
136
|
export interface CanvasBoardProps {
|
|
84
137
|
/** The accessible name of the canvas, such as "Launch landing page". */
|
|
85
138
|
label: string;
|
|
@@ -102,16 +155,26 @@ export interface CanvasBoardProps {
|
|
|
102
155
|
onNoteChange?: ((note: CanvasBoardNote) => void) | undefined;
|
|
103
156
|
/** A note was deleted. */
|
|
104
157
|
onNoteRemove?: ((id: string) => void) | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* The Text or Sticky tool placed a note at a canvas point (its top left, in
|
|
160
|
+
* canvas pixels). The caller adds the note, with whatever size and starting
|
|
161
|
+
* text it gives new notes, and returns its id, which the canvas then opens
|
|
162
|
+
* for typing. Absent, or on a canvas that is not editable, neither tool is
|
|
163
|
+
* offered.
|
|
164
|
+
*/
|
|
165
|
+
onNoteCreate?: ((kind: CanvasBoardNote['kind'], at: CanvasPoint) => string | undefined) | undefined;
|
|
105
166
|
/** The control that opens one board full size; absent, there is none. */
|
|
106
167
|
onOpen?: ((id: string) => void) | undefined;
|
|
107
168
|
/** The board that holds the pointer changed; null is the canvas itself. */
|
|
108
169
|
onActivate?: ((id: string | null) => void) | undefined;
|
|
109
170
|
/** Anything else in the canvas's control bar. */
|
|
110
171
|
controlsExtra?: ReactNode | undefined;
|
|
172
|
+
/** The floating tool palette. On by default; the keys work either way. */
|
|
173
|
+
toolbar?: boolean | undefined;
|
|
111
174
|
labels?: Partial<CanvasBoardLabels> | undefined;
|
|
112
175
|
canvasLabels?: Partial<CanvasLabels> | undefined;
|
|
113
176
|
/** The canvas underneath, for a caller that reveals or fits a board. */
|
|
114
177
|
canvasRef?: Ref<CanvasHandle> | undefined;
|
|
115
178
|
className?: string | undefined;
|
|
116
179
|
}
|
|
117
|
-
export declare function CanvasBoard({ label, boards, notes, renderBoard, maxLive, minLiveWidth, editable, minSide, maxSide, onBoardChange, onNoteChange, onNoteRemove, onOpen, onActivate, controlsExtra, labels, canvasLabels, canvasRef, className, }: CanvasBoardProps): import("react").JSX.Element;
|
|
180
|
+
export declare function CanvasBoard({ label, boards, notes, renderBoard, maxLive, minLiveWidth, editable, minSide, maxSide, onBoardChange, onNoteChange, onNoteRemove, onNoteCreate, onOpen, onActivate, controlsExtra, toolbar, labels, canvasLabels, canvasRef, className, }: CanvasBoardProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './CanvasBoard.css';
|
|
2
|
-
export { CanvasBoard, CANVAS_NOTE_COLORS } from './CanvasBoard.js';
|
|
3
|
-
export type { CanvasBoardItem, CanvasBoardLabels, CanvasBoardNote, CanvasBoardProps, CanvasBoardRect, CanvasNoteColor, } from './CanvasBoard.js';
|
|
2
|
+
export { CanvasBoard, CANVAS_BOARD_MIN_ZOOM, CANVAS_NOTE_COLORS, TITLE_GLYPH_EM, titleSize } from './CanvasBoard.js';
|
|
3
|
+
export type { CanvasBoardItem, CanvasBoardLabels, CanvasBoardNote, CanvasBoardProps, CanvasBoardRect, CanvasBoardTool, CanvasNoteColor, } from './CanvasBoard.js';
|
|
4
4
|
export { CANVAS_BOARD_MAX_LIVE, CANVAS_BOARD_MIN_LIVE_WIDTH, liveBoards } from './budget.js';
|
|
5
5
|
export type { BoardFrame } from './budget.js';
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
export { CANVAS_BOARD_MAX_LIVE, CANVAS_BOARD_MIN_LIVE_WIDTH, CANVAS_NOTE_COLORS, CanvasBoard, liveBoards } from '../chunk-
|
|
1
|
+
export { CANVAS_BOARD_MAX_LIVE, CANVAS_BOARD_MIN_LIVE_WIDTH, CANVAS_BOARD_MIN_ZOOM, CANVAS_NOTE_COLORS, CanvasBoard, TITLE_GLYPH_EM, liveBoards, titleSize } from '../chunk-PJD2KFHX.js';
|
|
2
2
|
import '../chunk-CJKMURZO.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-E6EWK5YY.js';
|
|
4
|
+
import '../chunk-PGRPNDWM.js';
|
|
5
|
+
import '../chunk-OTN35CI4.js';
|
|
4
6
|
import '../chunk-VYOKRN2I.js';
|
|
7
|
+
import '../chunk-SMBKXWML.js';
|
|
8
|
+
import '../chunk-QWOPX2MN.js';
|
|
5
9
|
import '../chunk-HMPFGIWM.js';
|
|
6
10
|
import '../chunk-R25RGPUB.js';
|
|
7
11
|
import '../chunk-OG6CL3EB.js';
|