payload-plugin-decks 1.0.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.
Files changed (48) hide show
  1. package/README.md +205 -0
  2. package/dist/blocks/decks/config.d.ts +2 -0
  3. package/dist/blocks/decks/config.js +148 -0
  4. package/dist/blocks/decks/config.js.map +1 -0
  5. package/dist/blocks/decks/index.d.ts +4 -0
  6. package/dist/blocks/decks/index.js +6 -0
  7. package/dist/blocks/decks/index.js.map +1 -0
  8. package/dist/components/decks/DecksBlock.d.ts +5 -0
  9. package/dist/components/decks/DecksBlock.js +104 -0
  10. package/dist/components/decks/DecksBlock.js.map +1 -0
  11. package/dist/components/decks/DecksComposition.d.ts +9 -0
  12. package/dist/components/decks/DecksComposition.js +94 -0
  13. package/dist/components/decks/DecksComposition.js.map +1 -0
  14. package/dist/components/decks/SnapContainer.d.ts +6 -0
  15. package/dist/components/decks/SnapContainer.js +61 -0
  16. package/dist/components/decks/SnapContainer.js.map +1 -0
  17. package/dist/components/decks/styles.css +167 -0
  18. package/dist/components/decks/useDecksSnap.d.ts +8 -0
  19. package/dist/components/decks/useDecksSnap.js +101 -0
  20. package/dist/components/decks/useDecksSnap.js.map +1 -0
  21. package/dist/decks/install.d.ts +16 -0
  22. package/dist/decks/install.js +36 -0
  23. package/dist/decks/install.js.map +1 -0
  24. package/dist/decks/install.spec.d.ts +1 -0
  25. package/dist/decks/install.spec.js +65 -0
  26. package/dist/decks/install.spec.js.map +1 -0
  27. package/dist/decks/model.d.ts +48 -0
  28. package/dist/decks/model.js +36 -0
  29. package/dist/decks/model.js.map +1 -0
  30. package/dist/decks/model.spec.d.ts +1 -0
  31. package/dist/decks/model.spec.js +55 -0
  32. package/dist/decks/model.spec.js.map +1 -0
  33. package/dist/decks/schema.d.ts +59 -0
  34. package/dist/decks/schema.js +75 -0
  35. package/dist/decks/schema.js.map +1 -0
  36. package/dist/decks/timeline.d.ts +37 -0
  37. package/dist/decks/timeline.js +205 -0
  38. package/dist/decks/timeline.js.map +1 -0
  39. package/dist/decks/timeline.spec.d.ts +1 -0
  40. package/dist/decks/timeline.spec.js +75 -0
  41. package/dist/decks/timeline.spec.js.map +1 -0
  42. package/dist/exports/client.d.ts +1 -0
  43. package/dist/exports/client.js +3 -0
  44. package/dist/exports/client.js.map +1 -0
  45. package/dist/index.d.ts +7 -0
  46. package/dist/index.js +9 -0
  47. package/dist/index.js.map +1 -0
  48. package/package.json +135 -0
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # payload-plugin-decks
2
+
3
+ `payload-plugin-decks` adds reusable deck blocks to Payload collections. Today it ships a `decks` block: a slide-based, Remotion-powered deck with background images, headlines, subtext, text positioning, transitions, autoplay, looping, and optional playback controls.
4
+
5
+ The plugin adds the editing fields to Payload. Your frontend decides where and how to render the saved deck blocks.
6
+
7
+ ## Requirements
8
+
9
+ - Payload `^3.84.0`
10
+ - React / Next.js frontend capable of rendering client components
11
+ - A Payload upload collection with slug `media`
12
+
13
+ The decks block's image field is currently configured with `relationTo: 'media'`, so your Payload app must define a `media` collection.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ pnpm add payload-plugin-decks
19
+ ```
20
+
21
+ The package includes its Remotion runtime dependencies:
22
+
23
+ - `@remotion/player`
24
+ - `remotion`
25
+
26
+ ## Configure Payload
27
+
28
+ Add `payloadDecks` to your Payload config and choose the collections that should receive the decks field.
29
+
30
+ ```ts
31
+ import { buildConfig } from 'payload'
32
+ import { payloadDecks } from 'payload-plugin-decks'
33
+
34
+ export default buildConfig({
35
+ collections: [
36
+ {
37
+ slug: 'pages',
38
+ fields: [
39
+ // your fields
40
+ ],
41
+ },
42
+ {
43
+ slug: 'media',
44
+ upload: true,
45
+ fields: [],
46
+ },
47
+ ],
48
+ plugins: [
49
+ payloadDecks({
50
+ collections: {
51
+ pages: true,
52
+ },
53
+ }),
54
+ ],
55
+ })
56
+ ```
57
+
58
+ This adds a `decks` blocks field to the configured collection. Editors can add one or more `decks` blocks inside that field.
59
+
60
+ ## Options
61
+
62
+ ```ts
63
+ type PayloadDecksConfig = {
64
+ collections?: Partial<Record<CollectionSlug, true>>
65
+ disabled?: boolean
66
+ fieldName?: string
67
+ }
68
+ ```
69
+
70
+ | Option | Default | Description |
71
+ | ------------- | ----------- | ------------------------------------------------------------------- |
72
+ | `collections` | `undefined` | Collections that should receive the decks blocks field. |
73
+ | `fieldName` | `'decks'` | Name of the blocks field added to each configured collection. |
74
+ | `disabled` | `false` | Leaves schema additions in place but skips runtime plugin behavior. |
75
+
76
+ ### Custom field name
77
+
78
+ ```ts
79
+ payloadDecks({
80
+ collections: {
81
+ pages: true,
82
+ posts: true,
83
+ },
84
+ fieldName: 'heroDecks',
85
+ })
86
+ ```
87
+
88
+ ## Alternative: add the block to an existing blocks field
89
+
90
+ If your collection already has a `blocks` field (for example a page `layout` builder), you usually do **not** want the `payloadDecks()` plugin — it would add a second, separate `decks` field disconnected from your existing one. Instead, import the `DecksBlock` block config and add it to the field you already manage, alongside your other blocks:
91
+
92
+ ```ts
93
+ import { DecksBlock } from 'payload-plugin-decks'
94
+
95
+ export const Pages = {
96
+ slug: 'pages',
97
+ fields: [
98
+ {
99
+ name: 'layout',
100
+ type: 'blocks',
101
+ blocks: [
102
+ // ...your existing blocks
103
+ DecksBlock,
104
+ ],
105
+ },
106
+ ],
107
+ }
108
+ ```
109
+
110
+ Editors then pick **Decks** as one block among the others in that field, and you render it from the same array using the client renderer (see [Render Decks](#render-decks)).
111
+
112
+ Use `payloadDecks()` when you want a brand-new, dedicated decks field added for you; use the `DecksBlock` config directly when decks should be one choice within a blocks field you already have.
113
+
114
+ ## Render Decks
115
+
116
+ The plugin does not automatically render decks in your frontend. Render the blocks from the field you added, usually inside your existing page or post block renderer.
117
+
118
+ ```tsx
119
+ import dynamic from 'next/dynamic'
120
+ import type { DecksBlockProps } from 'payload-plugin-decks'
121
+
122
+ const DecksBlock = dynamic(
123
+ () => import('payload-plugin-decks/client').then((mod) => mod.DecksBlock),
124
+ { ssr: false },
125
+ )
126
+
127
+ type DecksBlockData = DecksBlockProps & {
128
+ blockType: 'decks'
129
+ id?: string
130
+ }
131
+
132
+ type DeckBlock = DecksBlockData
133
+
134
+ export function DecksRenderer({ decks = [] }: { decks?: DeckBlock[] }) {
135
+ return (
136
+ <>
137
+ {decks.map((deck, index) => {
138
+ switch (deck.blockType) {
139
+ case 'decks':
140
+ return <DecksBlock key={deck.id || index} {...deck} />
141
+ default:
142
+ return null
143
+ }
144
+ })}
145
+ </>
146
+ )
147
+ }
148
+ ```
149
+
150
+ If you generate Payload types, prefer using the generated collection type for your renderer props.
151
+
152
+ ## Decks Fields
153
+
154
+ Each `decks` block supports:
155
+
156
+ | Field | Description |
157
+ | -------------------- | ----------------------------------------------------- |
158
+ | `title` | Optional internal reference for editors. |
159
+ | `fps` | Video frame rate. Defaults to `30`. |
160
+ | `durationPerSlide` | Seconds each slide is displayed. Defaults to `3`. |
161
+ | `transitionDuration` | Fade transition duration in frames. Defaults to `15`. |
162
+ | `backgroundColor` | Composition background color. Defaults to `#000000`. |
163
+ | `autoPlay` | Starts playback automatically. Defaults to `true`. |
164
+ | `loop` | Loops playback. Defaults to `true`. |
165
+ | `showControls` | Shows Remotion player controls. Defaults to `false`. |
166
+ | `slides` | Ordered slide array. Requires at least one slide. |
167
+
168
+ Each slide supports:
169
+
170
+ | Field | Description |
171
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
172
+ | `image` | Optional background image from the `media` collection. |
173
+ | `headline` | Optional headline text. |
174
+ | `subtext` | Optional supporting text. |
175
+ | `textColor` | Text color. Defaults to `#ffffff`. |
176
+ | `textPosition` | One of `top-left`, `top-center`, `top-right`, `center-left`, `center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`. |
177
+ | `animationType` | One of `fadeIn`, `slideUp`, `slideDown`, `scaleIn`, `none`. |
178
+ | `imageZoom` | Enables a slow Ken Burns-style image zoom. Defaults to `true`. |
179
+
180
+ ## Exports
181
+
182
+ ```ts
183
+ import { DecksBlock, payloadDecks } from 'payload-plugin-decks'
184
+ import { DecksBlock as DecksRenderer } from 'payload-plugin-decks/client'
185
+ ```
186
+
187
+ | Export | Description |
188
+ | ----------------------------------------------- | ---------------------------------------------------------------- |
189
+ | `payloadDecks` | Payload plugin factory. |
190
+ | `DecksBlock` from `payload-plugin-decks` | Payload block config for advanced composition. |
191
+ | `DecksBlock` from `payload-plugin-decks/client` | Client renderer for saved decks block data. |
192
+ | `DecksBlockProps` | Renderer prop type. |
193
+ | `DecksSlide` | Slide prop type. |
194
+ | `normalizeDecksBlock` | Normalizes saved Payload block data into the renderer interface. |
195
+
196
+ ## Development
197
+
198
+ ```sh
199
+ pnpm install
200
+ pnpm build
201
+ pnpm test:int
202
+ pnpm lint
203
+ ```
204
+
205
+ The integration test uses `mongodb-memory-server`, so it needs permission to bind a local port in sandboxed environments.
@@ -0,0 +1,2 @@
1
+ import type { Block } from 'payload';
2
+ export declare const DecksBlock: Block;
@@ -0,0 +1,148 @@
1
+ import { DECKS_DEFAULTS, decksAnimationOptions, decksTextPositionOptions } from '../../decks/schema.js';
2
+ export const DecksBlock = {
3
+ slug: 'decks',
4
+ fields: [
5
+ {
6
+ name: 'title',
7
+ type: 'text',
8
+ admin: {
9
+ description: 'Optional title for internal reference'
10
+ },
11
+ label: 'Title (internal reference)',
12
+ required: false
13
+ },
14
+ {
15
+ name: 'fps',
16
+ type: 'number',
17
+ admin: {
18
+ description: 'Video frame rate (default: 30 FPS)'
19
+ },
20
+ defaultValue: DECKS_DEFAULTS.fps,
21
+ label: 'Frames per Second',
22
+ max: 60,
23
+ min: 1
24
+ },
25
+ {
26
+ name: 'durationPerSlide',
27
+ type: 'number',
28
+ admin: {
29
+ description: 'How long each slide is displayed'
30
+ },
31
+ defaultValue: DECKS_DEFAULTS.durationPerSlide,
32
+ label: 'Duration per Slide (seconds)',
33
+ max: 30,
34
+ min: 1
35
+ },
36
+ {
37
+ name: 'transitionDuration',
38
+ type: 'number',
39
+ admin: {
40
+ description: 'Duration of fade transition between slides'
41
+ },
42
+ defaultValue: DECKS_DEFAULTS.transitionDuration,
43
+ label: 'Transition Duration (frames)',
44
+ max: 60,
45
+ min: 0
46
+ },
47
+ {
48
+ name: 'backgroundColor',
49
+ type: 'text',
50
+ admin: {
51
+ description: 'Background color in hex format (e.g., #000000)'
52
+ },
53
+ defaultValue: DECKS_DEFAULTS.backgroundColor,
54
+ label: 'Background Color'
55
+ },
56
+ {
57
+ name: 'autoPlay',
58
+ type: 'checkbox',
59
+ defaultValue: DECKS_DEFAULTS.autoPlay,
60
+ label: 'Auto Play'
61
+ },
62
+ {
63
+ name: 'loop',
64
+ type: 'checkbox',
65
+ defaultValue: DECKS_DEFAULTS.loop,
66
+ label: 'Loop Video'
67
+ },
68
+ {
69
+ name: 'showControls',
70
+ type: 'checkbox',
71
+ defaultValue: DECKS_DEFAULTS.showControls,
72
+ label: 'Show Playback Controls'
73
+ },
74
+ {
75
+ name: 'slides',
76
+ type: 'array',
77
+ fields: [
78
+ {
79
+ name: 'image',
80
+ type: 'upload',
81
+ filterOptions: {
82
+ mimeType: {
83
+ contains: 'image'
84
+ }
85
+ },
86
+ label: 'Background Image',
87
+ relationTo: 'media',
88
+ required: false
89
+ },
90
+ {
91
+ name: 'headline',
92
+ type: 'text',
93
+ label: 'Headline',
94
+ maxLength: 100
95
+ },
96
+ {
97
+ name: 'subtext',
98
+ type: 'textarea',
99
+ label: 'Subtext',
100
+ maxLength: 300
101
+ },
102
+ {
103
+ name: 'textColor',
104
+ type: 'text',
105
+ admin: {
106
+ description: 'Text color in hex format (e.g., #ffffff)'
107
+ },
108
+ defaultValue: DECKS_DEFAULTS.textColor,
109
+ label: 'Text Color'
110
+ },
111
+ {
112
+ name: 'textPosition',
113
+ type: 'select',
114
+ defaultValue: DECKS_DEFAULTS.textPosition,
115
+ label: 'Text Position',
116
+ options: [
117
+ ...decksTextPositionOptions
118
+ ]
119
+ },
120
+ {
121
+ name: 'animationType',
122
+ type: 'select',
123
+ defaultValue: DECKS_DEFAULTS.animationType,
124
+ label: 'Text Animation',
125
+ options: [
126
+ ...decksAnimationOptions
127
+ ]
128
+ },
129
+ {
130
+ name: 'imageZoom',
131
+ type: 'checkbox',
132
+ defaultValue: DECKS_DEFAULTS.imageZoom,
133
+ label: 'Enable Ken Burns Effect (slow zoom)'
134
+ }
135
+ ],
136
+ label: 'Slides',
137
+ minRows: 1,
138
+ required: true
139
+ }
140
+ ],
141
+ interfaceName: 'DecksBlock',
142
+ labels: {
143
+ plural: 'Decks',
144
+ singular: 'Decks'
145
+ }
146
+ };
147
+
148
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/decks/config.ts"],"sourcesContent":["import type { Block } from 'payload'\n\nimport {\n DECKS_DEFAULTS,\n decksAnimationOptions,\n decksTextPositionOptions,\n} from '../../decks/schema.js'\n\nexport const DecksBlock: Block = {\n slug: 'decks',\n fields: [\n {\n name: 'title',\n type: 'text',\n admin: {\n description: 'Optional title for internal reference',\n },\n label: 'Title (internal reference)',\n required: false,\n },\n {\n name: 'fps',\n type: 'number',\n admin: {\n description: 'Video frame rate (default: 30 FPS)',\n },\n defaultValue: DECKS_DEFAULTS.fps,\n label: 'Frames per Second',\n max: 60,\n min: 1,\n },\n {\n name: 'durationPerSlide',\n type: 'number',\n admin: {\n description: 'How long each slide is displayed',\n },\n defaultValue: DECKS_DEFAULTS.durationPerSlide,\n label: 'Duration per Slide (seconds)',\n max: 30,\n min: 1,\n },\n {\n name: 'transitionDuration',\n type: 'number',\n admin: {\n description: 'Duration of fade transition between slides',\n },\n defaultValue: DECKS_DEFAULTS.transitionDuration,\n label: 'Transition Duration (frames)',\n max: 60,\n min: 0,\n },\n {\n name: 'backgroundColor',\n type: 'text',\n admin: {\n description: 'Background color in hex format (e.g., #000000)',\n },\n defaultValue: DECKS_DEFAULTS.backgroundColor,\n label: 'Background Color',\n },\n {\n name: 'autoPlay',\n type: 'checkbox',\n defaultValue: DECKS_DEFAULTS.autoPlay,\n label: 'Auto Play',\n },\n {\n name: 'loop',\n type: 'checkbox',\n defaultValue: DECKS_DEFAULTS.loop,\n label: 'Loop Video',\n },\n {\n name: 'showControls',\n type: 'checkbox',\n defaultValue: DECKS_DEFAULTS.showControls,\n label: 'Show Playback Controls',\n },\n {\n name: 'slides',\n type: 'array',\n fields: [\n {\n name: 'image',\n type: 'upload',\n filterOptions: {\n mimeType: { contains: 'image' },\n },\n label: 'Background Image',\n relationTo: 'media',\n required: false,\n },\n {\n name: 'headline',\n type: 'text',\n label: 'Headline',\n maxLength: 100,\n },\n {\n name: 'subtext',\n type: 'textarea',\n label: 'Subtext',\n maxLength: 300,\n },\n {\n name: 'textColor',\n type: 'text',\n admin: {\n description: 'Text color in hex format (e.g., #ffffff)',\n },\n defaultValue: DECKS_DEFAULTS.textColor,\n label: 'Text Color',\n },\n {\n name: 'textPosition',\n type: 'select',\n defaultValue: DECKS_DEFAULTS.textPosition,\n label: 'Text Position',\n options: [...decksTextPositionOptions],\n },\n {\n name: 'animationType',\n type: 'select',\n defaultValue: DECKS_DEFAULTS.animationType,\n label: 'Text Animation',\n options: [...decksAnimationOptions],\n },\n {\n name: 'imageZoom',\n type: 'checkbox',\n defaultValue: DECKS_DEFAULTS.imageZoom,\n label: 'Enable Ken Burns Effect (slow zoom)',\n },\n ],\n label: 'Slides',\n minRows: 1,\n required: true,\n },\n ],\n interfaceName: 'DecksBlock',\n labels: {\n plural: 'Decks',\n singular: 'Decks',\n },\n}\n"],"names":["DECKS_DEFAULTS","decksAnimationOptions","decksTextPositionOptions","DecksBlock","slug","fields","name","type","admin","description","label","required","defaultValue","fps","max","min","durationPerSlide","transitionDuration","backgroundColor","autoPlay","loop","showControls","filterOptions","mimeType","contains","relationTo","maxLength","textColor","textPosition","options","animationType","imageZoom","minRows","interfaceName","labels","plural","singular"],"mappings":"AAEA,SACEA,cAAc,EACdC,qBAAqB,EACrBC,wBAAwB,QACnB,wBAAuB;AAE9B,OAAO,MAAMC,aAAoB;IAC/BC,MAAM;IACNC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAC,OAAO;YACPC,UAAU;QACZ;QACA;YACEL,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAG,cAAcZ,eAAea,GAAG;YAChCH,OAAO;YACPI,KAAK;YACLC,KAAK;QACP;QACA;YACET,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAG,cAAcZ,eAAegB,gBAAgB;YAC7CN,OAAO;YACPI,KAAK;YACLC,KAAK;QACP;QACA;YACET,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAG,cAAcZ,eAAeiB,kBAAkB;YAC/CP,OAAO;YACPI,KAAK;YACLC,KAAK;QACP;QACA;YACET,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,aAAa;YACf;YACAG,cAAcZ,eAAekB,eAAe;YAC5CR,OAAO;QACT;QACA;YACEJ,MAAM;YACNC,MAAM;YACNK,cAAcZ,eAAemB,QAAQ;YACrCT,OAAO;QACT;QACA;YACEJ,MAAM;YACNC,MAAM;YACNK,cAAcZ,eAAeoB,IAAI;YACjCV,OAAO;QACT;QACA;YACEJ,MAAM;YACNC,MAAM;YACNK,cAAcZ,eAAeqB,YAAY;YACzCX,OAAO;QACT;QACA;YACEJ,MAAM;YACNC,MAAM;YACNF,QAAQ;gBACN;oBACEC,MAAM;oBACNC,MAAM;oBACNe,eAAe;wBACbC,UAAU;4BAAEC,UAAU;wBAAQ;oBAChC;oBACAd,OAAO;oBACPe,YAAY;oBACZd,UAAU;gBACZ;gBACA;oBACEL,MAAM;oBACNC,MAAM;oBACNG,OAAO;oBACPgB,WAAW;gBACb;gBACA;oBACEpB,MAAM;oBACNC,MAAM;oBACNG,OAAO;oBACPgB,WAAW;gBACb;gBACA;oBACEpB,MAAM;oBACNC,MAAM;oBACNC,OAAO;wBACLC,aAAa;oBACf;oBACAG,cAAcZ,eAAe2B,SAAS;oBACtCjB,OAAO;gBACT;gBACA;oBACEJ,MAAM;oBACNC,MAAM;oBACNK,cAAcZ,eAAe4B,YAAY;oBACzClB,OAAO;oBACPmB,SAAS;2BAAI3B;qBAAyB;gBACxC;gBACA;oBACEI,MAAM;oBACNC,MAAM;oBACNK,cAAcZ,eAAe8B,aAAa;oBAC1CpB,OAAO;oBACPmB,SAAS;2BAAI5B;qBAAsB;gBACrC;gBACA;oBACEK,MAAM;oBACNC,MAAM;oBACNK,cAAcZ,eAAe+B,SAAS;oBACtCrB,OAAO;gBACT;aACD;YACDA,OAAO;YACPsB,SAAS;YACTrB,UAAU;QACZ;KACD;IACDsB,eAAe;IACfC,QAAQ;QACNC,QAAQ;QACRC,UAAU;IACZ;AACF,EAAC"}
@@ -0,0 +1,4 @@
1
+ export { DecksBlock as DecksBlockComponent, type DecksBlockProps, type DecksSlide, } from '../../components/decks/DecksBlock.js';
2
+ export { DecksComposition, type DecksCompositionProps, } from '../../components/decks/DecksComposition.js';
3
+ export { type NormalizedDecksBlock, type NormalizedDecksSlide, normalizeDecksBlock, } from '../../decks/model.js';
4
+ export { DecksBlock } from './config.js';
@@ -0,0 +1,6 @@
1
+ export { DecksBlock as DecksBlockComponent } from '../../components/decks/DecksBlock.js';
2
+ export { DecksComposition } from '../../components/decks/DecksComposition.js';
3
+ export { normalizeDecksBlock } from '../../decks/model.js';
4
+ export { DecksBlock } from './config.js';
5
+
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/decks/index.ts"],"sourcesContent":["export {\n DecksBlock as DecksBlockComponent,\n type DecksBlockProps,\n type DecksSlide,\n} from '../../components/decks/DecksBlock.js'\nexport {\n DecksComposition,\n type DecksCompositionProps,\n} from '../../components/decks/DecksComposition.js'\nexport {\n type NormalizedDecksBlock,\n type NormalizedDecksSlide,\n normalizeDecksBlock,\n} from '../../decks/model.js'\nexport { DecksBlock } from './config.js'\n"],"names":["DecksBlock","DecksBlockComponent","DecksComposition","normalizeDecksBlock"],"mappings":"AAAA,SACEA,cAAcC,mBAAmB,QAG5B,uCAAsC;AAC7C,SACEC,gBAAgB,QAEX,6CAA4C;AACnD,SAGEC,mBAAmB,QACd,uBAAsB;AAC7B,SAASH,UAAU,QAAQ,cAAa"}
@@ -0,0 +1,5 @@
1
+ import type { DecksBlockProps } from '../../decks/model.js';
2
+ import './styles.css';
3
+ export type { DecksBlockProps, DecksSlide } from '../../decks/model.js';
4
+ export declare const DecksBlock: (props: DecksBlockProps) => import("react/jsx-runtime").JSX.Element | null;
5
+ export default DecksBlock;
@@ -0,0 +1,104 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Player } from '@remotion/player';
4
+ import { useCallback, useMemo, useSyncExternalStore } from 'react';
5
+ import { normalizeDecksBlock } from '../../decks/model.js';
6
+ import { getSlideDurationFrames } from '../../decks/timeline.js';
7
+ import { DecksComposition } from './DecksComposition.js';
8
+ import { SnapContainer } from './SnapContainer.js';
9
+ import './styles.css';
10
+ const emptySubscribe = ()=>()=>{};
11
+ export const DecksBlock = (props)=>{
12
+ const isClient = useSyncExternalStore(emptySubscribe, ()=>true, ()=>false);
13
+ const deck = useMemo(()=>normalizeDecksBlock(props), [
14
+ props
15
+ ]);
16
+ const totalDurationInFrames = useMemo(()=>{
17
+ return deck.slides.length * getSlideDurationFrames({
18
+ durationPerSlide: deck.durationPerSlide,
19
+ fps: deck.fps
20
+ });
21
+ }, [
22
+ deck.durationPerSlide,
23
+ deck.fps,
24
+ deck.slides.length
25
+ ]);
26
+ const inputProps = useMemo(()=>({
27
+ backgroundColor: deck.backgroundColor,
28
+ durationPerSlide: deck.durationPerSlide,
29
+ slides: deck.slides,
30
+ transitionDuration: deck.transitionDuration
31
+ }), [
32
+ deck.backgroundColor,
33
+ deck.durationPerSlide,
34
+ deck.slides,
35
+ deck.transitionDuration
36
+ ]);
37
+ const renderLoading = useCallback(()=>{
38
+ return /*#__PURE__*/ _jsx("div", {
39
+ className: "decks-loading",
40
+ children: /*#__PURE__*/ _jsx("div", {
41
+ className: "decks-spinner"
42
+ })
43
+ });
44
+ }, []);
45
+ const errorFallback = useCallback(({ error })=>{
46
+ return /*#__PURE__*/ _jsx("div", {
47
+ className: "decks-error",
48
+ children: /*#__PURE__*/ _jsxs("p", {
49
+ children: [
50
+ "Failed to load video: ",
51
+ error.message
52
+ ]
53
+ })
54
+ });
55
+ }, []);
56
+ if (!isClient) {
57
+ return /*#__PURE__*/ _jsx("div", {
58
+ className: "decks-wrapper",
59
+ children: /*#__PURE__*/ _jsx("div", {
60
+ className: "decks-container",
61
+ children: /*#__PURE__*/ _jsx("div", {
62
+ className: "decks-loading",
63
+ children: /*#__PURE__*/ _jsx("div", {
64
+ className: "decks-spinner"
65
+ })
66
+ })
67
+ })
68
+ });
69
+ }
70
+ if (deck.slides.length === 0) {
71
+ return null;
72
+ }
73
+ return /*#__PURE__*/ _jsx(SnapContainer, {
74
+ children: /*#__PURE__*/ _jsx(Player, {
75
+ autoPlay: deck.autoPlay,
76
+ clickToPlay: !deck.autoPlay,
77
+ component: DecksComposition,
78
+ compositionHeight: 1080,
79
+ compositionWidth: 1920,
80
+ controls: deck.showControls,
81
+ doubleClickToFullscreen: true,
82
+ durationInFrames: totalDurationInFrames,
83
+ errorFallback: errorFallback,
84
+ fps: deck.fps,
85
+ // Deck compositions have no audio. Muting plus opting out of Remotion's
86
+ // shared audio tags stops the Player from creating a gated AudioContext,
87
+ // which strict browsers (e.g. Brave) block until a user gesture — that
88
+ // block stalls the playback clock so autoPlay never advances (black /
89
+ // frozen on the first frame until you pause-play or refocus the tab).
90
+ initiallyMuted: true,
91
+ inputProps: inputProps,
92
+ loop: deck.loop,
93
+ numberOfSharedAudioTags: 0,
94
+ renderLoading: renderLoading,
95
+ style: {
96
+ height: '100%',
97
+ width: '100%'
98
+ }
99
+ })
100
+ });
101
+ };
102
+ export default DecksBlock;
103
+
104
+ //# sourceMappingURL=DecksBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/decks/DecksBlock.tsx"],"sourcesContent":["'use client'\n\nimport { Player } from '@remotion/player'\nimport { useCallback, useMemo, useSyncExternalStore } from 'react'\n\nimport type { DecksBlockProps } from '../../decks/model.js'\n\nimport { normalizeDecksBlock } from '../../decks/model.js'\nimport { getSlideDurationFrames } from '../../decks/timeline.js'\nimport { DecksComposition } from './DecksComposition.js'\nimport { SnapContainer } from './SnapContainer.js'\nimport './styles.css'\n\nexport type { DecksBlockProps, DecksSlide } from '../../decks/model.js'\n\nconst emptySubscribe = () => () => {}\n\nexport const DecksBlock = (props: DecksBlockProps) => {\n const isClient = useSyncExternalStore(\n emptySubscribe,\n () => true,\n () => false,\n )\n const deck = useMemo(() => normalizeDecksBlock(props), [props])\n\n const totalDurationInFrames = useMemo(() => {\n return (\n deck.slides.length *\n getSlideDurationFrames({\n durationPerSlide: deck.durationPerSlide,\n fps: deck.fps,\n })\n )\n }, [deck.durationPerSlide, deck.fps, deck.slides.length])\n\n const inputProps = useMemo(\n () => ({\n backgroundColor: deck.backgroundColor,\n durationPerSlide: deck.durationPerSlide,\n slides: deck.slides,\n transitionDuration: deck.transitionDuration,\n }),\n [deck.backgroundColor, deck.durationPerSlide, deck.slides, deck.transitionDuration],\n )\n\n const renderLoading = useCallback(() => {\n return (\n <div className=\"decks-loading\">\n <div className=\"decks-spinner\" />\n </div>\n )\n }, [])\n\n const errorFallback = useCallback(({ error }: { error: Error }) => {\n return (\n <div className=\"decks-error\">\n <p>Failed to load video: {error.message}</p>\n </div>\n )\n }, [])\n\n if (!isClient) {\n return (\n <div className=\"decks-wrapper\">\n <div className=\"decks-container\">\n <div className=\"decks-loading\">\n <div className=\"decks-spinner\" />\n </div>\n </div>\n </div>\n )\n }\n\n if (deck.slides.length === 0) {\n return null\n }\n\n return (\n <SnapContainer>\n <Player\n autoPlay={deck.autoPlay}\n clickToPlay={!deck.autoPlay}\n component={DecksComposition}\n compositionHeight={1080}\n compositionWidth={1920}\n controls={deck.showControls}\n doubleClickToFullscreen\n durationInFrames={totalDurationInFrames}\n errorFallback={errorFallback}\n fps={deck.fps}\n // Deck compositions have no audio. Muting plus opting out of Remotion's\n // shared audio tags stops the Player from creating a gated AudioContext,\n // which strict browsers (e.g. Brave) block until a user gesture — that\n // block stalls the playback clock so autoPlay never advances (black /\n // frozen on the first frame until you pause-play or refocus the tab).\n initiallyMuted\n inputProps={inputProps}\n loop={deck.loop}\n numberOfSharedAudioTags={0}\n renderLoading={renderLoading}\n style={{\n height: '100%',\n width: '100%',\n }}\n />\n </SnapContainer>\n )\n}\n\nexport default DecksBlock\n"],"names":["Player","useCallback","useMemo","useSyncExternalStore","normalizeDecksBlock","getSlideDurationFrames","DecksComposition","SnapContainer","emptySubscribe","DecksBlock","props","isClient","deck","totalDurationInFrames","slides","length","durationPerSlide","fps","inputProps","backgroundColor","transitionDuration","renderLoading","div","className","errorFallback","error","p","message","autoPlay","clickToPlay","component","compositionHeight","compositionWidth","controls","showControls","doubleClickToFullscreen","durationInFrames","initiallyMuted","loop","numberOfSharedAudioTags","style","height","width"],"mappings":"AAAA;;AAEA,SAASA,MAAM,QAAQ,mBAAkB;AACzC,SAASC,WAAW,EAAEC,OAAO,EAAEC,oBAAoB,QAAQ,QAAO;AAIlE,SAASC,mBAAmB,QAAQ,uBAAsB;AAC1D,SAASC,sBAAsB,QAAQ,0BAAyB;AAChE,SAASC,gBAAgB,QAAQ,wBAAuB;AACxD,SAASC,aAAa,QAAQ,qBAAoB;AAClD,OAAO,eAAc;AAIrB,MAAMC,iBAAiB,IAAM,KAAO;AAEpC,OAAO,MAAMC,aAAa,CAACC;IACzB,MAAMC,WAAWR,qBACfK,gBACA,IAAM,MACN,IAAM;IAER,MAAMI,OAAOV,QAAQ,IAAME,oBAAoBM,QAAQ;QAACA;KAAM;IAE9D,MAAMG,wBAAwBX,QAAQ;QACpC,OACEU,KAAKE,MAAM,CAACC,MAAM,GAClBV,uBAAuB;YACrBW,kBAAkBJ,KAAKI,gBAAgB;YACvCC,KAAKL,KAAKK,GAAG;QACf;IAEJ,GAAG;QAACL,KAAKI,gBAAgB;QAAEJ,KAAKK,GAAG;QAAEL,KAAKE,MAAM,CAACC,MAAM;KAAC;IAExD,MAAMG,aAAahB,QACjB,IAAO,CAAA;YACLiB,iBAAiBP,KAAKO,eAAe;YACrCH,kBAAkBJ,KAAKI,gBAAgB;YACvCF,QAAQF,KAAKE,MAAM;YACnBM,oBAAoBR,KAAKQ,kBAAkB;QAC7C,CAAA,GACA;QAACR,KAAKO,eAAe;QAAEP,KAAKI,gBAAgB;QAAEJ,KAAKE,MAAM;QAAEF,KAAKQ,kBAAkB;KAAC;IAGrF,MAAMC,gBAAgBpB,YAAY;QAChC,qBACE,KAACqB;YAAIC,WAAU;sBACb,cAAA,KAACD;gBAAIC,WAAU;;;IAGrB,GAAG,EAAE;IAEL,MAAMC,gBAAgBvB,YAAY,CAAC,EAAEwB,KAAK,EAAoB;QAC5D,qBACE,KAACH;YAAIC,WAAU;sBACb,cAAA,MAACG;;oBAAE;oBAAuBD,MAAME,OAAO;;;;IAG7C,GAAG,EAAE;IAEL,IAAI,CAAChB,UAAU;QACb,qBACE,KAACW;YAAIC,WAAU;sBACb,cAAA,KAACD;gBAAIC,WAAU;0BACb,cAAA,KAACD;oBAAIC,WAAU;8BACb,cAAA,KAACD;wBAAIC,WAAU;;;;;IAKzB;IAEA,IAAIX,KAAKE,MAAM,CAACC,MAAM,KAAK,GAAG;QAC5B,OAAO;IACT;IAEA,qBACE,KAACR;kBACC,cAAA,KAACP;YACC4B,UAAUhB,KAAKgB,QAAQ;YACvBC,aAAa,CAACjB,KAAKgB,QAAQ;YAC3BE,WAAWxB;YACXyB,mBAAmB;YACnBC,kBAAkB;YAClBC,UAAUrB,KAAKsB,YAAY;YAC3BC,uBAAuB;YACvBC,kBAAkBvB;YAClBW,eAAeA;YACfP,KAAKL,KAAKK,GAAG;YACb,wEAAwE;YACxE,yEAAyE;YACzE,uEAAuE;YACvE,sEAAsE;YACtE,sEAAsE;YACtEoB,cAAc;YACdnB,YAAYA;YACZoB,MAAM1B,KAAK0B,IAAI;YACfC,yBAAyB;YACzBlB,eAAeA;YACfmB,OAAO;gBACLC,QAAQ;gBACRC,OAAO;YACT;;;AAIR,EAAC;AAED,eAAejC,WAAU"}
@@ -0,0 +1,9 @@
1
+ import type { NormalizedDecksBlock } from '../../decks/model.js';
2
+ export interface DecksCompositionProps {
3
+ backgroundColor: NormalizedDecksBlock['backgroundColor'];
4
+ durationPerSlide: NormalizedDecksBlock['durationPerSlide'];
5
+ slides: NormalizedDecksBlock['slides'];
6
+ transitionDuration: NormalizedDecksBlock['transitionDuration'];
7
+ }
8
+ export declare const DecksComposition: ({ backgroundColor, durationPerSlide, slides, transitionDuration, }: DecksCompositionProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default DecksComposition;
@@ -0,0 +1,94 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { AbsoluteFill, Img, Sequence, useCurrentFrame, useVideoConfig } from 'remotion';
4
+ import { getSlideDurationFrames, getSlideStyles } from '../../decks/timeline.js';
5
+ const Slide = ({ slide, slideDuration, transitionDuration })=>{
6
+ const frame = useCurrentFrame();
7
+ const { imageScale, opacity, position: positionStyles, textAnimation: textAnimationStyles } = getSlideStyles({
8
+ animationType: slide.animationType,
9
+ frame,
10
+ imageZoom: slide.imageZoom,
11
+ slideDuration,
12
+ textPosition: slide.textPosition,
13
+ transitionDuration
14
+ });
15
+ return /*#__PURE__*/ _jsxs(AbsoluteFill, {
16
+ style: {
17
+ opacity
18
+ },
19
+ children: [
20
+ slide.image?.url && /*#__PURE__*/ _jsx(AbsoluteFill, {
21
+ children: /*#__PURE__*/ _jsx(Img, {
22
+ alt: slide.image.alt || '',
23
+ src: slide.image.url,
24
+ style: {
25
+ height: '100%',
26
+ objectFit: 'cover',
27
+ transform: `scale(${imageScale})`,
28
+ width: '100%'
29
+ }
30
+ })
31
+ }),
32
+ /*#__PURE__*/ _jsx(AbsoluteFill, {
33
+ style: {
34
+ backgroundColor: 'rgba(0, 0, 0, 0.3)'
35
+ }
36
+ }),
37
+ (slide.headline || slide.subtext) && /*#__PURE__*/ _jsxs("div", {
38
+ style: {
39
+ ...positionStyles,
40
+ ...textAnimationStyles
41
+ },
42
+ children: [
43
+ slide.headline && /*#__PURE__*/ _jsx("h1", {
44
+ style: {
45
+ color: slide.textColor,
46
+ fontSize: '3.5rem',
47
+ fontWeight: 700,
48
+ lineHeight: 1.2,
49
+ margin: 0,
50
+ marginBottom: slide.subtext ? '1rem' : 0,
51
+ textShadow: '2px 2px 4px rgba(0, 0, 0, 0.5)'
52
+ },
53
+ children: slide.headline
54
+ }),
55
+ slide.subtext && /*#__PURE__*/ _jsx("p", {
56
+ style: {
57
+ color: slide.textColor,
58
+ fontSize: '1.5rem',
59
+ fontWeight: 400,
60
+ lineHeight: 1.5,
61
+ margin: 0,
62
+ textShadow: '1px 1px 2px rgba(0, 0, 0, 0.5)'
63
+ },
64
+ children: slide.subtext
65
+ })
66
+ ]
67
+ })
68
+ ]
69
+ });
70
+ };
71
+ export const DecksComposition = ({ backgroundColor, durationPerSlide, slides, transitionDuration })=>{
72
+ const { fps } = useVideoConfig();
73
+ const slideDurationFrames = getSlideDurationFrames({
74
+ durationPerSlide,
75
+ fps
76
+ });
77
+ return /*#__PURE__*/ _jsx(AbsoluteFill, {
78
+ style: {
79
+ backgroundColor
80
+ },
81
+ children: slides.map((slide, index)=>/*#__PURE__*/ _jsx(Sequence, {
82
+ durationInFrames: slideDurationFrames,
83
+ from: index * slideDurationFrames,
84
+ children: /*#__PURE__*/ _jsx(Slide, {
85
+ slide: slide,
86
+ slideDuration: slideDurationFrames,
87
+ transitionDuration: transitionDuration
88
+ })
89
+ }, index))
90
+ });
91
+ };
92
+ export default DecksComposition;
93
+
94
+ //# sourceMappingURL=DecksComposition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/decks/DecksComposition.tsx"],"sourcesContent":["'use client'\n\nimport { AbsoluteFill, Img, Sequence, useCurrentFrame, useVideoConfig } from 'remotion'\n\nimport type {\n NormalizedDecksBlock,\n NormalizedDecksSlide,\n} from '../../decks/model.js'\n\nimport {\n getSlideDurationFrames,\n getSlideStyles,\n} from '../../decks/timeline.js'\n\nexport interface DecksCompositionProps {\n backgroundColor: NormalizedDecksBlock['backgroundColor']\n durationPerSlide: NormalizedDecksBlock['durationPerSlide']\n slides: NormalizedDecksBlock['slides']\n transitionDuration: NormalizedDecksBlock['transitionDuration']\n}\n\ninterface SlideProps {\n slide: NormalizedDecksSlide\n slideDuration: number\n transitionDuration: number\n}\n\nconst Slide = ({ slide, slideDuration, transitionDuration }: SlideProps) => {\n const frame = useCurrentFrame()\n\n const { imageScale, opacity, position: positionStyles, textAnimation: textAnimationStyles } = getSlideStyles({\n animationType: slide.animationType,\n frame,\n imageZoom: slide.imageZoom,\n slideDuration,\n textPosition: slide.textPosition,\n transitionDuration,\n })\n\n return (\n <AbsoluteFill style={{ opacity }}>\n {slide.image?.url && (\n <AbsoluteFill>\n <Img\n alt={slide.image.alt || ''}\n src={slide.image.url}\n style={{\n height: '100%',\n objectFit: 'cover',\n transform: `scale(${imageScale})`,\n width: '100%',\n }}\n />\n </AbsoluteFill>\n )}\n\n <AbsoluteFill\n style={{\n backgroundColor: 'rgba(0, 0, 0, 0.3)',\n }}\n />\n\n {(slide.headline || slide.subtext) && (\n <div style={{ ...positionStyles, ...textAnimationStyles }}>\n {slide.headline && (\n <h1\n style={{\n color: slide.textColor,\n fontSize: '3.5rem',\n fontWeight: 700,\n lineHeight: 1.2,\n margin: 0,\n marginBottom: slide.subtext ? '1rem' : 0,\n textShadow: '2px 2px 4px rgba(0, 0, 0, 0.5)',\n }}\n >\n {slide.headline}\n </h1>\n )}\n {slide.subtext && (\n <p\n style={{\n color: slide.textColor,\n fontSize: '1.5rem',\n fontWeight: 400,\n lineHeight: 1.5,\n margin: 0,\n textShadow: '1px 1px 2px rgba(0, 0, 0, 0.5)',\n }}\n >\n {slide.subtext}\n </p>\n )}\n </div>\n )}\n </AbsoluteFill>\n )\n}\n\nexport const DecksComposition = ({\n backgroundColor,\n durationPerSlide,\n slides,\n transitionDuration,\n}: DecksCompositionProps) => {\n const { fps } = useVideoConfig()\n const slideDurationFrames = getSlideDurationFrames({ durationPerSlide, fps })\n\n return (\n <AbsoluteFill style={{ backgroundColor }}>\n {slides.map((slide, index) => (\n <Sequence\n durationInFrames={slideDurationFrames}\n from={index * slideDurationFrames}\n key={index}\n >\n <Slide\n slide={slide}\n slideDuration={slideDurationFrames}\n transitionDuration={transitionDuration}\n />\n </Sequence>\n ))}\n </AbsoluteFill>\n )\n}\n\nexport default DecksComposition\n"],"names":["AbsoluteFill","Img","Sequence","useCurrentFrame","useVideoConfig","getSlideDurationFrames","getSlideStyles","Slide","slide","slideDuration","transitionDuration","frame","imageScale","opacity","position","positionStyles","textAnimation","textAnimationStyles","animationType","imageZoom","textPosition","style","image","url","alt","src","height","objectFit","transform","width","backgroundColor","headline","subtext","div","h1","color","textColor","fontSize","fontWeight","lineHeight","margin","marginBottom","textShadow","p","DecksComposition","durationPerSlide","slides","fps","slideDurationFrames","map","index","durationInFrames","from"],"mappings":"AAAA;;AAEA,SAASA,YAAY,EAAEC,GAAG,EAAEC,QAAQ,EAAEC,eAAe,EAAEC,cAAc,QAAQ,WAAU;AAOvF,SACEC,sBAAsB,EACtBC,cAAc,QACT,0BAAyB;AAehC,MAAMC,QAAQ,CAAC,EAAEC,KAAK,EAAEC,aAAa,EAAEC,kBAAkB,EAAc;IACrE,MAAMC,QAAQR;IAEd,MAAM,EAAES,UAAU,EAAEC,OAAO,EAAEC,UAAUC,cAAc,EAAEC,eAAeC,mBAAmB,EAAE,GAAGX,eAAe;QAC3GY,eAAeV,MAAMU,aAAa;QAClCP;QACAQ,WAAWX,MAAMW,SAAS;QAC1BV;QACAW,cAAcZ,MAAMY,YAAY;QAChCV;IACF;IAEA,qBACE,MAACV;QAAaqB,OAAO;YAAER;QAAQ;;YAC5BL,MAAMc,KAAK,EAAEC,qBACZ,KAACvB;0BACC,cAAA,KAACC;oBACCuB,KAAKhB,MAAMc,KAAK,CAACE,GAAG,IAAI;oBACxBC,KAAKjB,MAAMc,KAAK,CAACC,GAAG;oBACpBF,OAAO;wBACLK,QAAQ;wBACRC,WAAW;wBACXC,WAAW,CAAC,MAAM,EAAEhB,WAAW,CAAC,CAAC;wBACjCiB,OAAO;oBACT;;;0BAKN,KAAC7B;gBACCqB,OAAO;oBACLS,iBAAiB;gBACnB;;YAGAtB,CAAAA,MAAMuB,QAAQ,IAAIvB,MAAMwB,OAAO,AAAD,mBAC9B,MAACC;gBAAIZ,OAAO;oBAAE,GAAGN,cAAc;oBAAE,GAAGE,mBAAmB;gBAAC;;oBACrDT,MAAMuB,QAAQ,kBACb,KAACG;wBACCb,OAAO;4BACLc,OAAO3B,MAAM4B,SAAS;4BACtBC,UAAU;4BACVC,YAAY;4BACZC,YAAY;4BACZC,QAAQ;4BACRC,cAAcjC,MAAMwB,OAAO,GAAG,SAAS;4BACvCU,YAAY;wBACd;kCAEClC,MAAMuB,QAAQ;;oBAGlBvB,MAAMwB,OAAO,kBACZ,KAACW;wBACCtB,OAAO;4BACLc,OAAO3B,MAAM4B,SAAS;4BACtBC,UAAU;4BACVC,YAAY;4BACZC,YAAY;4BACZC,QAAQ;4BACRE,YAAY;wBACd;kCAEClC,MAAMwB,OAAO;;;;;;AAO5B;AAEA,OAAO,MAAMY,mBAAmB,CAAC,EAC/Bd,eAAe,EACfe,gBAAgB,EAChBC,MAAM,EACNpC,kBAAkB,EACI;IACtB,MAAM,EAAEqC,GAAG,EAAE,GAAG3C;IAChB,MAAM4C,sBAAsB3C,uBAAuB;QAAEwC;QAAkBE;IAAI;IAE3E,qBACE,KAAC/C;QAAaqB,OAAO;YAAES;QAAgB;kBACpCgB,OAAOG,GAAG,CAAC,CAACzC,OAAO0C,sBAClB,KAAChD;gBACCiD,kBAAkBH;gBAClBI,MAAMF,QAAQF;0BAGd,cAAA,KAACzC;oBACCC,OAAOA;oBACPC,eAAeuC;oBACftC,oBAAoBA;;eALjBwC;;AAWf,EAAC;AAED,eAAeN,iBAAgB"}
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from 'react';
2
+ import './styles.css';
3
+ export interface SnapContainerProps {
4
+ children: ReactNode;
5
+ }
6
+ export declare const SnapContainer: ({ children }: SnapContainerProps) => import("react/jsx-runtime").JSX.Element;