@format.dev/react 0.0.0 → 0.1.1

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/dist/index.cjs ADDED
@@ -0,0 +1,468 @@
1
+ let react_dom_server = require("react-dom/server");
2
+ let react_jsx_runtime = require("react/jsx-runtime");
3
+
4
+ //#region src/utils.ts
5
+ const IMAGE_PRELOAD_LINK = /<link\b(?=[^>]*\brel="preload")(?=[^>]*\bas="image")[^>]*>/g;
6
+ /**
7
+ * Removes the `<link rel="preload" as="image">` tags that React's server
8
+ * renderer emits ahead of every eager `<img>`. The engine allows a `<link>`
9
+ * only when its `rel` is `stylesheet`, and fails the render with an
10
+ * `INVALID_HTML_LINK_ELEMENT` 400 otherwise.
11
+ */
12
+ function stripImagePreloads(html) {
13
+ return html.replace(IMAGE_PRELOAD_LINK, "");
14
+ }
15
+ /**
16
+ * Tagged template for authoring CSS, typically inside a `<style>` element.
17
+ * Returns the string from the raw segments, so CSS escapes (`\2014`,
18
+ * icon-font codepoints, escaped selectors) survive intact. Interpolated
19
+ * `null`, `undefined`, and `false` collapse to an empty string for clean
20
+ * conditional rules. The `css` name also lets editors and the Format docs
21
+ * highlighter treat the contents as CSS.
22
+ */
23
+ function css(parts, ...vals) {
24
+ let out = parts.raw[0] ?? "";
25
+ for (let i = 0; i < vals.length; i++) {
26
+ const v = vals[i];
27
+ out += (v == null || v === false ? "" : String(v)) + parts.raw[i + 1];
28
+ }
29
+ return out;
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/Template.tsx
34
+ function Template({ children, ...props }) {
35
+ const html = stripImagePreloads((0, react_dom_server.renderToStaticMarkup)(children));
36
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("template", {
37
+ ...props,
38
+ dangerouslySetInnerHTML: { __html: html }
39
+ });
40
+ }
41
+
42
+ //#endregion
43
+ //#region src/engine-target.ts
44
+ const engineTarget = "0.1.0";
45
+
46
+ //#endregion
47
+ //#region src/sdk-version.ts
48
+ const sdkVersion = "0.1.1";
49
+
50
+ //#endregion
51
+ //#region src/Document.tsx
52
+ function Document({ title, subject, author, keywords, fonts, children }) {
53
+ const keywordsString = keywords?.join(", ");
54
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
55
+ "data-sdk": sdkVersion,
56
+ "data-engine": engineTarget,
57
+ "data-type": "document",
58
+ "data-title": title,
59
+ "data-subject": subject,
60
+ "data-author": author,
61
+ "data-keywords": keywordsString,
62
+ "data-fonts": fonts,
63
+ children
64
+ });
65
+ }
66
+
67
+ //#endregion
68
+ //#region src/Layout.tsx
69
+ function Layout({ id, width, height, paginationStrategy, splitGranularity, children }) {
70
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
71
+ "data-type": "layout",
72
+ "data-id": id,
73
+ "data-width": `${width}px`,
74
+ "data-height": `${height}px`,
75
+ "data-pagination-strategy": paginationStrategy,
76
+ "data-split-granularity": splitGranularity,
77
+ children
78
+ });
79
+ }
80
+
81
+ //#endregion
82
+ //#region src/Flow.tsx
83
+ /**
84
+ * A Flow is a region whose content paginates across pages. Everything inside the
85
+ * Flow that isn't its Stream is scaffolding that repeats on every page the
86
+ * content spans; the stream's items appear once and flow.
87
+ *
88
+ * Author the stream two ways:
89
+ *
90
+ * - **bare** — `<Flow>{items}</Flow>`: the Flow's own children are the stream,
91
+ * injected with no wrapper element.
92
+ * - **scaffolded** — wrap the stream in a `<Stream>` inside surrounding markup,
93
+ * e.g. `<Flow><table><thead/><Stream>{rows}</Stream><tfoot/></table></Flow>`:
94
+ * the table, thead, and tfoot repeat per page; the rows flow.
95
+ *
96
+ * Flows nest: a Flow placed inside another Flow's stream paginates against the
97
+ * nearest enclosing sealing region (a Frame, else the page), re-cloning its own
98
+ * scaffolding on each page its content reaches.
99
+ */
100
+ function Flow({ splitGranularity, paginationStrategy, scope, children }) {
101
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
102
+ "data-type": "flow",
103
+ "data-split-granularity": splitGranularity,
104
+ "data-pagination-strategy": paginationStrategy,
105
+ "data-scope": scope,
106
+ children
107
+ });
108
+ }
109
+
110
+ //#endregion
111
+ //#region src/Stream.tsx
112
+ /**
113
+ * A Stream marks where a scaffolded Flow's items land. Use it when a Flow wraps
114
+ * its content in repeating scaffolding (a table's header and footer, a titled
115
+ * panel) and you need to say where in that scaffolding the stream flows in:
116
+ *
117
+ * ```tsx
118
+ * <Flow>
119
+ * <table>
120
+ * <thead>…</thead>
121
+ * <Stream>{rows}</Stream>
122
+ * <tfoot>…</tfoot>
123
+ * </table>
124
+ * </Flow>
125
+ * ```
126
+ *
127
+ * Omit it for a bare Flow, where the Flow's own children are the stream.
128
+ */
129
+ function Stream({ children }) {
130
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
131
+ "data-type": "stream",
132
+ children
133
+ });
134
+ }
135
+
136
+ //#endregion
137
+ //#region src/PageBreak.tsx
138
+ function PageBreak() {
139
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("template", { "data-type": "page-break" });
140
+ }
141
+
142
+ //#endregion
143
+ //#region src/PageCounter.tsx
144
+ function PageCounter({ type, as: Tag = "span", counterStyle, style, ...rest }) {
145
+ const mergedStyle = counterStyle ? {
146
+ ...style,
147
+ "--page-counter-style": counterStyle
148
+ } : style;
149
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
150
+ "data-type": type,
151
+ style: mergedStyle,
152
+ ...rest
153
+ });
154
+ }
155
+
156
+ //#endregion
157
+ //#region src/PageNumber.tsx
158
+ function PageNumber(props) {
159
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageCounter, {
160
+ ...props,
161
+ type: "page-number"
162
+ });
163
+ }
164
+
165
+ //#endregion
166
+ //#region src/PageCount.tsx
167
+ function PageCount(props) {
168
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageCounter, {
169
+ ...props,
170
+ type: "page-count"
171
+ });
172
+ }
173
+
174
+ //#endregion
175
+ //#region src/Counter.tsx
176
+ /**
177
+ * A counter whose value survives pagination. Unlike a CSS counter, which resets
178
+ * on every page, this is resolved by Format before pages are split, so the
179
+ * number stays correct wherever the content lands.
180
+ *
181
+ * By default it advances the counter and shows the new value — the usual "this
182
+ * is Figure N" case. `peek` reads without advancing, `set` jumps to a value, and
183
+ * `reset` starts the count over. These three are mutually exclusive; when more
184
+ * than one is set, `reset` wins, then `set`, then `peek`. `by` applies only to
185
+ * the default advance.
186
+ *
187
+ * Give the counter an `id` to make it referenceable. A `<Ref to="that-id" />`
188
+ * then prints the exact value this counter showed, and `<Ref to="that-id" page />`
189
+ * the page it landed on — the same way a heading's id yields its section number.
190
+ */
191
+ function Counter({ name, peek, reset, set, by, join, as: Tag = "span", counterStyle, ...rest }) {
192
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && set !== void 0 && by !== void 0) console.error("<Counter>: `set` and `by` are mutually exclusive; `set` jumps to an exact value and wins, `by` is ignored.");
193
+ const action = reset ? "reset" : set !== void 0 ? "set" : peek ? "peek" : "next";
194
+ const value = set !== void 0 ? set : action === "next" ? by : void 0;
195
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
196
+ "data-type": "counter",
197
+ "data-name": name,
198
+ "data-action": action,
199
+ "data-value": value,
200
+ "data-join": join,
201
+ "data-counter-style": counterStyle,
202
+ ...rest
203
+ });
204
+ }
205
+
206
+ //#endregion
207
+ //#region src/Numbering.tsx
208
+ /**
209
+ * Turns on document-wide numbering. With no children it numbers headings `h1`
210
+ * through `h6` hierarchically — `1`, `1.1`, `1.1.1` — with each level resetting
211
+ * the ones beneath it. Add <NumberingRule> children to number other things or
212
+ * change the format.
213
+ *
214
+ * Numbers are resolved before pages are split, so they stay correct across page
215
+ * breaks where plain CSS counters would reset.
216
+ *
217
+ * ```tsx
218
+ * <Document title="Report">
219
+ * <Numbering />
220
+ * ...
221
+ * </Document>
222
+ * ```
223
+ */
224
+ function Numbering({ counterStyle, children }) {
225
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
226
+ "data-type": "numbering",
227
+ "data-counter-style": counterStyle,
228
+ children
229
+ });
230
+ }
231
+ /**
232
+ * One numbering rule, used as `<NumberingRule>` inside `<Numbering>`. Each rule
233
+ * matches a selector and advances (and optionally inserts) a counter. Add rules
234
+ * to number things beyond the default headings, or to change the heading format.
235
+ */
236
+ function NumberingRule({ match, counter, format, increment, set, counterStyle, insert }) {
237
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && set !== void 0 && increment !== void 0) console.error("<NumberingRule>: `set` and `increment` are mutually exclusive; `set` forces an exact value and wins, `increment` is ignored.");
238
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
239
+ "data-type": "numbering-rule",
240
+ "data-match": match,
241
+ "data-counter": counter,
242
+ "data-format": format,
243
+ "data-increment": increment,
244
+ "data-set": set,
245
+ "data-counter-style": counterStyle,
246
+ "data-insert": insert
247
+ });
248
+ }
249
+ /**
250
+ * Declares one counter's behaviour, used as `<CounterDef>` inside `<Numbering>`. Name
251
+ * the counter and, optionally, the owner counter it restarts under. A counter with an
252
+ * owner returns to 0 every time the owner's value changes; one with no owner restarts
253
+ * only when you reset or set it yourself.
254
+ *
255
+ * ```tsx
256
+ * <Numbering>
257
+ * <CounterDef name="figure" resetEach="chapter" />
258
+ * <NumberingRule match="figcaption" counter="figure" format="Figure {chapter}.{figure}: " />
259
+ * </Numbering>
260
+ * ```
261
+ */
262
+ function CounterDef({ name, resetEach }) {
263
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
264
+ "data-type": "counter-def",
265
+ "data-name": name,
266
+ "data-reset-each": resetEach
267
+ });
268
+ }
269
+
270
+ //#endregion
271
+ //#region src/Scope.tsx
272
+ /**
273
+ * Opens a counter scope around its children and adds no element to the output: a
274
+ * `<Scope>` is the fallback for nesting content that has no element of its own to carry
275
+ * the scope. When the content already sits in a container or a `<Flow>`, mark that
276
+ * directly (`<ol data-scope="item">`, `<Flow scope="item">`) instead of wrapping.
277
+ *
278
+ * ```tsx
279
+ * <Scope counter="item">
280
+ * <Counter name="item" join="." /> First
281
+ * <Scope counter="item">
282
+ * <Counter name="item" join="." /> Nested
283
+ * </Scope>
284
+ * </Scope>
285
+ * ```
286
+ */
287
+ function Scope({ counter, children }) {
288
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
289
+ "data-scope": counter,
290
+ children
291
+ });
292
+ }
293
+
294
+ //#endregion
295
+ //#region src/Ref.tsx
296
+ /**
297
+ * A cross-reference to a numbered element — "see Section 2.1" or "Figure 3".
298
+ * Point it at an `id`: a heading's id yields its section number, a `<Counter>`'s
299
+ * id yields the value that counter printed. Add `page` for the page the target
300
+ * landed on, or `counter` to read a named counter's running value at the target.
301
+ *
302
+ * References resolve before pages are split and can point forward to an element
303
+ * that appears later in the document.
304
+ *
305
+ * ```tsx
306
+ * <figcaption>Figure <Counter name="figure" id="flow" />: the data flow</figcaption>
307
+ * // ...anywhere else in the document:
308
+ * <p>The method (see Section <Ref to="method" />) reads Figure <Ref to="flow" />,
309
+ * shown in full on page <Ref to="flow" page />.</p>
310
+ * ```
311
+ */
312
+ function Ref({ to, counter, page, as: Tag = "span", counterStyle, ...rest }) {
313
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
314
+ "data-type": "ref",
315
+ "data-to": to,
316
+ "data-counter": page ? void 0 : counter,
317
+ "data-page": page ? "" : void 0,
318
+ "data-counter-style": counterStyle,
319
+ ...rest
320
+ });
321
+ }
322
+
323
+ //#endregion
324
+ //#region src/TableOfContents.tsx
325
+ /**
326
+ * A table of contents. Format fills it after laying out the document: one entry
327
+ * per heading the `collect` selector matches, each with the heading's number, its
328
+ * title, and the page it landed on.
329
+ *
330
+ * The entries are flat anchors in a `<div data-type="toc-entries">` inside a
331
+ * `<nav data-type="toc">`: each is an `<a data-type="toc-entry" data-depth="N">`
332
+ * (depth 0 at the top of the outline) holding `toc-number`, `toc-title`, and
333
+ * `toc-page` spans. Depth is data, not nesting, so the stylesheet indents and sizes
334
+ * by depth and a long contents paginates by breaking between anchors. Style it through
335
+ * the `data-type` hooks and the `--toc-*` custom properties (root size, per-depth size
336
+ * and indent, page-number size, leader, and vertical rhythm), or set a `className` (or
337
+ * `styled(TableOfContents)`) on the nav. Set `leader="none"` to omit the dot leader
338
+ * entirely, so no leader is drawn between a title and its page number.
339
+ *
340
+ * Children are leading content shown above the entries — put a "Contents" heading there.
341
+ * It shows once by default; set `repeatHead` to repeat it with the nav on every page.
342
+ *
343
+ * Give a collected heading a `data-toc-description` and its entry gains a
344
+ * `toc-description` line under the title (a one-line summary, as on a magazine or
345
+ * report contents):
346
+ *
347
+ * ```tsx
348
+ * <TableOfContents collect="h1, h2">
349
+ * <h2>Contents</h2>
350
+ * </TableOfContents>
351
+ *
352
+ * <h1 data-toc-description="Defining the studio's personality and direction.">
353
+ * Visual Positioning
354
+ * </h1>
355
+ * ```
356
+ */
357
+ function TableOfContents({ collect, leader, repeatHead, className, style, children }) {
358
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
359
+ "data-type": "toc",
360
+ "data-collect": collect,
361
+ "data-leader": leader,
362
+ "data-repeat-head": repeatHead === void 0 ? void 0 : repeatHead ? "true" : "false",
363
+ className,
364
+ style,
365
+ children
366
+ });
367
+ }
368
+
369
+ //#endregion
370
+ //#region src/Footnote.tsx
371
+ /**
372
+ * A footnote. Write the note's text as the children, at the point it's
373
+ * referenced; Format leaves a numbered marker inline and moves the text to the
374
+ * footer of whichever page the marker lands on. Footnotes are numbered
375
+ * continuously through the document.
376
+ *
377
+ * Pair it with a `<Footnotes />` region in the Layout to control where the notes
378
+ * sit; without one, Format adds a footer area to each page that needs it.
379
+ *
380
+ * ```tsx
381
+ * <p>The result holds<Footnote>under the stated assumptions</Footnote>.</p>
382
+ * ```
383
+ */
384
+ function Footnote({ children }) {
385
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
386
+ "data-type": "footnote",
387
+ children
388
+ });
389
+ }
390
+
391
+ //#endregion
392
+ //#region src/Footnotes.tsx
393
+ /**
394
+ * The region that collects a page's footnotes, authored as a `<template>` Format
395
+ * fills. In a Layout it is a per-page footer gathering the notes whose markers
396
+ * landed there; in a flow's content it is an endnotes list. Format renders it as an
397
+ * `<aside data-type="footnotes">` holding a `<dl data-type="footnote-entries">`, where
398
+ * each note is a `<dt data-type="footnote-number">` term and a
399
+ * `<dd data-type="footnote-content">` definition; style the list as a grid with your
400
+ * own CSS.
401
+ *
402
+ * Put a heading or rule inside `<Footnotes>` to render it above the generated list,
403
+ * the way a table of contents renders its leading content above the entries:
404
+ *
405
+ * ```tsx
406
+ * <Footnotes>
407
+ * <h4>Notes</h4>
408
+ * </Footnotes>
409
+ * ```
410
+ *
411
+ * Omit it and Format adds a plain footer to each page that has footnotes.
412
+ */
413
+ function Footnotes({ counterStyle, restartEachPage, repeatHead, className, style, children }) {
414
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Template, {
415
+ "data-type": "footnotes",
416
+ "data-counter-style": counterStyle,
417
+ "data-restart-each-page": restartEachPage ? "" : void 0,
418
+ "data-repeat-head": repeatHead === void 0 ? void 0 : repeatHead ? "true" : "false",
419
+ className,
420
+ style,
421
+ children
422
+ });
423
+ }
424
+
425
+ //#endregion
426
+ //#region src/types.ts
427
+ /**
428
+ * How a Flow splits content that overflows a page: at a `sentence`, `word`, or
429
+ * `grapheme` boundary, or `none` to keep the block whole and move it to the next
430
+ * page intact. Use the constant (`SplitGranularity.None`) or the plain string
431
+ * (`'none'`); both are accepted.
432
+ */
433
+ const SplitGranularity = {
434
+ Sentence: "sentence",
435
+ Word: "word",
436
+ Grapheme: "grapheme",
437
+ None: "none"
438
+ };
439
+ /**
440
+ * The dot leader between a contents entry's title and its page number. The default,
441
+ * `dots`, draws it; `none` leaves the run between them blank. Use the constant
442
+ * (`TocLeader.None`) or the plain string (`'none'`); both are accepted.
443
+ */
444
+ const TocLeader = {
445
+ Dots: "dots",
446
+ None: "none"
447
+ };
448
+
449
+ //#endregion
450
+ exports.Counter = Counter;
451
+ exports.CounterDef = CounterDef;
452
+ exports.Document = Document;
453
+ exports.Flow = Flow;
454
+ exports.Footnote = Footnote;
455
+ exports.Footnotes = Footnotes;
456
+ exports.Layout = Layout;
457
+ exports.Numbering = Numbering;
458
+ exports.NumberingRule = NumberingRule;
459
+ exports.PageBreak = PageBreak;
460
+ exports.PageCount = PageCount;
461
+ exports.PageNumber = PageNumber;
462
+ exports.Ref = Ref;
463
+ exports.Scope = Scope;
464
+ exports.SplitGranularity = SplitGranularity;
465
+ exports.Stream = Stream;
466
+ exports.TableOfContents = TableOfContents;
467
+ exports.TocLeader = TocLeader;
468
+ exports.css = css;