rlz-web-slides 0.1.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/LICENSE +21 -0
- package/README.md +157 -0
- package/lib/components/DrawingLayer.d.ts +2 -0
- package/lib/components/Panel.d.ts +12 -0
- package/lib/components/Slide.d.ts +9 -0
- package/lib/components/SlideNumber.d.ts +6 -0
- package/lib/index.js +8088 -0
- package/lib/player/Presentation.d.ts +10 -0
- package/lib/player/SlideContext.d.ts +11 -0
- package/lib/public-api.d.ts +7 -0
- package/lib/slides/DecoratedSlide.d.ts +12 -0
- package/lib/theme.d.ts +98 -0
- package/package.json +80 -0
- package/scripts/build-slides.d.mts +17 -0
- package/scripts/build-slides.mjs +165 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dmitry Maslennikov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Web Slides
|
|
2
|
+
|
|
3
|
+
A small set of React components for composing slides: a resolved theme, an embedded and fullscreen player, and flexible primitives. Demo slides live in `src/examples` and are used by the local Vite documentation.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install rlz-web-slides
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
React, React DOM, and Emotion are peer dependencies and are usually already present in a React application.
|
|
12
|
+
|
|
13
|
+
## Develop
|
|
14
|
+
|
|
15
|
+
Development requires Node.js 22.12+ and npm.
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install
|
|
19
|
+
npm start # documentation with a live demo
|
|
20
|
+
npm run dev # same as above
|
|
21
|
+
npm run demo # standalone presentation at /demo.html
|
|
22
|
+
npm run build # production site in dist/
|
|
23
|
+
npm test # library tests
|
|
24
|
+
npm run lint # Oxlint and formatting checks
|
|
25
|
+
npm run format # format source files
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Documentation is available at `/`; the standalone demo is at `/demo.html`. Use the player button or F to enter the native Fullscreen API. Browsers do not allow fullscreen to start on page load.
|
|
29
|
+
|
|
30
|
+
## GitHub Pages
|
|
31
|
+
|
|
32
|
+
The [`.github/workflows/deploy-pages.yml`](.github/workflows/deploy-pages.yml) workflow deploys the built documentation on pushes to `main`. After its first run, open **Settings → Pages** in the GitHub repository and choose **GitHub Actions** as the publishing source. The site will be available at `https://<owner>.github.io/<repository>/`.
|
|
33
|
+
|
|
34
|
+
## Use
|
|
35
|
+
|
|
36
|
+
Consumer applications import from `rlz-web-slides`. Enable the Emotion JSX runtime in `tsconfig.json` to use the `css` prop:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"compilerOptions": {
|
|
41
|
+
"jsx": "react-jsx",
|
|
42
|
+
"jsxImportSource": "@emotion/react"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import {
|
|
49
|
+
DecoratedSlide,
|
|
50
|
+
Presentation,
|
|
51
|
+
SlideNumber,
|
|
52
|
+
SlidesThemeProvider
|
|
53
|
+
} from 'rlz-web-slides'
|
|
54
|
+
|
|
55
|
+
const slides = [
|
|
56
|
+
<DecoratedSlide
|
|
57
|
+
headerLeft="My project"
|
|
58
|
+
footerLeft="September 2026"
|
|
59
|
+
footerRight={<SlideNumber />}
|
|
60
|
+
>
|
|
61
|
+
<h1>Start with the main idea.</h1>
|
|
62
|
+
<p>One thought per slide.</p>
|
|
63
|
+
</DecoratedSlide>
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
export function App() {
|
|
67
|
+
return (
|
|
68
|
+
<SlidesThemeProvider theme={{ colors: { 'accent-1': '#b8d7fa' } }}>
|
|
69
|
+
<Presentation slides={slides} />
|
|
70
|
+
</SlidesThemeProvider>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Player
|
|
76
|
+
|
|
77
|
+
`Presentation` accepts `slides: readonly ReactNode[]`. `embedded` is the default mode; `fullscreen` fills the browser window. In native fullscreen, the controls hide and slides use the entire screen. `initialSlide`, `onSlideChange(index)`, and `controls` set the initial index, receive slide changes, and configure the controls.
|
|
78
|
+
|
|
79
|
+
The player preserves the canvas aspect ratio with `ResizeObserver`. ← / →, Space, PageUp / PageDown, and Home / End work only in the focused player; inputs and editable elements keep their keyboard behavior. F enters native fullscreen and Esc exits it. Inactive slides stay mounted but are removed from focus navigation and the accessibility tree.
|
|
80
|
+
|
|
81
|
+
### Components
|
|
82
|
+
|
|
83
|
+
`Slide`, `DecoratedSlide`, and `Panel` accept `className` and Emotion `css`; `SlideNumber` accepts `css`. External styles take precedence. The library does not modify `body`, global scrolling, or a page reset.
|
|
84
|
+
|
|
85
|
+
| Component | Purpose |
|
|
86
|
+
| ---------------- | ----------------------------------------------------------------------------------- |
|
|
87
|
+
| `Slide` | The themed canvas, without padding or utility areas |
|
|
88
|
+
| `DecoratedSlide` | A `Slide` with `headerLeft`, `headerRight`, `footerLeft`, and `footerRight` slots |
|
|
89
|
+
| `Panel` | A themed surface with a background, padding, corner radius, and configurable shadow |
|
|
90
|
+
| `SlideNumber` | The current slide number and total from `Presentation` context |
|
|
91
|
+
|
|
92
|
+
`DecoratedSlide` keeps headers and footers in normal flex flow while its central area fills the remaining height. Slots accept strings or arbitrary React nodes. Pass `null` to both slots of an area to omit it.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<DecoratedSlide
|
|
96
|
+
headerLeft="Team"
|
|
97
|
+
headerRight="Strategy"
|
|
98
|
+
footerLeft="Internal document"
|
|
99
|
+
footerRight={<SlideNumber css={{ fontWeight: 700 }} />}
|
|
100
|
+
>
|
|
101
|
+
<h1>The main idea</h1>
|
|
102
|
+
</DecoratedSlide>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Drawing on a slide
|
|
106
|
+
|
|
107
|
+
Pass `drawing` to `Slide` or `DecoratedSlide` to show drawing controls at the top center. Annotations are local to the browser and tied to that slide instance: they do not modify children or appear in HTML export. The controls include an opaque pen, translucent highlighter, seven contrasting colors, a large eraser, and clear all. “Blank canvas” replaces the slide with a white surface; “Over slide” lightly dims the original slide.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<DecoratedSlide drawing headerLeft="Walkthrough">
|
|
111
|
+
<h1>Mark up important details while you present</h1>
|
|
112
|
+
</DecoratedSlide>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Theme
|
|
116
|
+
|
|
117
|
+
`SlidesThemeProvider` accepts a fully optional `SlidesThemeInput`. `useSlidesTheme()` returns a resolved `SlidesTheme` and also works without a provider. `resolveSlidesTheme(input)` returns the same result outside React.
|
|
118
|
+
|
|
119
|
+
Nested providers inherit overrides. The palette has three accents: `accent-1`, `accent-2`, and `accent-3`, available as `theme.colors['accent-1']` and so on. `light` and `dark` define the base surface colors, while `textLight` and `textDark` define their text colors. `colord` derives shades and `culori` determines contrast, including CSS OKLCH. CSS variables use compatible `color-mix()` output.
|
|
120
|
+
|
|
121
|
+
`theme.backgrounds` is one shared generator set for slides, panels, and custom surfaces. It provides `solid(color?)`, `gradient(color?)`, `texture({ base, dot, size })`, `aurora({ base, lowerLeft, upperRight, center })`, `mesh({ base, colors })`, `grid({ base, line, size })`, and `spotlight({ base, light, position })`. The option objects let visual treatments control their independent colors and geometry rather than reducing every background to one color.
|
|
122
|
+
|
|
123
|
+
`Panel` has a light surface by default. Pass a background generator through Emotion `css` to change it. It also supports `shadow` (`'low'` by default, `'medium'`, `'high'`, or `false`) and `padding`; when neither the prop nor `css` sets padding, it uses `theme.spacings.half`. The theme provides `theme.shadows.low`, `theme.shadows.medium`, and `theme.shadows.high`.
|
|
124
|
+
|
|
125
|
+
Alongside base `theme.spacing` and `theme.radius`, the resolved theme provides `theme.spacings.tight`, `compact`, `half`, `comfortable`, `base`, `double` and `theme.radii.quarter`, `half`, `base`, `double`. These values are recalculated when a base value changes, so components need not multiply spacing or radii manually.
|
|
126
|
+
|
|
127
|
+
Every background factory adds a contrasting `color` with its `backgroundColor`. Pass the result to `css` to override a background; an explicitly supplied external `color` always takes precedence.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { Panel, Slide, useSlidesTheme } from 'rlz-web-slides'
|
|
131
|
+
import { colord } from 'colord'
|
|
132
|
+
|
|
133
|
+
function ResultSlide() {
|
|
134
|
+
const theme = useSlidesTheme()
|
|
135
|
+
const panelColor = colord(theme.colors['accent-1']).lighten(0.16).toHex()
|
|
136
|
+
return (
|
|
137
|
+
<Slide css={theme.backgrounds.gradient('accent-2')}>
|
|
138
|
+
<Panel css={theme.backgrounds.solid(panelColor)}>
|
|
139
|
+
<h2>Result</h2>
|
|
140
|
+
</Panel>
|
|
141
|
+
</Slide>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Structure
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
src/theme.tsx SlidesThemeProvider, useSlidesTheme, resolveSlidesTheme
|
|
150
|
+
src/components/ Slide, Panel, and SlideNumber
|
|
151
|
+
src/player/ Presentation and its contexts
|
|
152
|
+
src/slides/ DecoratedSlide
|
|
153
|
+
src/examples/ Demo slides
|
|
154
|
+
src/docs/ One-page documentation
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The former positioning primitives (`Box`, `Row`, `Column`, `Text`, `Image`, `NumberedList`) and the `TopBottom`, `TwoColumns`, `Sidebar`, and `TwoPanels` templates have been removed. Compose custom layouts with ordinary HTML elements and Emotion `css` inside `Slide` or `DecoratedSlide`.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Interpolation, Theme as EmotionTheme } from '@emotion/react';
|
|
2
|
+
import type { CSSProperties, HTMLAttributes } from 'react';
|
|
3
|
+
import { type ShadowLevel } from '../theme';
|
|
4
|
+
export interface PanelProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Shadow intensity, or false to render the panel without a shadow. */
|
|
6
|
+
shadow?: ShadowLevel | false;
|
|
7
|
+
/** Inner spacing. Defaults to 65% of the theme spacing. */
|
|
8
|
+
padding?: CSSProperties['padding'];
|
|
9
|
+
css?: Interpolation<EmotionTheme>;
|
|
10
|
+
}
|
|
11
|
+
/** A surface that can be composed inside any slide layout. Emotion forwards css as className. */
|
|
12
|
+
export declare function Panel({ children, shadow, padding, css, ...props }: PanelProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
import type { Interpolation, Theme as EmotionTheme } from '@emotion/react';
|
|
3
|
+
export interface SlideProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
css?: Interpolation<EmotionTheme>;
|
|
5
|
+
/** Shows controls for local, stylus-friendly annotations. */
|
|
6
|
+
drawing?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** A theme-aware canvas without padding or content-specific regions. */
|
|
9
|
+
export declare function Slide({ children, css, drawing, ...props }: SlideProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Interpolation, Theme as EmotionTheme } from '@emotion/react';
|
|
2
|
+
export type SlideNumberProps = {
|
|
3
|
+
css?: Interpolation<EmotionTheme>;
|
|
4
|
+
};
|
|
5
|
+
/** A presentation-independent slide counter with overridable slide-relative position. */
|
|
6
|
+
export declare function SlideNumber({ css }: SlideNumberProps): import("@emotion/react/jsx-runtime").JSX.Element;
|