@datalayer/primer-addons 1.0.20 → 1.0.22
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 +14 -0
- package/lib/components/appearance/AppearanceMenuWithStore.d.ts +26 -0
- package/lib/components/appearance/AppearanceMenuWithStore.js +21 -0
- package/lib/components/appearance/CollaboratorPalette.d.ts +65 -0
- package/lib/components/appearance/CollaboratorPalette.js +160 -0
- package/lib/components/appearance/index.d.ts +2 -0
- package/lib/components/appearance/index.js +2 -0
- package/lib/components/box/Box.d.ts +17 -5
- package/lib/components/box/Box.js +3 -5
- package/lib/components/calendar-picker/CalendarPicker.d.ts +35 -0
- package/lib/components/calendar-picker/CalendarPicker.js +146 -0
- package/lib/components/calendar-picker/index.d.ts +1 -0
- package/lib/components/calendar-picker/index.js +5 -0
- package/lib/components/card/Card.d.ts +6 -1
- package/lib/components/card/Card.js +1 -1
- package/lib/components/color/ColorSwatch.d.ts +1 -1
- package/lib/components/color-picker/ColorPicker.d.ts +97 -0
- package/lib/components/color-picker/ColorPicker.js +358 -0
- package/lib/components/color-picker/index.d.ts +1 -0
- package/lib/components/color-picker/index.js +5 -0
- package/lib/components/content-loader/ContentLoader.d.ts +1 -1
- package/lib/components/content-loader/ContentLoader.stories.d.ts +1 -1
- package/lib/components/date-picker/DatePicker.d.ts +46 -0
- package/lib/components/date-picker/DatePicker.js +98 -0
- package/lib/components/date-picker/index.d.ts +1 -0
- package/lib/components/date-picker/index.js +5 -0
- package/lib/components/icons/CircleIcon.d.ts +1 -1
- package/lib/components/icons/CircleIcon.stories.d.ts +1 -1
- package/lib/components/index.d.ts +5 -0
- package/lib/components/index.js +5 -0
- package/lib/components/logo/DatalayerText.d.ts +1 -1
- package/lib/components/logo/index.d.ts +0 -1
- package/lib/components/logo/index.js +0 -1
- package/lib/components/side-overlay/SideOverlay.d.ts +5 -5
- package/lib/components/side-overlay/SideOverlay.stories.d.ts +1 -1
- package/lib/components/slider/Slider.d.ts +1 -1
- package/lib/components/slider/Slider.stories.d.ts +1 -1
- package/lib/components/sliding-panel/SlidingPanel.d.ts +1 -1
- package/lib/components/sliding-panel/SlidingPanel.stories.d.ts +1 -1
- package/lib/components/toolbar/Toolbar.d.ts +2 -2
- package/lib/components/toolbar/Toolbar.js +0 -0
- package/lib/components/toolbar/ToolbarButton.d.ts +3 -1
- package/lib/components/toolbar/ToolbarButton.js +54 -22
- package/lib/components/toolbar/ToolbarDivider.d.ts +1 -1
- package/lib/components/toolbar/ToolbarDropdown.d.ts +3 -3
- package/lib/components/toolbar/ToolbarDropdown.js +66 -35
- package/lib/components/toolbar/ToolbarRenderer.d.ts +20 -3
- package/lib/components/toolbar/ToolbarRenderer.js +16 -16
- package/lib/components/toolbar/types.d.ts +15 -8
- package/lib/reactor/AppearancePlugin.d.ts +31 -0
- package/lib/reactor/AppearancePlugin.js +63 -0
- package/lib/reactor/ThemePlugin.d.ts +5 -0
- package/lib/reactor/ThemePlugin.js +98 -0
- package/lib/reactor/index.d.ts +30 -0
- package/lib/reactor/index.js +34 -0
- package/lib/reactor/page-layout/PageLayout.d.ts +148 -0
- package/lib/reactor/page-layout/PageLayout.js +310 -0
- package/lib/reactor/page-layout/PageLayoutPlugin.d.ts +59 -0
- package/lib/reactor/page-layout/PageLayoutPlugin.js +105 -0
- package/lib/reactor/page-layout/PagePanelToggle.d.ts +21 -0
- package/lib/reactor/page-layout/PagePanelToggle.js +29 -0
- package/lib/reactor/page-layout/SlotPageLayout.d.ts +36 -0
- package/lib/reactor/page-layout/SlotPageLayout.js +25 -0
- package/lib/reactor/page-layout/panelState.d.ts +28 -0
- package/lib/reactor/page-layout/panelState.js +49 -0
- package/lib/story-helpers.d.ts +2 -2
- package/lib/theme/DatalayerBrandThemeProvider.d.ts +1 -1
- package/lib/theme/DatalayerThemeProvider.d.ts +5 -5
- package/lib/theme/DatalayerThemeProvider.js +119 -58
- package/lib/theme/css/createThemeCSSVars.d.ts +1 -0
- package/lib/theme/css/createThemeCSSVars.js +9 -0
- package/lib/theme/fontStacks.d.ts +2 -0
- package/lib/theme/fontStacks.js +6 -0
- package/lib/theme/index.d.ts +2 -0
- package/lib/theme/index.js +2 -0
- package/lib/theme/palettes/ColorPalette.d.ts +3 -3
- package/lib/theme/portableTheme.d.ts +32 -0
- package/lib/theme/portableTheme.js +45 -0
- package/lib/utils/Helper.d.ts +2 -2
- package/lib/utils/Portals.d.ts +15 -0
- package/lib/utils/Portals.js +83 -28
- package/lib/utils/Styles.d.ts +1 -1
- package/package.json +15 -14
- package/lib/components/logo/DI.d.ts +0 -19
- package/lib/components/logo/DI.js +0 -20
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* `@datalayer/primer-appearance` — the appearance menu, as a reactor plugin.
|
|
7
|
+
*
|
|
8
|
+
* The control the public Datalayer header wears at its right edge: a small
|
|
9
|
+
* square showing the color mode which, hovered, opens the appearance overlay
|
|
10
|
+
* — light, dark and auto as a segmented control; one circle per theme; the
|
|
11
|
+
* chosen theme's name and description; and a "Show preview" button that
|
|
12
|
+
* unfolds a live card of it. That is {@link AppearanceMenuWithStore}, and
|
|
13
|
+
* every reactor host that wanted it wrote the same slot component around it.
|
|
14
|
+
* This plugin is that component, written once: a host lists the plugin, names
|
|
15
|
+
* a slot if the default is not `header`, and the menu is there.
|
|
16
|
+
*
|
|
17
|
+
* It depends on {@link ThemePlugin}: the menu changes the color mode, and the
|
|
18
|
+
* theme plugin is what keeps Primer's portals — a palette, a menu — in the
|
|
19
|
+
* mode chosen. Listing this plugin brings that one along.
|
|
20
|
+
*
|
|
21
|
+
* @module reactor/AppearancePlugin
|
|
22
|
+
*/
|
|
23
|
+
import { createElement } from "react";
|
|
24
|
+
import { definePlugin } from "@datalayer/reactor";
|
|
25
|
+
import { AppearanceMenuWithStore } from "../components/appearance/AppearanceMenuWithStore";
|
|
26
|
+
import { ThemePlugin } from "./ThemePlugin";
|
|
27
|
+
export const APPEARANCE_PLUGIN_NAME = "@datalayer/primer-appearance";
|
|
28
|
+
/** The id of the slot component, for a host that looks it up. */
|
|
29
|
+
export const APPEARANCE_MENU_COMPONENT_ID = "appearance-menu";
|
|
30
|
+
export const AppearancePlugin = definePlugin({
|
|
31
|
+
name: APPEARANCE_PLUGIN_NAME,
|
|
32
|
+
displayName: "Appearance",
|
|
33
|
+
description: "The color mode and theme chooser, in the header.",
|
|
34
|
+
octicon: "paintbrush",
|
|
35
|
+
emoji: "\u{1F3A8}",
|
|
36
|
+
dependencies: [ThemePlugin],
|
|
37
|
+
config: {
|
|
38
|
+
slot: "header",
|
|
39
|
+
order: 100,
|
|
40
|
+
size: 26,
|
|
41
|
+
shape: "square",
|
|
42
|
+
placement: "bottom-end",
|
|
43
|
+
showThemePreviews: true,
|
|
44
|
+
applyThemeColorMode: false,
|
|
45
|
+
},
|
|
46
|
+
build: ({ config }) => ({
|
|
47
|
+
components: [
|
|
48
|
+
{
|
|
49
|
+
id: APPEARANCE_MENU_COMPONENT_ID,
|
|
50
|
+
slot: config.slot,
|
|
51
|
+
order: config.order,
|
|
52
|
+
Component: () => createElement(AppearanceMenuWithStore, {
|
|
53
|
+
size: config.size,
|
|
54
|
+
shape: config.shape,
|
|
55
|
+
hoverOverlayPlacement: config.placement,
|
|
56
|
+
showThemePreviews: config.showThemePreviews,
|
|
57
|
+
applyThemeColorMode: config.applyThemeColorMode,
|
|
58
|
+
}),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
export default AppearancePlugin;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const THEME_PLUGIN_NAME = "@datalayer/primer-theme";
|
|
2
|
+
/** The command's id, for hosts that want to invoke or rebind it. */
|
|
3
|
+
export declare const TOGGLE_COLOR_MODE_COMMAND = "theme.toggleColorMode";
|
|
4
|
+
export declare const ThemePlugin: import("@datalayer/reactor").ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
5
|
+
export default ThemePlugin;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* `@datalayer/primer-theme` — the Primer theme, as a reactor plugin.
|
|
7
|
+
*
|
|
8
|
+
* Every reactor application that portals Primer overlays — a command palette,
|
|
9
|
+
* a menu — needs the same two lines of glue: `setupPrimerPortals()` before
|
|
10
|
+
* anything portals, and again on every theme change so the portal root's
|
|
11
|
+
* `data-color-mode` follows the application. Each host wrote them for itself
|
|
12
|
+
* (the music example at module load, the LOOP palette inside its build), and
|
|
13
|
+
* each copy was one theme-change subscription short: a palette opened after a
|
|
14
|
+
* toggle wore the mode the page started in.
|
|
15
|
+
*
|
|
16
|
+
* This plugin is that glue, written once where the theme actually lives. It
|
|
17
|
+
* sets the portal root up when it registers, follows the shared theme store
|
|
18
|
+
* and the OS scheme (for `auto`) for as long as it runs, and contributes the
|
|
19
|
+
* command the copies never had: cycle the color mode, from the palette or by
|
|
20
|
+
* keystroke.
|
|
21
|
+
*
|
|
22
|
+
* It lives beside the theme store rather than in the reactor repo because the
|
|
23
|
+
* store is the thing being followed — the reactor knows nothing of Primer,
|
|
24
|
+
* and should not learn.
|
|
25
|
+
*
|
|
26
|
+
* @module reactor/ThemePlugin
|
|
27
|
+
*/
|
|
28
|
+
import { definePlugin } from "@datalayer/reactor";
|
|
29
|
+
import { setupPrimerPortals } from "../utils/Portals";
|
|
30
|
+
import { useThemeStore } from "../theme/useThemeStore";
|
|
31
|
+
export const THEME_PLUGIN_NAME = "@datalayer/primer-theme";
|
|
32
|
+
/** The command's id, for hosts that want to invoke or rebind it. */
|
|
33
|
+
export const TOGGLE_COLOR_MODE_COMMAND = "theme.toggleColorMode";
|
|
34
|
+
export const ThemePlugin = definePlugin({
|
|
35
|
+
name: THEME_PLUGIN_NAME,
|
|
36
|
+
displayName: "Theme",
|
|
37
|
+
description: "Keeps Primer portals in the application’s color mode, and toggles it.",
|
|
38
|
+
octicon: "sun",
|
|
39
|
+
emoji: "\u{1F317}",
|
|
40
|
+
commands: [
|
|
41
|
+
{
|
|
42
|
+
id: TOGGLE_COLOR_MODE_COMMAND,
|
|
43
|
+
name: "Toggle the color mode",
|
|
44
|
+
description: "Switch between light and dark",
|
|
45
|
+
emoji: "\u{1F317}",
|
|
46
|
+
category: "Appearance",
|
|
47
|
+
// Not Mod+Alt+T: on GNOME that is "launch a terminal", grabbed by the
|
|
48
|
+
// desktop before the browser sees the key, so the command never ran.
|
|
49
|
+
keybinding: "Mod+Alt+C",
|
|
50
|
+
execute: () => {
|
|
51
|
+
// A visible change on every press. The store's own `toggleColorMode`
|
|
52
|
+
// cycles light → dark → auto, and the step onto `auto` (or off it)
|
|
53
|
+
// shows nothing when `auto` resolves to the mode already on screen —
|
|
54
|
+
// so every third press looked like a dud, and from `auto` it took
|
|
55
|
+
// two. Resolve what is showing and go to the opposite explicit mode;
|
|
56
|
+
// `auto` remains a choice for the picker.
|
|
57
|
+
const store = useThemeStore.getState();
|
|
58
|
+
const showing = store.colorMode === "auto"
|
|
59
|
+
? typeof window !== "undefined" &&
|
|
60
|
+
window.matchMedia?.("(prefers-color-scheme: dark)").matches
|
|
61
|
+
? "dark"
|
|
62
|
+
: "light"
|
|
63
|
+
: store.colorMode;
|
|
64
|
+
store.setColorMode(showing === "dark" ? "light" : "dark");
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
register: () => {
|
|
69
|
+
// Nothing to portal into on a server.
|
|
70
|
+
if (typeof document === "undefined") {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Before anything portals: the root has to exist, in the right mode,
|
|
74
|
+
// by the time the first overlay looks for it.
|
|
75
|
+
setupPrimerPortals(useThemeStore.getState().colorMode);
|
|
76
|
+
// The user changing their mind. `setupPrimerPortals` is idempotent and
|
|
77
|
+
// re-reads the theme markers, so following the store is one call.
|
|
78
|
+
const unsubscribe = useThemeStore.subscribe((state, previous) => {
|
|
79
|
+
if (state.colorMode !== previous.colorMode) {
|
|
80
|
+
setupPrimerPortals(state.colorMode);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
// The OS changing its mind, which only matters on `auto`: the store's
|
|
84
|
+
// value has not moved, but what it resolves to has.
|
|
85
|
+
const scheme = window.matchMedia("(prefers-color-scheme: dark)");
|
|
86
|
+
const followScheme = () => {
|
|
87
|
+
if (useThemeStore.getState().colorMode === "auto") {
|
|
88
|
+
setupPrimerPortals("auto");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
scheme.addEventListener("change", followScheme);
|
|
92
|
+
return () => {
|
|
93
|
+
unsubscribe();
|
|
94
|
+
scheme.removeEventListener("change", followScheme);
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
export default ThemePlugin;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reactor-facing corner of primer-addons.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT re-exported from the package's main barrel: importing
|
|
5
|
+
* anything from here pulls `@datalayer/reactor` into the bundle, and most
|
|
6
|
+
* consumers of primer-addons are pages with no reactor at all. A host that
|
|
7
|
+
* wants the plugins imports them by path:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { AppearancePlugin, ThemePlugin } from '@datalayer/primer-addons/lib/reactor';
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Three plugins. `ThemePlugin` keeps Primer's portals in the application's
|
|
14
|
+
* color mode and toggles that mode by command. `AppearancePlugin` puts the
|
|
15
|
+
* appearance menu — color mode, theme, the theme's description and a
|
|
16
|
+
* preview of it — in a slot, the header by default, and brings the first
|
|
17
|
+
* along as a dependency. `PageLayoutPlugin` arranges a host's slots as a
|
|
18
|
+
* page: the work on a centred sheet, a band above it, a side panel opened
|
|
19
|
+
* from the header — and the layout, its toggle and its signals are exported
|
|
20
|
+
* on their own for a host that wires the parts itself, as the Loop does.
|
|
21
|
+
*
|
|
22
|
+
* @module reactor
|
|
23
|
+
*/
|
|
24
|
+
export { ThemePlugin, THEME_PLUGIN_NAME, TOGGLE_COLOR_MODE_COMMAND, } from "./ThemePlugin";
|
|
25
|
+
export { AppearancePlugin, APPEARANCE_PLUGIN_NAME, APPEARANCE_MENU_COMPONENT_ID, type AppearancePluginConfig, } from "./AppearancePlugin";
|
|
26
|
+
export { PageLayoutPlugin, PAGE_LAYOUT_PLUGIN_NAME, PageLayoutSlots, type PageLayoutPluginConfig, } from "./page-layout/PageLayoutPlugin";
|
|
27
|
+
export { PageLayout, PAGE_SHEET_WIDTH, PAGE_PANEL_WIDTH, PAGE_SIZE_FORMATS, resolvePageSize, type PageLayoutProps, type PageSize, type PageSizeFormat, } from "./page-layout/PageLayout";
|
|
28
|
+
export { PagePanelToggle, type PagePanelToggleProps, } from "./page-layout/PagePanelToggle";
|
|
29
|
+
export { SlotPageLayout, SlotPanelToggle, type SlotPageLayoutProps, } from "./page-layout/SlotPageLayout";
|
|
30
|
+
export { pageLayoutPanelOpen, pageLayoutSheet, pageLayoutActivity, openPagePanel, closePagePanel, togglePagePanel, } from "./page-layout/panelState";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The reactor-facing corner of primer-addons.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately NOT re-exported from the package's main barrel: importing
|
|
9
|
+
* anything from here pulls `@datalayer/reactor` into the bundle, and most
|
|
10
|
+
* consumers of primer-addons are pages with no reactor at all. A host that
|
|
11
|
+
* wants the plugins imports them by path:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { AppearancePlugin, ThemePlugin } from '@datalayer/primer-addons/lib/reactor';
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Three plugins. `ThemePlugin` keeps Primer's portals in the application's
|
|
18
|
+
* color mode and toggles that mode by command. `AppearancePlugin` puts the
|
|
19
|
+
* appearance menu — color mode, theme, the theme's description and a
|
|
20
|
+
* preview of it — in a slot, the header by default, and brings the first
|
|
21
|
+
* along as a dependency. `PageLayoutPlugin` arranges a host's slots as a
|
|
22
|
+
* page: the work on a centred sheet, a band above it, a side panel opened
|
|
23
|
+
* from the header — and the layout, its toggle and its signals are exported
|
|
24
|
+
* on their own for a host that wires the parts itself, as the Loop does.
|
|
25
|
+
*
|
|
26
|
+
* @module reactor
|
|
27
|
+
*/
|
|
28
|
+
export { ThemePlugin, THEME_PLUGIN_NAME, TOGGLE_COLOR_MODE_COMMAND, } from "./ThemePlugin";
|
|
29
|
+
export { AppearancePlugin, APPEARANCE_PLUGIN_NAME, APPEARANCE_MENU_COMPONENT_ID, } from "./AppearancePlugin";
|
|
30
|
+
export { PageLayoutPlugin, PAGE_LAYOUT_PLUGIN_NAME, PageLayoutSlots, } from "./page-layout/PageLayoutPlugin";
|
|
31
|
+
export { PageLayout, PAGE_SHEET_WIDTH, PAGE_PANEL_WIDTH, PAGE_SIZE_FORMATS, resolvePageSize, } from "./page-layout/PageLayout";
|
|
32
|
+
export { PagePanelToggle, } from "./page-layout/PagePanelToggle";
|
|
33
|
+
export { SlotPageLayout, SlotPanelToggle, } from "./page-layout/SlotPageLayout";
|
|
34
|
+
export { pageLayoutPanelOpen, pageLayoutSheet, pageLayoutActivity, openPagePanel, closePagePanel, togglePagePanel, } from "./page-layout/panelState";
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page layout: the work on a centred sheet, like a document.
|
|
3
|
+
*
|
|
4
|
+
* A quiet canvas fills the view. On it, one sheet — the page, at a reading
|
|
5
|
+
* width, with the margins and the shadow a page has — and a band docked
|
|
6
|
+
* directly above the canvas — or, when the host asks for it, floating over
|
|
7
|
+
* the canvas as a draggable card — like the toolbar of a document
|
|
8
|
+
* application, with chips directly under it — or standing in the side panel
|
|
9
|
+
* under its content, the page bare. With no page to show, the side panel's
|
|
10
|
+
* content is the page: the same sheet, holding it, and no side panel. While
|
|
11
|
+
* something works in the page, a small line at the top of the sheet says
|
|
12
|
+
* what it is doing — "Analyst is adding a cell…" — so the change is seen
|
|
13
|
+
* where it happens. The panel is a column on the right that opens when it
|
|
14
|
+
* is wanted — on either side by `panelSide`, and by `panelMode` a column, an
|
|
15
|
+
* overlay over the page's edge or a small window in its corner; closed, the
|
|
16
|
+
* page is all there is.
|
|
17
|
+
*
|
|
18
|
+
* The sheet is a reading column by default, as tall as what is on it; asked
|
|
19
|
+
* for a paper (`pageSize`: letter, A4, or a free width and height), it takes
|
|
20
|
+
* the paper's width and is at least the paper's height.
|
|
21
|
+
*
|
|
22
|
+
* The band holds one **mount point**, and that is what gives its content its
|
|
23
|
+
* width: the same `sheetWidth` column the sheet gets, centred the same way,
|
|
24
|
+
* inside the same canvas padding. So the band and the page below it are one
|
|
25
|
+
* column with one pair of edges, and they stay one when the panel opens and
|
|
26
|
+
* narrows the canvas — because the band lives inside the page column, not
|
|
27
|
+
* across the whole view. A floating card sizes itself, which is why it never
|
|
28
|
+
* lines up with anything. It hangs at the top of the canvas, over the chips
|
|
29
|
+
* and the sheet, which start where they would with no band at all: the flow
|
|
30
|
+
* keeps no room for the card. What it covers is a drag away, and a strip of
|
|
31
|
+
* canvas held clear for it was a blank band before the page — worse than a
|
|
32
|
+
* card over the first lines.
|
|
33
|
+
*
|
|
34
|
+
* Nothing here decides what the parts do. A host wires them; this arranges
|
|
35
|
+
* them. It grew up as the Loop's page layout, where the page is a notebook or
|
|
36
|
+
* a document, the band is the composer and the panel is the conversation;
|
|
37
|
+
* the names here are the general ones.
|
|
38
|
+
*
|
|
39
|
+
* @module reactor/page-layout/PageLayout
|
|
40
|
+
*/
|
|
41
|
+
import { type JSX, type ReactNode } from "react";
|
|
42
|
+
/** A page reads best at about this width; wider and lines run too long. */
|
|
43
|
+
export declare const PAGE_SHEET_WIDTH = 920;
|
|
44
|
+
/** The side panel, when open. */
|
|
45
|
+
export declare const PAGE_PANEL_WIDTH = 400;
|
|
46
|
+
/**
|
|
47
|
+
* How the sheet is sized: `free`, or as a sheet of paper.
|
|
48
|
+
*
|
|
49
|
+
* `free` is the reading column — `PAGE_SHEET_WIDTH` wide, or the width the
|
|
50
|
+
* host gives, as tall as its content. `letter` and `a4` are the papers, at
|
|
51
|
+
* CSS's 96 dots to the inch: the sheet takes their width and is at least
|
|
52
|
+
* their height, so a short document still reads as a page rather than as a
|
|
53
|
+
* box shrunk around three lines.
|
|
54
|
+
*/
|
|
55
|
+
export type PageSizeFormat = "free" | "letter" | "a4";
|
|
56
|
+
/** The sheet's size: a format, and free width and height over it. */
|
|
57
|
+
export type PageSize = {
|
|
58
|
+
/** `free` unless said otherwise. */
|
|
59
|
+
format?: PageSizeFormat;
|
|
60
|
+
/** The sheet's width in px. Over a paper format, replaces the paper's. */
|
|
61
|
+
width?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The sheet's least height in px; content past it grows the sheet. Over a
|
|
64
|
+
* paper format, replaces the paper's. Omitted under `free`: the content's.
|
|
65
|
+
*/
|
|
66
|
+
height?: number;
|
|
67
|
+
};
|
|
68
|
+
/** The papers, in CSS px (96 to the inch): US Letter 8.5 × 11 in, A4 210 × 297 mm. */
|
|
69
|
+
export declare const PAGE_SIZE_FORMATS: Record<Exclude<PageSizeFormat, "free">, {
|
|
70
|
+
width: number;
|
|
71
|
+
height: number;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* The width and least height a `PageSize` asks for: the format's, with any
|
|
75
|
+
* free width or height over it; `sheetWidth` and the content's height when
|
|
76
|
+
* neither says.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolvePageSize(size: PageSize | undefined, sheetWidth?: number): {
|
|
79
|
+
width: number;
|
|
80
|
+
height?: number;
|
|
81
|
+
};
|
|
82
|
+
export type PageLayoutProps = {
|
|
83
|
+
/** The page: what lies on the sheet. */
|
|
84
|
+
page?: ReactNode;
|
|
85
|
+
/**
|
|
86
|
+
* Whether there is a page on screen.
|
|
87
|
+
*
|
|
88
|
+
* When false, the panel's content lies on the sheet instead, and the page
|
|
89
|
+
* is kept mounted out of sight — whatever lives in it keeps running —
|
|
90
|
+
* rather than unmounted. Defaults to whether `page` was given.
|
|
91
|
+
*/
|
|
92
|
+
hasPage?: boolean;
|
|
93
|
+
/** The side panel's content: a conversation, an inspector, a list. */
|
|
94
|
+
panel?: ReactNode;
|
|
95
|
+
/**
|
|
96
|
+
* The band above the page: a composer, a toolbar. Docked in a band at the
|
|
97
|
+
* sheet's width, or floating over the canvas, by `bandMode`. Nothing when
|
|
98
|
+
* omitted — an empty band is a strip of chrome that does nothing.
|
|
99
|
+
*/
|
|
100
|
+
band?: ReactNode;
|
|
101
|
+
/** Chips under the band, above the sheet: openers, quick actions. */
|
|
102
|
+
chips?: ReactNode;
|
|
103
|
+
/** A strip above the canvas: a picker, a row of tabs. */
|
|
104
|
+
picker?: ReactNode;
|
|
105
|
+
/** Rendered after the canvas, positioned by itself: a transient notice. */
|
|
106
|
+
transient?: ReactNode;
|
|
107
|
+
/**
|
|
108
|
+
* What is happening in the page, pinned to the sheet's top edge while set.
|
|
109
|
+
* Omitted, the layout reads {@link pageLayoutActivity}.
|
|
110
|
+
*/
|
|
111
|
+
activity?: string;
|
|
112
|
+
/**
|
|
113
|
+
* `docked` (the default): the band above the canvas, at the sheet's width.
|
|
114
|
+
* `floating`: the band's content is a draggable card at the top of the
|
|
115
|
+
* canvas, positioned by itself against this layout's root, over the chips
|
|
116
|
+
* and the sheet — which start at the top of the canvas as if there were
|
|
117
|
+
* no band; the card covers what it covers. `panel`: the band stands in the
|
|
118
|
+
* side panel, under the panel's content, with the chips above it; the
|
|
119
|
+
* page has no band over it at all, and the panel is on screen for as
|
|
120
|
+
* long as the band is in it, whatever the toggle says.
|
|
121
|
+
*/
|
|
122
|
+
bandMode?: "docked" | "floating" | "panel";
|
|
123
|
+
/**
|
|
124
|
+
* Where the panel stands, when open. `docked` (the default): a column
|
|
125
|
+
* beside the page, narrowing it. `overlay`: over the page's right edge at
|
|
126
|
+
* full height, the page untouched under it. `popup`: a small window in
|
|
127
|
+
* the page's bottom-right corner.
|
|
128
|
+
*/
|
|
129
|
+
panelMode?: "docked" | "overlay" | "popup";
|
|
130
|
+
/**
|
|
131
|
+
* Which side the panel stands on: `right` (the default), or `left`, where
|
|
132
|
+
* a navigation sidebar belongs. An overlay and a popup follow the same
|
|
133
|
+
* side, so a left panel slides in over the page's left edge.
|
|
134
|
+
*/
|
|
135
|
+
panelSide?: "left" | "right";
|
|
136
|
+
/** The sheet's width; {@link PAGE_SHEET_WIDTH} by default. */
|
|
137
|
+
sheetWidth?: number;
|
|
138
|
+
/**
|
|
139
|
+
* The sheet's size: `free` (the default) at `sheetWidth`, or a paper —
|
|
140
|
+
* `letter`, `a4` — whose width the sheet takes and whose height it is at
|
|
141
|
+
* least; a `width` or `height` given here comes before either.
|
|
142
|
+
*/
|
|
143
|
+
pageSize?: PageSize;
|
|
144
|
+
/** The panel's width when open; {@link PAGE_PANEL_WIDTH} by default. */
|
|
145
|
+
panelWidth?: number;
|
|
146
|
+
};
|
|
147
|
+
export declare function PageLayout({ page, hasPage, panel, band, chips, picker, transient, activity, bandMode, panelMode, panelSide, sheetWidth, pageSize, panelWidth, }: PageLayoutProps): JSX.Element;
|
|
148
|
+
export default PageLayout;
|