@pressy-pub/components 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.
@@ -0,0 +1,41 @@
1
+ import * as preact from 'preact';
2
+ import { ComponentChildren, ComponentType } from 'preact';
3
+
4
+ interface FootnoteProps {
5
+ id: string | number;
6
+ children: ComponentChildren;
7
+ }
8
+ declare function Footnote({ id, children }: FootnoteProps): preact.JSX.Element;
9
+
10
+ interface AsideProps {
11
+ children: ComponentChildren;
12
+ title?: string;
13
+ }
14
+ declare function Aside({ children, title }: AsideProps): preact.JSX.Element;
15
+
16
+ interface FigureProps {
17
+ src: string;
18
+ alt?: string;
19
+ caption?: string;
20
+ wide?: boolean;
21
+ children?: ComponentChildren;
22
+ }
23
+ declare function Figure({ src, alt, caption, wide, children }: FigureProps): preact.JSX.Element;
24
+
25
+ type CalloutType = 'note' | 'tip' | 'warning' | 'important';
26
+ interface CalloutProps {
27
+ type?: CalloutType;
28
+ title?: string;
29
+ children: ComponentChildren;
30
+ }
31
+ declare function Callout({ type, title, children }: CalloutProps): preact.JSX.Element;
32
+
33
+ interface SceneBreakProps {
34
+ variant?: 'asterisks' | 'line' | 'ornament';
35
+ }
36
+ declare function SceneBreak({ variant }: SceneBreakProps): preact.JSX.Element;
37
+
38
+ declare function setMDXComponents(components: Record<string, ComponentType<any>>): void;
39
+ declare function useMDXComponents(): Record<string, ComponentType<any>>;
40
+
41
+ export { Aside, Callout, Figure, Footnote, SceneBreak, setMDXComponents, useMDXComponents };
@@ -0,0 +1,368 @@
1
+ // src/content/Footnote.tsx
2
+ import { useSignal } from "@preact/signals";
3
+ import { jsx, jsxs } from "preact/jsx-runtime";
4
+ function Footnote({ id, children }) {
5
+ const isOpen = useSignal(false);
6
+ return /* @__PURE__ */ jsxs("span", { class: "pressy-footnote-wrapper", children: [
7
+ /* @__PURE__ */ jsx(
8
+ "button",
9
+ {
10
+ class: "pressy-footnote-ref",
11
+ onClick: () => isOpen.value = !isOpen.value,
12
+ "aria-describedby": `footnote-${id}`,
13
+ "aria-expanded": isOpen.value,
14
+ children: id
15
+ }
16
+ ),
17
+ isOpen.value && /* @__PURE__ */ jsxs("span", { class: "pressy-footnote-content", id: `footnote-${id}`, role: "tooltip", children: [
18
+ children,
19
+ /* @__PURE__ */ jsx(
20
+ "button",
21
+ {
22
+ class: "pressy-footnote-close",
23
+ onClick: () => isOpen.value = false,
24
+ "aria-label": "Close footnote",
25
+ children: "\xD7"
26
+ }
27
+ )
28
+ ] }),
29
+ /* @__PURE__ */ jsx("style", { children: `
30
+ .pressy-footnote-wrapper {
31
+ position: relative;
32
+ display: inline;
33
+ }
34
+
35
+ .pressy-footnote-ref {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ min-width: 1.25em;
40
+ height: 1.25em;
41
+ padding: 0 0.25em;
42
+ font-size: 0.75em;
43
+ font-weight: 600;
44
+ color: var(--color-accent);
45
+ background: var(--color-bg-subtle);
46
+ border: none;
47
+ border-radius: 0.25em;
48
+ cursor: pointer;
49
+ vertical-align: super;
50
+ line-height: 1;
51
+ transition: background 0.15s;
52
+ }
53
+
54
+ .pressy-footnote-ref:hover {
55
+ background: var(--color-bg-muted);
56
+ }
57
+
58
+ .pressy-footnote-content {
59
+ position: absolute;
60
+ bottom: calc(100% + 0.5em);
61
+ left: 0;
62
+ z-index: 30;
63
+ display: block;
64
+ padding: 0.5em 2em 0.5em 0.75em;
65
+ font-size: var(--font-size-sm);
66
+ background: var(--color-bg-subtle);
67
+ border-radius: 0.375em;
68
+ border: 1px solid var(--color-border);
69
+ width: 300px;
70
+ max-width: 80vw;
71
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
72
+ }
73
+
74
+ .pressy-footnote-close {
75
+ position: absolute;
76
+ top: 0.25em;
77
+ right: 0.25em;
78
+ width: 1.5em;
79
+ height: 1.5em;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ font-size: 1em;
84
+ color: var(--color-text-muted);
85
+ background: none;
86
+ border: none;
87
+ cursor: pointer;
88
+ border-radius: 0.25em;
89
+ }
90
+
91
+ .pressy-footnote-close:hover {
92
+ background: var(--color-bg-muted);
93
+ color: var(--color-text);
94
+ }
95
+ ` })
96
+ ] });
97
+ }
98
+
99
+ // src/content/Aside.tsx
100
+ import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
101
+ function Aside({ children, title }) {
102
+ return /* @__PURE__ */ jsxs2("aside", { class: "pressy-aside", children: [
103
+ title && /* @__PURE__ */ jsx2("strong", { class: "pressy-aside-title", children: title }),
104
+ /* @__PURE__ */ jsx2("div", { class: "pressy-aside-content", children }),
105
+ /* @__PURE__ */ jsx2("style", { children: `
106
+ .pressy-aside {
107
+ font-size: var(--font-size-sm);
108
+ color: var(--color-text-muted);
109
+ border-left: 3px solid var(--color-accent);
110
+ padding-left: 1em;
111
+ margin-block: 1.5em;
112
+ }
113
+
114
+ .pressy-aside-title {
115
+ display: block;
116
+ color: var(--color-heading);
117
+ margin-bottom: 0.5em;
118
+ font-weight: 600;
119
+ }
120
+
121
+ .pressy-aside-content {
122
+ line-height: 1.5;
123
+ }
124
+
125
+ .pressy-aside-content p:first-child {
126
+ margin-top: 0;
127
+ }
128
+
129
+ .pressy-aside-content p:last-child {
130
+ margin-bottom: 0;
131
+ }
132
+
133
+ @media (min-width: 80ch) {
134
+ .pressy-aside {
135
+ float: right;
136
+ width: 40%;
137
+ margin-left: 2em;
138
+ margin-right: calc(-1 * ((100vw - 65ch) / 4));
139
+ }
140
+ }
141
+ ` })
142
+ ] });
143
+ }
144
+
145
+ // src/content/Figure.tsx
146
+ import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
147
+ function Figure({ src, alt, caption, wide, children }) {
148
+ return /* @__PURE__ */ jsxs3("figure", { class: `pressy-figure ${wide ? "pressy-figure-wide" : ""}`, children: [
149
+ /* @__PURE__ */ jsx3("img", { src, alt: alt || caption || "", loading: "lazy", decoding: "async" }),
150
+ (caption || children) && /* @__PURE__ */ jsx3("figcaption", { class: "pressy-figure-caption", children: caption || children }),
151
+ /* @__PURE__ */ jsx3("style", { children: `
152
+ .pressy-figure {
153
+ margin-block: 2em;
154
+ margin-inline: 0;
155
+ }
156
+
157
+ .pressy-figure img {
158
+ width: 100%;
159
+ height: auto;
160
+ border-radius: 0.5em;
161
+ }
162
+
163
+ .pressy-figure-caption {
164
+ font-size: var(--font-size-sm);
165
+ color: var(--color-text-muted);
166
+ text-align: center;
167
+ margin-top: 0.75em;
168
+ font-style: italic;
169
+ }
170
+
171
+ .pressy-figure-wide {
172
+ margin-inline: 0;
173
+ }
174
+
175
+ @media (min-width: 80ch) {
176
+ .pressy-figure-wide {
177
+ margin-inline: calc(-1 * ((100vw - 65ch) / 4));
178
+ max-width: none;
179
+ }
180
+ }
181
+ ` })
182
+ ] });
183
+ }
184
+
185
+ // src/content/Callout.tsx
186
+ import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
187
+ var icons = {
188
+ note: "\u{1F4DD}",
189
+ tip: "\u{1F4A1}",
190
+ warning: "\u26A0\uFE0F",
191
+ important: "\u2757"
192
+ };
193
+ var defaultTitles = {
194
+ note: "Note",
195
+ tip: "Tip",
196
+ warning: "Warning",
197
+ important: "Important"
198
+ };
199
+ function Callout({ type = "note", title, children }) {
200
+ return /* @__PURE__ */ jsxs4("div", { class: `pressy-callout pressy-callout-${type}`, children: [
201
+ /* @__PURE__ */ jsxs4("div", { class: "pressy-callout-header", children: [
202
+ /* @__PURE__ */ jsx4("span", { class: "pressy-callout-icon", children: icons[type] }),
203
+ /* @__PURE__ */ jsx4("strong", { class: "pressy-callout-title", children: title || defaultTitles[type] })
204
+ ] }),
205
+ /* @__PURE__ */ jsx4("div", { class: "pressy-callout-content", children }),
206
+ /* @__PURE__ */ jsx4("style", { children: `
207
+ .pressy-callout {
208
+ border-radius: 0.5em;
209
+ padding: 1em 1.25em;
210
+ margin-block: 1.5em;
211
+ }
212
+
213
+ .pressy-callout-note {
214
+ background: #eff6ff;
215
+ border: 1px solid #bfdbfe;
216
+ }
217
+
218
+ .pressy-callout-tip {
219
+ background: #f0fdf4;
220
+ border: 1px solid #bbf7d0;
221
+ }
222
+
223
+ .pressy-callout-warning {
224
+ background: #fffbeb;
225
+ border: 1px solid #fde68a;
226
+ }
227
+
228
+ .pressy-callout-important {
229
+ background: #fef2f2;
230
+ border: 1px solid #fecaca;
231
+ }
232
+
233
+ .pressy-callout-header {
234
+ display: flex;
235
+ align-items: center;
236
+ gap: 0.5em;
237
+ margin-bottom: 0.5em;
238
+ }
239
+
240
+ .pressy-callout-icon {
241
+ font-size: 1.25em;
242
+ }
243
+
244
+ .pressy-callout-title {
245
+ font-weight: 600;
246
+ }
247
+
248
+ .pressy-callout-content {
249
+ font-size: var(--font-size-sm);
250
+ line-height: 1.5;
251
+ }
252
+
253
+ .pressy-callout-content p:first-child {
254
+ margin-top: 0;
255
+ }
256
+
257
+ .pressy-callout-content p:last-child {
258
+ margin-bottom: 0;
259
+ }
260
+
261
+ /* Dark mode adjustments */
262
+ @media (prefers-color-scheme: dark) {
263
+ .pressy-callout-note {
264
+ background: #1e3a5f;
265
+ border-color: #1e40af;
266
+ }
267
+
268
+ .pressy-callout-tip {
269
+ background: #052e16;
270
+ border-color: #166534;
271
+ }
272
+
273
+ .pressy-callout-warning {
274
+ background: #422006;
275
+ border-color: #854d0e;
276
+ }
277
+
278
+ .pressy-callout-important {
279
+ background: #450a0a;
280
+ border-color: #991b1b;
281
+ }
282
+ }
283
+
284
+ [data-theme="dark"] .pressy-callout-note {
285
+ background: #1e3a5f;
286
+ border-color: #1e40af;
287
+ }
288
+
289
+ [data-theme="dark"] .pressy-callout-tip {
290
+ background: #052e16;
291
+ border-color: #166534;
292
+ }
293
+
294
+ [data-theme="dark"] .pressy-callout-warning {
295
+ background: #422006;
296
+ border-color: #854d0e;
297
+ }
298
+
299
+ [data-theme="dark"] .pressy-callout-important {
300
+ background: #450a0a;
301
+ border-color: #991b1b;
302
+ }
303
+ ` })
304
+ ] });
305
+ }
306
+
307
+ // src/content/SceneBreak.tsx
308
+ import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
309
+ function SceneBreak({ variant = "asterisks" }) {
310
+ return /* @__PURE__ */ jsxs5("div", { class: `pressy-scene-break pressy-scene-break-${variant}`, role: "separator", children: [
311
+ variant === "asterisks" && /* @__PURE__ */ jsx5("span", { children: "* * *" }),
312
+ variant === "ornament" && /* @__PURE__ */ jsx5("span", { children: "\u2767" }),
313
+ /* @__PURE__ */ jsx5("style", { children: `
314
+ .pressy-scene-break {
315
+ display: flex;
316
+ align-items: center;
317
+ justify-content: center;
318
+ margin-block: 3em;
319
+ color: var(--color-text-muted);
320
+ }
321
+
322
+ .pressy-scene-break-asterisks span {
323
+ letter-spacing: 0.5em;
324
+ font-size: 1.25em;
325
+ }
326
+
327
+ .pressy-scene-break-line {
328
+ width: 100%;
329
+ max-width: 10ch;
330
+ height: 1px;
331
+ background: var(--color-border);
332
+ }
333
+
334
+ .pressy-scene-break-ornament span {
335
+ font-size: 1.5em;
336
+ }
337
+ ` })
338
+ ] });
339
+ }
340
+
341
+ // src/content/index.ts
342
+ var defaultComponents = {
343
+ Footnote,
344
+ Aside,
345
+ Figure,
346
+ Callout,
347
+ SceneBreak,
348
+ // Override default elements
349
+ img: Figure,
350
+ hr: SceneBreak
351
+ };
352
+ var customComponents = {};
353
+ function setMDXComponents(components) {
354
+ customComponents = components;
355
+ }
356
+ function useMDXComponents() {
357
+ return { ...defaultComponents, ...customComponents };
358
+ }
359
+ export {
360
+ Aside,
361
+ Callout,
362
+ Figure,
363
+ Footnote,
364
+ SceneBreak,
365
+ setMDXComponents,
366
+ useMDXComponents
367
+ };
368
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/content/Footnote.tsx","../../src/content/Aside.tsx","../../src/content/Figure.tsx","../../src/content/Callout.tsx","../../src/content/SceneBreak.tsx","../../src/content/index.ts"],"sourcesContent":["import { ComponentChildren } from 'preact'\nimport { useSignal } from '@preact/signals'\n\ninterface FootnoteProps {\n id: string | number\n children: ComponentChildren\n}\n\nexport function Footnote({ id, children }: FootnoteProps) {\n const isOpen = useSignal(false)\n\n return (\n <span class=\"pressy-footnote-wrapper\">\n <button\n class=\"pressy-footnote-ref\"\n onClick={() => (isOpen.value = !isOpen.value)}\n aria-describedby={`footnote-${id}`}\n aria-expanded={isOpen.value}\n >\n {id}\n </button>\n\n {isOpen.value && (\n <span class=\"pressy-footnote-content\" id={`footnote-${id}`} role=\"tooltip\">\n {children}\n <button\n class=\"pressy-footnote-close\"\n onClick={() => (isOpen.value = false)}\n aria-label=\"Close footnote\"\n >\n ×\n </button>\n </span>\n )}\n\n <style>{`\n .pressy-footnote-wrapper {\n position: relative;\n display: inline;\n }\n\n .pressy-footnote-ref {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25em;\n height: 1.25em;\n padding: 0 0.25em;\n font-size: 0.75em;\n font-weight: 600;\n color: var(--color-accent);\n background: var(--color-bg-subtle);\n border: none;\n border-radius: 0.25em;\n cursor: pointer;\n vertical-align: super;\n line-height: 1;\n transition: background 0.15s;\n }\n\n .pressy-footnote-ref:hover {\n background: var(--color-bg-muted);\n }\n\n .pressy-footnote-content {\n position: absolute;\n bottom: calc(100% + 0.5em);\n left: 0;\n z-index: 30;\n display: block;\n padding: 0.5em 2em 0.5em 0.75em;\n font-size: var(--font-size-sm);\n background: var(--color-bg-subtle);\n border-radius: 0.375em;\n border: 1px solid var(--color-border);\n width: 300px;\n max-width: 80vw;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n }\n\n .pressy-footnote-close {\n position: absolute;\n top: 0.25em;\n right: 0.25em;\n width: 1.5em;\n height: 1.5em;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1em;\n color: var(--color-text-muted);\n background: none;\n border: none;\n cursor: pointer;\n border-radius: 0.25em;\n }\n\n .pressy-footnote-close:hover {\n background: var(--color-bg-muted);\n color: var(--color-text);\n }\n `}</style>\n </span>\n )\n}\n","import { ComponentChildren } from 'preact'\n\ninterface AsideProps {\n children: ComponentChildren\n title?: string\n}\n\nexport function Aside({ children, title }: AsideProps) {\n return (\n <aside class=\"pressy-aside\">\n {title && <strong class=\"pressy-aside-title\">{title}</strong>}\n <div class=\"pressy-aside-content\">{children}</div>\n\n <style>{`\n .pressy-aside {\n font-size: var(--font-size-sm);\n color: var(--color-text-muted);\n border-left: 3px solid var(--color-accent);\n padding-left: 1em;\n margin-block: 1.5em;\n }\n\n .pressy-aside-title {\n display: block;\n color: var(--color-heading);\n margin-bottom: 0.5em;\n font-weight: 600;\n }\n\n .pressy-aside-content {\n line-height: 1.5;\n }\n\n .pressy-aside-content p:first-child {\n margin-top: 0;\n }\n\n .pressy-aside-content p:last-child {\n margin-bottom: 0;\n }\n\n @media (min-width: 80ch) {\n .pressy-aside {\n float: right;\n width: 40%;\n margin-left: 2em;\n margin-right: calc(-1 * ((100vw - 65ch) / 4));\n }\n }\n `}</style>\n </aside>\n )\n}\n","import { ComponentChildren } from 'preact'\n\ninterface FigureProps {\n src: string\n alt?: string\n caption?: string\n wide?: boolean\n children?: ComponentChildren\n}\n\nexport function Figure({ src, alt, caption, wide, children }: FigureProps) {\n return (\n <figure class={`pressy-figure ${wide ? 'pressy-figure-wide' : ''}`}>\n <img src={src} alt={alt || caption || ''} loading=\"lazy\" decoding=\"async\" />\n {(caption || children) && (\n <figcaption class=\"pressy-figure-caption\">{caption || children}</figcaption>\n )}\n\n <style>{`\n .pressy-figure {\n margin-block: 2em;\n margin-inline: 0;\n }\n\n .pressy-figure img {\n width: 100%;\n height: auto;\n border-radius: 0.5em;\n }\n\n .pressy-figure-caption {\n font-size: var(--font-size-sm);\n color: var(--color-text-muted);\n text-align: center;\n margin-top: 0.75em;\n font-style: italic;\n }\n\n .pressy-figure-wide {\n margin-inline: 0;\n }\n\n @media (min-width: 80ch) {\n .pressy-figure-wide {\n margin-inline: calc(-1 * ((100vw - 65ch) / 4));\n max-width: none;\n }\n }\n `}</style>\n </figure>\n )\n}\n","import { ComponentChildren } from 'preact'\n\ntype CalloutType = 'note' | 'tip' | 'warning' | 'important'\n\ninterface CalloutProps {\n type?: CalloutType\n title?: string\n children: ComponentChildren\n}\n\nconst icons: Record<CalloutType, string> = {\n note: '📝',\n tip: '💡',\n warning: '⚠️',\n important: '❗',\n}\n\nconst defaultTitles: Record<CalloutType, string> = {\n note: 'Note',\n tip: 'Tip',\n warning: 'Warning',\n important: 'Important',\n}\n\nexport function Callout({ type = 'note', title, children }: CalloutProps) {\n return (\n <div class={`pressy-callout pressy-callout-${type}`}>\n <div class=\"pressy-callout-header\">\n <span class=\"pressy-callout-icon\">{icons[type]}</span>\n <strong class=\"pressy-callout-title\">{title || defaultTitles[type]}</strong>\n </div>\n <div class=\"pressy-callout-content\">{children}</div>\n\n <style>{`\n .pressy-callout {\n border-radius: 0.5em;\n padding: 1em 1.25em;\n margin-block: 1.5em;\n }\n\n .pressy-callout-note {\n background: #eff6ff;\n border: 1px solid #bfdbfe;\n }\n\n .pressy-callout-tip {\n background: #f0fdf4;\n border: 1px solid #bbf7d0;\n }\n\n .pressy-callout-warning {\n background: #fffbeb;\n border: 1px solid #fde68a;\n }\n\n .pressy-callout-important {\n background: #fef2f2;\n border: 1px solid #fecaca;\n }\n\n .pressy-callout-header {\n display: flex;\n align-items: center;\n gap: 0.5em;\n margin-bottom: 0.5em;\n }\n\n .pressy-callout-icon {\n font-size: 1.25em;\n }\n\n .pressy-callout-title {\n font-weight: 600;\n }\n\n .pressy-callout-content {\n font-size: var(--font-size-sm);\n line-height: 1.5;\n }\n\n .pressy-callout-content p:first-child {\n margin-top: 0;\n }\n\n .pressy-callout-content p:last-child {\n margin-bottom: 0;\n }\n\n /* Dark mode adjustments */\n @media (prefers-color-scheme: dark) {\n .pressy-callout-note {\n background: #1e3a5f;\n border-color: #1e40af;\n }\n\n .pressy-callout-tip {\n background: #052e16;\n border-color: #166534;\n }\n\n .pressy-callout-warning {\n background: #422006;\n border-color: #854d0e;\n }\n\n .pressy-callout-important {\n background: #450a0a;\n border-color: #991b1b;\n }\n }\n\n [data-theme=\"dark\"] .pressy-callout-note {\n background: #1e3a5f;\n border-color: #1e40af;\n }\n\n [data-theme=\"dark\"] .pressy-callout-tip {\n background: #052e16;\n border-color: #166534;\n }\n\n [data-theme=\"dark\"] .pressy-callout-warning {\n background: #422006;\n border-color: #854d0e;\n }\n\n [data-theme=\"dark\"] .pressy-callout-important {\n background: #450a0a;\n border-color: #991b1b;\n }\n `}</style>\n </div>\n )\n}\n","interface SceneBreakProps {\n variant?: 'asterisks' | 'line' | 'ornament'\n}\n\nexport function SceneBreak({ variant = 'asterisks' }: SceneBreakProps) {\n return (\n <div class={`pressy-scene-break pressy-scene-break-${variant}`} role=\"separator\">\n {variant === 'asterisks' && <span>* * *</span>}\n {variant === 'ornament' && <span>❧</span>}\n\n <style>{`\n .pressy-scene-break {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-block: 3em;\n color: var(--color-text-muted);\n }\n\n .pressy-scene-break-asterisks span {\n letter-spacing: 0.5em;\n font-size: 1.25em;\n }\n\n .pressy-scene-break-line {\n width: 100%;\n max-width: 10ch;\n height: 1px;\n background: var(--color-border);\n }\n\n .pressy-scene-break-ornament span {\n font-size: 1.5em;\n }\n `}</style>\n </div>\n )\n}\n","import { ComponentType, ComponentChildren } from 'preact'\nimport { Footnote } from './Footnote.js'\nimport { Aside } from './Aside.js'\nimport { Figure } from './Figure.js'\nimport { Callout } from './Callout.js'\nimport { SceneBreak } from './SceneBreak.js'\n\nexport { Footnote } from './Footnote.js'\nexport { Aside } from './Aside.js'\nexport { Figure } from './Figure.js'\nexport { Callout } from './Callout.js'\nexport { SceneBreak } from './SceneBreak.js'\n\n// MDX components provider\nconst defaultComponents: Record<string, ComponentType<any>> = {\n Footnote,\n Aside,\n Figure,\n Callout,\n SceneBreak,\n // Override default elements\n img: Figure,\n hr: SceneBreak,\n}\n\nlet customComponents: Record<string, ComponentType<any>> = {}\n\nexport function setMDXComponents(components: Record<string, ComponentType<any>>) {\n customComponents = components\n}\n\nexport function useMDXComponents(): Record<string, ComponentType<any>> {\n return { ...defaultComponents, ...customComponents }\n}\n"],"mappings":";AACA,SAAS,iBAAiB;AAYpB,cAUE,YAVF;AALC,SAAS,SAAS,EAAE,IAAI,SAAS,GAAkB;AACxD,QAAM,SAAS,UAAU,KAAK;AAE9B,SACE,qBAAC,UAAK,OAAM,2BACV;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAS,MAAO,OAAO,QAAQ,CAAC,OAAO;AAAA,QACvC,oBAAkB,YAAY,EAAE;AAAA,QAChC,iBAAe,OAAO;AAAA,QAErB;AAAA;AAAA,IACH;AAAA,IAEC,OAAO,SACN,qBAAC,UAAK,OAAM,2BAA0B,IAAI,YAAY,EAAE,IAAI,MAAK,WAC9D;AAAA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,SAAS,MAAO,OAAO,QAAQ;AAAA,UAC/B,cAAW;AAAA,UACZ;AAAA;AAAA,MAED;AAAA,OACF;AAAA,IAGF,oBAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAkEN;AAAA,KACJ;AAEJ;;;AC/FI,SACY,OAAAA,MADZ,QAAAC,aAAA;AAFG,SAAS,MAAM,EAAE,UAAU,MAAM,GAAe;AACrD,SACE,gBAAAA,MAAC,WAAM,OAAM,gBACV;AAAA,aAAS,gBAAAD,KAAC,YAAO,OAAM,sBAAsB,iBAAM;AAAA,IACpD,gBAAAA,KAAC,SAAI,OAAM,wBAAwB,UAAS;AAAA,IAE5C,gBAAAA,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAoCN;AAAA,KACJ;AAEJ;;;ACxCI,SACE,OAAAE,MADF,QAAAC,aAAA;AAFG,SAAS,OAAO,EAAE,KAAK,KAAK,SAAS,MAAM,SAAS,GAAgB;AACzE,SACE,gBAAAA,MAAC,YAAO,OAAO,iBAAiB,OAAO,uBAAuB,EAAE,IAC9D;AAAA,oBAAAD,KAAC,SAAI,KAAU,KAAK,OAAO,WAAW,IAAI,SAAQ,QAAO,UAAS,SAAQ;AAAA,KACxE,WAAW,aACX,gBAAAA,KAAC,gBAAW,OAAM,yBAAyB,qBAAW,UAAS;AAAA,IAGjE,gBAAAA,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SA8BN;AAAA,KACJ;AAEJ;;;ACxBM,SACE,OAAAE,MADF,QAAAC,aAAA;AAjBN,IAAM,QAAqC;AAAA,EACzC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,SAAS;AAAA,EACT,WAAW;AACb;AAEA,IAAM,gBAA6C;AAAA,EACjD,MAAM;AAAA,EACN,KAAK;AAAA,EACL,SAAS;AAAA,EACT,WAAW;AACb;AAEO,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,SAAS,GAAiB;AACxE,SACE,gBAAAA,MAAC,SAAI,OAAO,iCAAiC,IAAI,IAC/C;AAAA,oBAAAA,MAAC,SAAI,OAAM,yBACT;AAAA,sBAAAD,KAAC,UAAK,OAAM,uBAAuB,gBAAM,IAAI,GAAE;AAAA,MAC/C,gBAAAA,KAAC,YAAO,OAAM,wBAAwB,mBAAS,cAAc,IAAI,GAAE;AAAA,OACrE;AAAA,IACA,gBAAAA,KAAC,SAAI,OAAM,0BAA0B,UAAS;AAAA,IAE9C,gBAAAA,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAiGN;AAAA,KACJ;AAEJ;;;AC/HI,SAC8B,OAAAE,MAD9B,QAAAC,aAAA;AAFG,SAAS,WAAW,EAAE,UAAU,YAAY,GAAoB;AACrE,SACE,gBAAAA,MAAC,SAAI,OAAO,yCAAyC,OAAO,IAAI,MAAK,aAClE;AAAA,gBAAY,eAAe,gBAAAD,KAAC,UAAK,mBAAK;AAAA,IACtC,YAAY,cAAc,gBAAAA,KAAC,UAAK,oBAAC;AAAA,IAElC,gBAAAA,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAwBN;AAAA,KACJ;AAEJ;;;ACvBA,IAAM,oBAAwD;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,KAAK;AAAA,EACL,IAAI;AACN;AAEA,IAAI,mBAAuD,CAAC;AAErD,SAAS,iBAAiB,YAAgD;AAC/E,qBAAmB;AACrB;AAEO,SAAS,mBAAuD;AACrE,SAAO,EAAE,GAAG,mBAAmB,GAAG,iBAAiB;AACrD;","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs"]}
@@ -0,0 +1,131 @@
1
+ import * as preact from 'preact';
2
+ import { ComponentType, ComponentChildren } from 'preact';
3
+
4
+ interface ProgressData {
5
+ page: number;
6
+ totalPages: number;
7
+ scrollPosition: number;
8
+ }
9
+ interface ChapterMapData {
10
+ chapterMap: Record<string, () => Promise<{
11
+ default: ComponentType<{
12
+ components?: Record<string, unknown>;
13
+ }>;
14
+ }>>;
15
+ chapterOrder: string[];
16
+ }
17
+ interface ReaderProps {
18
+ children: ComponentChildren;
19
+ title: string;
20
+ bookTitle?: string;
21
+ chapterSlug?: string;
22
+ prevChapter?: {
23
+ slug: string;
24
+ title: string;
25
+ };
26
+ nextChapter?: {
27
+ slug: string;
28
+ title: string;
29
+ };
30
+ showDropCap?: boolean;
31
+ paginationMode?: "scroll" | "paginated";
32
+ onSaveProgress?: (data: ProgressData) => void;
33
+ onRestoreProgress?: () => Promise<ProgressData | null>;
34
+ bookProgressPercent?: number;
35
+ initialContent?: ComponentType<{
36
+ components?: Record<string, unknown>;
37
+ }>;
38
+ chapterMapData?: ChapterMapData;
39
+ currentChapterSlug?: string;
40
+ allChapters?: Array<{
41
+ slug: string;
42
+ title: string;
43
+ wordCount?: number;
44
+ }>;
45
+ bookBasePath?: string;
46
+ onChapterChange?: (slug: string, page: number, totalPages: number) => void;
47
+ mdxComponents?: Record<string, unknown>;
48
+ }
49
+ declare function Reader({ children, bookTitle, prevChapter, nextChapter, showDropCap, paginationMode, onSaveProgress, onRestoreProgress, bookProgressPercent, initialContent, chapterMapData, currentChapterSlug, allChapters, bookBasePath, onChapterChange, mdxComponents, }: ReaderProps): preact.JSX.Element;
50
+
51
+ interface NavigationProps {
52
+ prev?: {
53
+ slug: string;
54
+ title: string;
55
+ };
56
+ next?: {
57
+ slug: string;
58
+ title: string;
59
+ };
60
+ }
61
+ declare function Navigation({ prev, next }: NavigationProps): preact.JSX.Element | null;
62
+
63
+ interface TOCItem {
64
+ level: number;
65
+ text: string;
66
+ slug: string;
67
+ }
68
+ interface TableOfContentsProps {
69
+ items: TOCItem[];
70
+ onNavigate?: () => void;
71
+ activeSlug?: string;
72
+ }
73
+ declare function TableOfContents({ items, onNavigate, activeSlug }: TableOfContentsProps): preact.JSX.Element;
74
+
75
+ declare function TextShare(): preact.JSX.Element | null;
76
+
77
+ interface PaywallProps {
78
+ bookSlug: string;
79
+ bookTitle: string;
80
+ previewChapters: number;
81
+ currentChapter: number;
82
+ shopifyProductId?: string;
83
+ mode?: 'shopify' | 'email';
84
+ onUnlock?: () => void;
85
+ }
86
+ declare function Paywall({ bookSlug, bookTitle, previewChapters, currentChapter, shopifyProductId, mode, onUnlock, }: PaywallProps): preact.JSX.Element | null;
87
+
88
+ declare function ThemeSwitcher(): preact.JSX.Element;
89
+
90
+ declare function OfflineIndicator(): preact.JSX.Element | null;
91
+
92
+ interface DownloadBookProps {
93
+ bookSlug: string;
94
+ chapterUrls: string[];
95
+ /** Reactive signal: set of cached book slugs */
96
+ cachedBooks: {
97
+ value: Set<string>;
98
+ };
99
+ /** Reactive signal: current download progress or null */
100
+ cacheProgress: {
101
+ value: {
102
+ bookSlug: string;
103
+ current: number;
104
+ total: number;
105
+ } | null;
106
+ };
107
+ /** Called to start downloading the book */
108
+ onDownload: (bookSlug: string, chapterUrls: string[]) => void;
109
+ /** Called to remove the cached book */
110
+ onRemove: (bookSlug: string) => void;
111
+ }
112
+ declare function DownloadBook({ bookSlug, chapterUrls, cachedBooks, cacheProgress, onDownload, onRemove, }: DownloadBookProps): preact.JSX.Element;
113
+
114
+ interface BookProgressProps {
115
+ bookSlug: string;
116
+ chapters: Array<{
117
+ slug: string;
118
+ title: string;
119
+ order: number;
120
+ wordCount?: number;
121
+ }>;
122
+ basePath: string;
123
+ loadAllProgress: () => Promise<Array<{
124
+ chapterSlug: string;
125
+ page: number;
126
+ totalPages: number;
127
+ }>>;
128
+ }
129
+ declare function BookProgress({ chapters, basePath, bookSlug, loadAllProgress, }: BookProgressProps): preact.JSX.Element;
130
+
131
+ export { BookProgress, type BookProgressProps, type ChapterMapData, DownloadBook, type DownloadBookProps, Navigation, type NavigationProps, OfflineIndicator, Paywall, type PaywallProps, type ProgressData, Reader, type ReaderProps, type TOCItem, TableOfContents, type TableOfContentsProps, TextShare, ThemeSwitcher };