@protoyard/decks-ui 0.0.0-stage → 1.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 +172 -2
- package/dist/app/CustomSlide.svelte +42 -0
- package/dist/app/CustomSlide.svelte.d.ts +60 -0
- package/dist/app/DeckApp.svelte +527 -0
- package/dist/app/DeckApp.svelte.d.ts +41 -0
- package/dist/app/FreeBlock.svelte +66 -0
- package/dist/app/FreeBlock.svelte.d.ts +10 -0
- package/dist/app/FreeSlide.svelte +135 -0
- package/dist/app/FreeSlide.svelte.d.ts +5 -0
- package/dist/app/context.d.ts +14 -0
- package/dist/app/context.js +11 -0
- package/dist/app/fit.d.ts +39 -0
- package/dist/app/fit.js +97 -0
- package/dist/app/free-prefetch.d.ts +3 -0
- package/dist/app/free-prefetch.js +13 -0
- package/dist/app/index.d.ts +6 -0
- package/dist/app/index.js +5 -0
- package/dist/app/interactive.d.ts +3 -0
- package/dist/app/interactive.js +25 -0
- package/dist/app/renderers.d.ts +14 -0
- package/dist/app/renderers.js +49 -0
- package/dist/app/stage-deck.d.ts +40 -0
- package/dist/app/stage-deck.js +65 -0
- package/dist/debug/BlockOutline.svelte +117 -0
- package/dist/debug/BlockOutline.svelte.d.ts +12 -0
- package/dist/debug/DeckDebugPanel.svelte +205 -0
- package/dist/debug/DeckDebugPanel.svelte.d.ts +18 -0
- package/dist/debug/availability.d.ts +19 -0
- package/dist/debug/availability.js +27 -0
- package/dist/debug/format.d.ts +12 -0
- package/dist/debug/format.js +39 -0
- package/dist/debug/index.d.ts +10 -0
- package/dist/debug/index.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/layouts/CustomSlideHost.svelte +97 -0
- package/dist/layouts/CustomSlideHost.svelte.d.ts +14 -0
- package/dist/layouts/custom-slides.d.ts +28 -0
- package/dist/layouts/custom-slides.js +20 -0
- package/dist/layouts/index.d.ts +7 -0
- package/dist/layouts/index.js +7 -0
- package/dist/player.css +6 -0
- package/dist/player.css.d.ts +1 -0
- package/dist/studio/DeckStudioPanel.svelte +261 -0
- package/dist/studio/DeckStudioPanel.svelte.d.ts +8 -0
- package/dist/studio/StudioIcon.svelte +9 -0
- package/dist/studio/StudioIcon.svelte.d.ts +6 -0
- package/dist/studio/index.d.ts +26 -0
- package/dist/studio/index.js +21 -0
- package/dist/studio/studio.svelte.d.ts +565 -0
- package/dist/studio/studio.svelte.js +85 -0
- package/dist/styles.css +5 -0
- package/dist/styles.css.d.ts +1 -0
- package/package.json +106 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dailybot, Inc.
|
|
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
CHANGED
|
@@ -1,3 +1,173 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @protoyard/decks-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The deck host for Protoyard ([ADR-038](../../docs/DECISIONS.md)): `DeckApp`,
|
|
4
|
+
the one deck component the player's deck entry and generated deck prototypes
|
|
5
|
+
mount. Decks are presented by the [`@texuli/slides`](../../../texuli/packages/slides/README.md)
|
|
6
|
+
stage core (`DeckStageCore` from `@texuli/slides/stage-core`, Texuli ADR-009),
|
|
7
|
+
the stage without its default renderer tables, which a Protoyard deck never
|
|
8
|
+
uses: the fixed canvas, `#/<slide-id>/<step>`
|
|
9
|
+
routes, keys, touch, the toolbar (below the slide at the inline end), slide
|
|
10
|
+
list, overview, presenter view and window, blackout, laser, help, copy link,
|
|
11
|
+
first-visit hint, full screen, transitions and print are the stage's.
|
|
12
|
+
DeckApp adds what is Protoyard's own:
|
|
13
|
+
|
|
14
|
+
- the Protoyard deck shape, migrated to the deck model and prepared once with
|
|
15
|
+
Protoyard's block check (`prepareDeckV2`), so the stage paints it on its
|
|
16
|
+
first render without validating it again;
|
|
17
|
+
- Protoyard themes, palette seeds and font pairings (`loadTheme` through
|
|
18
|
+
`@protoyard/decks/style`), and `mode` (`light`/`dark`) as the host
|
|
19
|
+
`data-tx-mode`;
|
|
20
|
+
- free slides painted by `@protoyard/blocks-ui`, so interactive blocks keep
|
|
21
|
+
their state in the host's `stateHost`, `embed-app` mounts through the host's
|
|
22
|
+
`mountEmbed`, votes use the host's `viewerId`, and Protoyard-only blocks
|
|
23
|
+
(poll, quiz, calculator, form, flow, terminal, embed-app…) render;
|
|
24
|
+
- the generated deck's custom slides (`customSlides`);
|
|
25
|
+
- the "Debug for agents" panel (`D` and a toolbar button), Deck Studio, and the
|
|
26
|
+
print page for `?print=1` and the browser's own print (Ctrl/Cmd+P).
|
|
27
|
+
|
|
28
|
+
## Subpaths
|
|
29
|
+
|
|
30
|
+
| Import | What it provides |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| `@protoyard/decks-ui` | `fitDeckCanvas` (the engine's canvas fit) and its `DeckCanvasFit` type. |
|
|
33
|
+
| `@protoyard/decks-ui/app` | `DeckApp` and the custom slide types (`CustomSlideProps`, `CustomSlideComponent`, `CustomSlideLoader`, `CustomSlideRegistry`). |
|
|
34
|
+
| `@protoyard/decks-ui/layouts` | `CustomSlideHost`, `customSlideLoader`, `frozenCopy` and the custom slide types. The 20 catalog layouts render on the stage (`@texuli/slides/layouts`). |
|
|
35
|
+
| `@protoyard/decks-ui/studio` | Deck Studio: `createDeckStudio`, `deckStudioTab`, `prefixDeckPatch`. |
|
|
36
|
+
| `@protoyard/decks-ui/debug` | `DeckDebugPanel`, `BlockOutline`, `deckDebugAvailable`, `debugQueryOn`, `isDevBuild`, `deckFileName`, `downloadText`, `inertJson`. |
|
|
37
|
+
| `@protoyard/decks-ui/styles.css`, `./player.css` | The blocks styles (Tailwind sources) for free slides, custom slides and the debug panel. DeckApp imports `@texuli/slides/styles.css` itself. |
|
|
38
|
+
|
|
39
|
+
## DeckApp
|
|
40
|
+
|
|
41
|
+
| Prop | Default | What it does |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `deck` | required | A deck that passed `DeckSchema` |
|
|
44
|
+
| `syncHash` | `true` | Keep `#/<slide-id>/<step>` in the URL and follow it |
|
|
45
|
+
| `autofocus` | `true` | Focus the active slide on mount |
|
|
46
|
+
| `namespace` | `deck` | Presenter channel, view transitions and the first-visit hint |
|
|
47
|
+
| `mode` | `light` | The deck theme's mode (decks default to light for stable exports) |
|
|
48
|
+
| `fit` | `viewport` | `viewport` takes the app height (`h-app`); `container` fills a sized parent |
|
|
49
|
+
| `debug` | `auto` | The debug panel: `auto` in dev builds or with `?debug=1`, `on`, `off` |
|
|
50
|
+
| `debugSource` | `null` | Where the deck came from, for the agent reference |
|
|
51
|
+
| `customSlides` | — | A generated deck's `src/custom-slides.ts` registry |
|
|
52
|
+
| `resolveAvatar` | — | Library avatar id → URL (`avatarUrl` from `@protoyard/renderer-svelte`) |
|
|
53
|
+
|
|
54
|
+
The wrapper keeps `data-py-deck-app`, `data-slide-id` and `data-slide-step`
|
|
55
|
+
(they follow the stage's controller, including a deep link's first position),
|
|
56
|
+
`data-presenter`, `data-py-deck-theme`, `data-py-deck-mode` and
|
|
57
|
+
`data-py-deck-motion` for devtools and e2e. The stage uses the `developer` URL
|
|
58
|
+
tier: every deck reaching DeckApp passed Protoyard's stricter offline media
|
|
59
|
+
policy, which allows bounded `data:` images the untrusted tier refuses. A
|
|
60
|
+
followed hash past a slide's last step is rewritten to that step.
|
|
61
|
+
|
|
62
|
+
### Free slides
|
|
63
|
+
|
|
64
|
+
The stage validates free-slide blocks with `@texuli/blocks`, which does not
|
|
65
|
+
know Protoyard's block vocabulary, so DeckApp hands each free slide to the
|
|
66
|
+
stage as a host (`custom`) slide with the same step count (its own step
|
|
67
|
+
labels, then "Step n") and paints the original blocks with
|
|
68
|
+
`@protoyard/blocks-ui` (`app/FreeSlide.svelte`). Reveals use the stage's step
|
|
69
|
+
machinery (`createDeckStepContext` over the model's step table of the
|
|
70
|
+
original slide), so fragments carry `data-tx-deck-fragment` and animate with
|
|
71
|
+
the stage's styles; code highlights move per step. A leading unstepped
|
|
72
|
+
heading is the slide title; the blocks zoom down to fit the canvas.
|
|
73
|
+
The stage's `--tx-*` theme tokens feed Protoyard's blocks inside the slide, so
|
|
74
|
+
blocks follow the deck theme and the background's text color.
|
|
75
|
+
|
|
76
|
+
### Custom slides
|
|
77
|
+
|
|
78
|
+
`layout: "custom"` slides run the generated deck's own component
|
|
79
|
+
(`CustomSlideHost`): `{ slide, step, stepCount, data }` as frozen copies,
|
|
80
|
+
errors kept on the slide, clicks never advance the deck. The player (no
|
|
81
|
+
registry) and the stage's thumbnails, presenter previews and print show a
|
|
82
|
+
labelled card and never run owned code.
|
|
83
|
+
|
|
84
|
+
### Keyboard shortcuts
|
|
85
|
+
|
|
86
|
+
Generated from `DECK_KEY_BINDINGS` (the engine's registry, which the stage's
|
|
87
|
+
help dialog also reads). With the debug panel available, `D` toggles it and
|
|
88
|
+
`Esc` closes it first.
|
|
89
|
+
|
|
90
|
+
<!-- key-bindings:start (generated by packages/decks/tests/readme-sync.test.ts) -->
|
|
91
|
+
| Keys | Action | What it does |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `←`, `↑`, `Page Up`, `Shift + Space`, `Backspace` | `prev` | Previous step or slide |
|
|
94
|
+
| `→`, `↓`, `Page Down`, `Space`, `Enter` | `next` | Next step or slide |
|
|
95
|
+
| `Home` | `first` | First slide |
|
|
96
|
+
| `End` | `last` | Last slide |
|
|
97
|
+
| `O`, `Esc` | `overview` | Overview of all slides |
|
|
98
|
+
| `F` | `fullscreen` | Full screen |
|
|
99
|
+
| `Esc` | `fullscreen-exit` | Leave full screen |
|
|
100
|
+
| `S`, `P` | `presenter` | Presenter view |
|
|
101
|
+
| `B`, `.`, `Esc` | `blackout` | Black out the screen |
|
|
102
|
+
| `L`, `Esc` | `laser` | Laser pointer |
|
|
103
|
+
| `Ctrl + P`, `⌘ + P` | `print` | Print, one slide per page |
|
|
104
|
+
| `?`, `Esc` | `help` | Controls and shortcuts |
|
|
105
|
+
<!-- key-bindings:end -->
|
|
106
|
+
|
|
107
|
+
### Debug for agents (`D`)
|
|
108
|
+
|
|
109
|
+
In dev builds, with `?debug=1` or `debug="on"`, the stage's toolbar gains a
|
|
110
|
+
"Debug for agents" button (`data-py-deck-tool="debug"`) as its last group,
|
|
111
|
+
"More tools" (the stage's `tools` snippet), and `D` toggles the
|
|
112
|
+
panel (`data-py-deck-debug`): the slide record, its checks, outlines, and
|
|
113
|
+
copy/download actions. It loads on its own chunk (under 12.4 KB gzip,
|
|
114
|
+
`tests/debug-panel.test.ts`).
|
|
115
|
+
|
|
116
|
+
## Print
|
|
117
|
+
|
|
118
|
+
The stage's Print button opens `?print=1`, where DeckApp renders the stage's
|
|
119
|
+
print view (`DeckPrintViewCore` from `@texuli/slides/export-core`, painted
|
|
120
|
+
with DeckApp's own renderer tables): one page per
|
|
121
|
+
visible slide, notes with `¬es=1`. The browser's own print (Ctrl/Cmd+P)
|
|
122
|
+
mounts the same view for paper: its code is preloaded while the browser is
|
|
123
|
+
idle after the deck opens (`preloadDeckPrintViewCore`), and the view is mounted on
|
|
124
|
+
the first print. That first print captures the page before the view has
|
|
125
|
+
settled its themes, images and fonts, so it prints the current slide and says
|
|
126
|
+
so; every later print has all the slides. PPTX export is available from `@texuli/slides/export`; no
|
|
127
|
+
Protoyard UI calls it yet.
|
|
128
|
+
|
|
129
|
+
## Deck Studio
|
|
130
|
+
|
|
131
|
+
A lazy DevTools tab that edits the deck style and the current slide with a
|
|
132
|
+
live preview and exports RFC 6902 patches (`@protoyard/decks/patch`).
|
|
133
|
+
|
|
134
|
+
## Measured numbers
|
|
135
|
+
|
|
136
|
+
`tests/bundle-size.test.ts` builds the `./app` entry in production
|
|
137
|
+
(2026-10-31, npm Texuli 0.10.0): 105,816 B gzip initial JavaScript (cap
|
|
138
|
+
111,657 B), 9,404 B first-screen CSS (cap 10,481 B) and 57,011 B of all
|
|
139
|
+
emitted CSS (cap 88,094 B). The print view comes from
|
|
140
|
+
`@texuli/slides/export-core` (G105), so the build no longer emits the stage's
|
|
141
|
+
default component registry that decks never load (86,765 B of all emitted CSS
|
|
142
|
+
before, on the same Texuli).
|
|
143
|
+
The debug panel chunk is 11,179 B gzip.
|
|
144
|
+
|
|
145
|
+
## Known limits
|
|
146
|
+
|
|
147
|
+
- Free slides cannot use the deck model's masters, `math` blocks or component
|
|
148
|
+
items; component slides are not part of Protoyard's deck shape yet.
|
|
149
|
+
- The stage always installs its default component registry, so its lazy
|
|
150
|
+
painter chunks and CSS are emitted into every deck build.
|
|
151
|
+
- Layout strings for assistive tech (comparison "Yes"/"No", chart table
|
|
152
|
+
caption) are English only (the stage's limit).
|
|
153
|
+
|
|
154
|
+
## Install in a workspace prototype
|
|
155
|
+
|
|
156
|
+
Add `"@protoyard/decks-ui": "workspace:*"` to the prototype dependencies. Then
|
|
157
|
+
import the styles after Tailwind and the theme/UI styles:
|
|
158
|
+
|
|
159
|
+
```css
|
|
160
|
+
@import '@protoyard/decks-ui/styles.css';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Tests
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pnpm vitest run packages/decks-ui
|
|
167
|
+
pnpm vitest run packages/decks-ui/tests/deck-app.test.ts
|
|
168
|
+
pnpm vitest run packages/decks-ui/tests/fragments.test.ts
|
|
169
|
+
pnpm vitest run packages/decks-ui/tests/custom-slides.test.ts
|
|
170
|
+
pnpm vitest run packages/decks-ui/tests/bundle-size.test.ts
|
|
171
|
+
pnpm vitest run packages/decks/tests/readme-sync.test.ts # this README's keyboard table
|
|
172
|
+
pnpm --filter @protoyard/decks-ui typecheck
|
|
173
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CustomSlide as Slide } from '@protoyard/decks/schema';
|
|
3
|
+
import type { CustomSlide as CustomSlideModel } from '@texuli/deck/model';
|
|
4
|
+
import { type DeckSlideRendererProps, getDeckStepContext } from '@texuli/slides/stage-core';
|
|
5
|
+
import CustomSlideHost from '../layouts/CustomSlideHost.svelte';
|
|
6
|
+
import { getDeckHostContext } from './context.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A `layout: "custom"` slide on the `@texuli/slides` stage: the generated
|
|
10
|
+
* deck's own component (DeckApp's `customSlides`), or a labelled card in the
|
|
11
|
+
* player. Overview thumbnails, presenter previews and print show the card and
|
|
12
|
+
* never run owned code (the stage paints them with the same renderers, so
|
|
13
|
+
* the slide checks where it was mounted).
|
|
14
|
+
*/
|
|
15
|
+
let { slide, context }: DeckSlideRendererProps<CustomSlideModel> = $props();
|
|
16
|
+
const host = getDeckHostContext();
|
|
17
|
+
const fromContext = getDeckStepContext();
|
|
18
|
+
const step = $derived(fromContext ?? context.step);
|
|
19
|
+
/** Unknown until mounted; a preview or print page never turns live. */
|
|
20
|
+
let live = $state(false);
|
|
21
|
+
|
|
22
|
+
function placement(node: HTMLElement): void {
|
|
23
|
+
live = node.closest('[data-tx-deck-preview], .tx-deck-print-view') === null;
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div class="py-deck-custom absolute inset-0 overflow-hidden" {@attach placement}>
|
|
28
|
+
<CustomSlideHost
|
|
29
|
+
slide={slide as unknown as Slide}
|
|
30
|
+
step={step.step}
|
|
31
|
+
stepCount={step.count}
|
|
32
|
+
registry={host.customSlides}
|
|
33
|
+
{live}
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
/* The deck's radius choice reaches the custom slide's Texuli components (see FreeSlide). */
|
|
39
|
+
.py-deck-custom {
|
|
40
|
+
--tx-radius: var(--tx-deck-radius);
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type DeckSlideRendererProps } from '@texuli/slides/stage-core';
|
|
2
|
+
declare const CustomSlide: import("svelte").Component<DeckSlideRendererProps<{
|
|
3
|
+
layout: "custom";
|
|
4
|
+
props: {
|
|
5
|
+
component: string;
|
|
6
|
+
data?: string | number | boolean | import("@texuli/deck").JsonValue[] | {
|
|
7
|
+
[key: string]: import("@texuli/deck").JsonValue;
|
|
8
|
+
} | null | undefined;
|
|
9
|
+
};
|
|
10
|
+
id: string;
|
|
11
|
+
title?: string | undefined;
|
|
12
|
+
notes?: string | undefined;
|
|
13
|
+
hidden?: boolean | undefined;
|
|
14
|
+
background?: "solid-color" | "solid-surface" | "solid-primary" | "solid-accent" | "solid-muted" | "solid-inverse" | "gradient-brand" | "gradient-dusk" | "gradient-dawn" | "gradient-forest" | "gradient-mist" | "pattern-dots" | "pattern-grid" | {
|
|
15
|
+
kind: "solid";
|
|
16
|
+
token?: "background" | "accent" | "surface" | "primary" | "muted" | "inverse" | undefined;
|
|
17
|
+
color?: string | undefined;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "gradient";
|
|
20
|
+
gradient: "brand" | "dusk" | "dawn" | "forest" | "mist";
|
|
21
|
+
angle?: number | undefined;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "pattern";
|
|
24
|
+
pattern: "dots" | "grid";
|
|
25
|
+
} | {
|
|
26
|
+
kind: "image" | "image-full";
|
|
27
|
+
src: string;
|
|
28
|
+
tone?: "dark" | "light" | undefined;
|
|
29
|
+
overlay?: number | undefined;
|
|
30
|
+
position?: "center" | "top" | "bottom" | "left" | "right" | undefined;
|
|
31
|
+
alt?: string | undefined;
|
|
32
|
+
fit?: "cover" | "contain" | undefined;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "video" | "video-full";
|
|
35
|
+
src: string;
|
|
36
|
+
tone?: "dark" | "light" | undefined;
|
|
37
|
+
overlay?: number | undefined;
|
|
38
|
+
position?: "center" | "top" | "bottom" | "left" | "right" | undefined;
|
|
39
|
+
poster?: string | undefined;
|
|
40
|
+
} | undefined;
|
|
41
|
+
transition?: "fade-up" | "fade" | "none" | "slide" | "zoom" | "morph" | undefined;
|
|
42
|
+
theme?: string | {
|
|
43
|
+
id: string;
|
|
44
|
+
kind: "catalog";
|
|
45
|
+
mode?: "dark" | "light" | "high-contrast" | "system" | undefined;
|
|
46
|
+
} | {
|
|
47
|
+
theme: string | number | boolean | import("@texuli/deck").JsonValue[] | {
|
|
48
|
+
[key: string]: import("@texuli/deck").JsonValue;
|
|
49
|
+
} | null;
|
|
50
|
+
kind: "embedded";
|
|
51
|
+
mode?: "dark" | "light" | "high-contrast" | "system" | undefined;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "seed";
|
|
54
|
+
seed: number;
|
|
55
|
+
mode?: "dark" | "light" | "high-contrast" | "system" | undefined;
|
|
56
|
+
} | undefined;
|
|
57
|
+
steps?: string[] | undefined;
|
|
58
|
+
}>, {}, "">;
|
|
59
|
+
type CustomSlide = ReturnType<typeof CustomSlide>;
|
|
60
|
+
export default CustomSlide;
|