@styleflow.app/flowpress-astro-core 0.2.0-beta.22 → 0.2.0-beta.23
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/CHANGELOG.md +10 -0
- package/README.md +26 -1
- package/dist/astro/GutenbergRenderer.astro +64 -3
- package/dist/astro/blocks/TextBlock.astro +7 -4
- package/dist/astro/blocks/helpers.d.ts +2 -0
- package/dist/astro/blocks/helpers.d.ts.map +1 -1
- package/dist/astro/blocks/helpers.js +32 -3
- package/dist/astro/blocks/helpers.js.map +1 -1
- package/dist/astro/blocks/helpers.ts +37 -3
- package/dist/block-renderers.d.ts +12 -0
- package/dist/block-renderers.d.ts.map +1 -1
- package/dist/block-renderers.js.map +1 -1
- package/dist/styleflow.js +1 -1
- package/dist/styleflow.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.2.0-beta.23
|
|
6
|
+
|
|
7
|
+
- Added validated Gutenberg text alignment for FlowPress and core text blocks.
|
|
8
|
+
- Added a typed project icon renderer, recursive propagation, standalone icon
|
|
9
|
+
blocks and ordered button icons with the StyleFlow `control` layout role.
|
|
10
|
+
- Treated `foreground=inherit` as omission, matching inherited tone and
|
|
11
|
+
intensity behavior.
|
|
12
|
+
- Rendered trusted `sf/code` documents in the main DOM only when WordPress
|
|
13
|
+
serialization supplies `codeApproved=true`; unapproved documents fail closed.
|
|
14
|
+
|
|
5
15
|
## 0.2.0-beta.22
|
|
6
16
|
|
|
7
17
|
- Added a dedicated `sf/image` renderer with WordPress responsive `srcset`,
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ The package must not import from an application or project plugin.
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
pnpm add @styleflow.app/flowpress-astro-core@0.2.0-beta.
|
|
12
|
+
pnpm add @styleflow.app/flowpress-astro-core@0.2.0-beta.23
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Prereleases are pinned exactly. The package expects Astro 7 or newer and the
|
|
@@ -44,6 +44,12 @@ visible characters. The exported
|
|
|
44
44
|
from rendered CMS blocks so consumers can generate Tailwind
|
|
45
45
|
`@source inline()` directives before compiling their frontend CSS.
|
|
46
46
|
|
|
47
|
+
Heading, rich-text, quote and matching core blocks accept Gutenberg alignment
|
|
48
|
+
from either `style.typography.textAlign` or the FlowPress `textAlign` field.
|
|
49
|
+
Only `left`, `center`, `right`, `justify`, `start` and `end` reach CSS.
|
|
50
|
+
`foreground=inherit` is omitted so icons and text inherit the surrounding
|
|
51
|
+
foreground instead of serializing an invalid StyleFlow role.
|
|
52
|
+
|
|
47
53
|
Hero image and video backgrounds apply the catalog `objectPosition` value as
|
|
48
54
|
two percentages (for example `77% 100%`). Invalid or missing CMS values safely
|
|
49
55
|
fall back to `50% 50%`.
|
|
@@ -80,6 +86,25 @@ Each custom renderer receives the original `block` and optional StyleFlow
|
|
|
80
86
|
`contract`. Its default slot contains recursively rendered child blocks, so a
|
|
81
87
|
container override can place `<slot />` where its children belong.
|
|
82
88
|
|
|
89
|
+
Projects provide their SVG implementation through the typed `iconRenderer`
|
|
90
|
+
prop. It is used by `sf/icon`, propagated through all recursive paths and used
|
|
91
|
+
for optional button icons in `before` or `after` position.
|
|
92
|
+
|
|
93
|
+
```astro
|
|
94
|
+
---
|
|
95
|
+
import GutenbergRenderer from "@styleflow.app/flowpress-astro-core/GutenbergRenderer.astro";
|
|
96
|
+
import ProjectIcon from "@sf/ui/Icon.astro";
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
<GutenbergRenderer blocks={blocks} iconRenderer={ProjectIcon} />
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`sf/code` is deliberately a trusted-code boundary, not a sandbox. The renderer
|
|
103
|
+
emits its complete HTML fragment (including style, script, iframe and embed
|
|
104
|
+
elements) in the main document only when the serialized block contains the
|
|
105
|
+
server-issued boolean `codeApproved=true`. The WordPress editor must never
|
|
106
|
+
execute the document, and consumers must not synthesize this flag.
|
|
107
|
+
|
|
83
108
|
`sf/number-spinner` renders prefix, target number and suffix with independent
|
|
84
109
|
semantic tags and StyleFlow text coordinates. Its numeric value counts from
|
|
85
110
|
zero only when it enters the viewport. The final target remains available to
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
FlowpressBlockRenderers,
|
|
5
|
+
FlowpressIconRenderer
|
|
6
|
+
} from "../block-renderers.js";
|
|
4
7
|
import type { StyleflowContract } from "../styleflow.js";
|
|
5
8
|
import type { FlowpressBlock } from "../types.js";
|
|
6
9
|
import ColumnBlock from "./blocks/ColumnBlock.astro";
|
|
@@ -23,9 +26,10 @@ interface Props {
|
|
|
23
26
|
blocks: FlowpressBlock[];
|
|
24
27
|
contract?: StyleflowContract;
|
|
25
28
|
blockRenderers?: FlowpressBlockRenderers;
|
|
29
|
+
iconRenderer?: FlowpressIconRenderer;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
const { blocks, contract, blockRenderers = {} } = Astro.props;
|
|
32
|
+
const { blocks, contract, blockRenderers = {}, iconRenderer: IconRenderer } = Astro.props;
|
|
29
33
|
|
|
30
34
|
function youtubeEmbedUrl(value: unknown): string | null {
|
|
31
35
|
try {
|
|
@@ -59,6 +63,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
59
63
|
blocks={children}
|
|
60
64
|
contract={contract}
|
|
61
65
|
blockRenderers={blockRenderers}
|
|
66
|
+
iconRenderer={IconRenderer}
|
|
62
67
|
/>
|
|
63
68
|
</CustomBlockRenderer>
|
|
64
69
|
);
|
|
@@ -71,6 +76,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
71
76
|
blocks={children}
|
|
72
77
|
contract={contract}
|
|
73
78
|
blockRenderers={blockRenderers}
|
|
79
|
+
iconRenderer={IconRenderer}
|
|
74
80
|
/>
|
|
75
81
|
</HeroBlock>
|
|
76
82
|
);
|
|
@@ -83,6 +89,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
83
89
|
blocks={children}
|
|
84
90
|
contract={contract}
|
|
85
91
|
blockRenderers={blockRenderers}
|
|
92
|
+
iconRenderer={IconRenderer}
|
|
86
93
|
/>
|
|
87
94
|
</GridBlock>
|
|
88
95
|
);
|
|
@@ -95,6 +102,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
95
102
|
blocks={children}
|
|
96
103
|
contract={contract}
|
|
97
104
|
blockRenderers={blockRenderers}
|
|
105
|
+
iconRenderer={IconRenderer}
|
|
98
106
|
/>
|
|
99
107
|
</ColumnBlock>
|
|
100
108
|
);
|
|
@@ -120,6 +128,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
120
128
|
blocks={children}
|
|
121
129
|
contract={contract}
|
|
122
130
|
blockRenderers={blockRenderers}
|
|
131
|
+
iconRenderer={IconRenderer}
|
|
123
132
|
/>
|
|
124
133
|
</TextBlock>
|
|
125
134
|
);
|
|
@@ -129,20 +138,67 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
129
138
|
const href = linkValue(block, "href") || "#";
|
|
130
139
|
const link = objectValue(block, "href");
|
|
131
140
|
const opensInNewTab = Boolean(link.opensInNewTab);
|
|
141
|
+
const icon = String(block.attributes.icon ?? "").trim();
|
|
142
|
+
const iconPosition = ["after", "right"].includes(
|
|
143
|
+
String(block.attributes.iconPosition ?? "before")
|
|
144
|
+
) ? "after" : "before";
|
|
145
|
+
const buttonSemantic = semanticProps(block.attributes, contract, {
|
|
146
|
+
layoutRole: "control",
|
|
147
|
+
density: "md"
|
|
148
|
+
});
|
|
149
|
+
const buttonIcon = IconRenderer && icon ? (
|
|
150
|
+
<IconRenderer name={icon} display="inline" size={4} />
|
|
151
|
+
) : null;
|
|
132
152
|
return (
|
|
133
153
|
<S
|
|
134
154
|
as="a"
|
|
135
155
|
href={href}
|
|
136
156
|
target={opensInNewTab ? "_blank" : undefined}
|
|
137
157
|
rel={opensInNewTab ? "noopener noreferrer" : undefined}
|
|
138
|
-
{...
|
|
158
|
+
{...buttonSemantic}
|
|
139
159
|
{...htmlAttributes}
|
|
140
160
|
>
|
|
161
|
+
{iconPosition === "before" ? buttonIcon : null}
|
|
141
162
|
{textValue(block, "label")}
|
|
163
|
+
{iconPosition === "after" ? buttonIcon : null}
|
|
142
164
|
</S>
|
|
143
165
|
);
|
|
144
166
|
}
|
|
145
167
|
|
|
168
|
+
if (name === "icon") {
|
|
169
|
+
const icon = String(block.attributes.icon ?? "").trim();
|
|
170
|
+
const display = block.attributes.display === "block" ? "block" : "inline";
|
|
171
|
+
const numericSize = Number(block.attributes.size ?? 4);
|
|
172
|
+
const size = Number.isFinite(numericSize) && numericSize > 0
|
|
173
|
+
? numericSize
|
|
174
|
+
: 4;
|
|
175
|
+
const iconSemantic = semanticProps({
|
|
176
|
+
foreground: block.attributes.foreground,
|
|
177
|
+
tone: block.attributes.tone,
|
|
178
|
+
intensity: block.attributes.intensity
|
|
179
|
+
}, contract, {});
|
|
180
|
+
return IconRenderer && icon ? (
|
|
181
|
+
<IconRenderer
|
|
182
|
+
name={icon}
|
|
183
|
+
display={display}
|
|
184
|
+
size={size}
|
|
185
|
+
label={String(block.attributes.label ?? "").trim() || undefined}
|
|
186
|
+
{...iconSemantic}
|
|
187
|
+
{...htmlAttributes}
|
|
188
|
+
/>
|
|
189
|
+
) : null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (name === "code") {
|
|
193
|
+
return block.attributes.codeApproved === true ? (
|
|
194
|
+
<div
|
|
195
|
+
data-flowpress-trusted-code
|
|
196
|
+
{...htmlAttributes}
|
|
197
|
+
set:html={String(block.attributes.document ?? "")}
|
|
198
|
+
/>
|
|
199
|
+
) : null;
|
|
200
|
+
}
|
|
201
|
+
|
|
146
202
|
if (name === "image") {
|
|
147
203
|
return <ImageBlock block={block} contract={contract} />;
|
|
148
204
|
}
|
|
@@ -236,6 +292,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
236
292
|
blocks={resolvedBlocks[index]}
|
|
237
293
|
contract={contract}
|
|
238
294
|
blockRenderers={blockRenderers}
|
|
295
|
+
iconRenderer={IconRenderer}
|
|
239
296
|
/>
|
|
240
297
|
) : (
|
|
241
298
|
<ListItemFallback item={item} />
|
|
@@ -253,6 +310,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
253
310
|
blocks={children}
|
|
254
311
|
contract={contract}
|
|
255
312
|
blockRenderers={blockRenderers}
|
|
313
|
+
iconRenderer={IconRenderer}
|
|
256
314
|
/>
|
|
257
315
|
</div>
|
|
258
316
|
) : (
|
|
@@ -260,6 +318,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
260
318
|
blocks={children}
|
|
261
319
|
contract={contract}
|
|
262
320
|
blockRenderers={blockRenderers}
|
|
321
|
+
iconRenderer={IconRenderer}
|
|
263
322
|
/>
|
|
264
323
|
);
|
|
265
324
|
}
|
|
@@ -277,6 +336,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
277
336
|
blocks={children}
|
|
278
337
|
contract={contract}
|
|
279
338
|
blockRenderers={blockRenderers}
|
|
339
|
+
iconRenderer={IconRenderer}
|
|
280
340
|
/>
|
|
281
341
|
</details>
|
|
282
342
|
</S>
|
|
@@ -333,6 +393,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
|
|
|
333
393
|
blocks={children}
|
|
334
394
|
contract={contract}
|
|
335
395
|
blockRenderers={blockRenderers}
|
|
396
|
+
iconRenderer={IconRenderer}
|
|
336
397
|
/>
|
|
337
398
|
)}
|
|
338
399
|
</S>
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
preserveEmptyTextBlock,
|
|
8
8
|
preserveRichTextSpacing,
|
|
9
9
|
semanticProps,
|
|
10
|
+
textAlignmentStyle,
|
|
10
11
|
textValue,
|
|
11
12
|
unwrapCoreHtml
|
|
12
13
|
} from "./helpers.js";
|
|
@@ -38,6 +39,7 @@ const defaults = heading
|
|
|
38
39
|
};
|
|
39
40
|
const semantic = semanticProps(attributes, contract, defaults);
|
|
40
41
|
const htmlAttributes = blockHtmlAttributes(attributes);
|
|
42
|
+
const alignmentStyle = textAlignmentStyle(attributes);
|
|
41
43
|
const coreHtml = String(
|
|
42
44
|
attributes.content
|
|
43
45
|
?? attributes.value
|
|
@@ -58,18 +60,18 @@ const listTag = Boolean(attributes.ordered) ? "ol" : "ul";
|
|
|
58
60
|
---
|
|
59
61
|
|
|
60
62
|
{heading ? (
|
|
61
|
-
<S as={headingTag} {...semantic} {...htmlAttributes} set:html={html} />
|
|
63
|
+
<S as={headingTag} {...semantic} {...htmlAttributes} style={alignmentStyle} set:html={html} />
|
|
62
64
|
) : name === "core/list" ? (
|
|
63
|
-
<S as={listTag} {...semantic} {...htmlAttributes}>
|
|
65
|
+
<S as={listTag} {...semantic} {...htmlAttributes} style={alignmentStyle}>
|
|
64
66
|
{hasChildren ? <slot /> : <Fragment set:html={html} />}
|
|
65
67
|
</S>
|
|
66
68
|
) : name === "core/list-item" ? (
|
|
67
|
-
<S as="li" {...semantic} {...htmlAttributes}>
|
|
69
|
+
<S as="li" {...semantic} {...htmlAttributes} style={alignmentStyle}>
|
|
68
70
|
<span set:html={html}></span>
|
|
69
71
|
{hasChildren ? <slot /> : null}
|
|
70
72
|
</S>
|
|
71
73
|
) : name === "quote" || name === "core/quote" ? (
|
|
72
|
-
<S as="blockquote" {...semantic} {...htmlAttributes}>
|
|
74
|
+
<S as="blockquote" {...semantic} {...htmlAttributes} style={alignmentStyle}>
|
|
73
75
|
{hasChildren ? <slot /> : <div set:html={html}></div>}
|
|
74
76
|
{attributes.citation ? <cite>{String(attributes.citation)}</cite> : null}
|
|
75
77
|
</S>
|
|
@@ -78,6 +80,7 @@ const listTag = Boolean(attributes.ordered) ? "ol" : "ul";
|
|
|
78
80
|
as={name === "core/paragraph" ? "p" : "div"}
|
|
79
81
|
{...semantic}
|
|
80
82
|
{...htmlAttributes}
|
|
83
|
+
style={alignmentStyle}
|
|
81
84
|
set:html={html}
|
|
82
85
|
/>
|
|
83
86
|
)}
|
|
@@ -15,6 +15,8 @@ export declare const TEXT_HTML_TAGS: readonly ["span", "p", "h1", "h2", "h3", "h
|
|
|
15
15
|
export type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];
|
|
16
16
|
export declare function textHtmlTag(value: unknown): TextHtmlTag;
|
|
17
17
|
export declare function semanticProps(attributes: Record<string, unknown>, contract?: StyleflowContract, defaults?: Record<string, unknown>): Record<string, unknown>;
|
|
18
|
+
/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */
|
|
19
|
+
export declare function textAlignmentStyle(attributes: Record<string, unknown>): string | undefined;
|
|
18
20
|
export declare function prefixedTextSemanticProps(attributes: Record<string, unknown>, prefix: string, contract?: StyleflowContract, defaults?: Record<string, unknown>): Record<string, unknown>;
|
|
19
21
|
export declare function objectValue(block: FlowpressBlock, key: string): Record<string, unknown>;
|
|
20
22
|
export declare function textValue(block: FlowpressBlock, key?: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,4BAA4B,YAAY,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBzD;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,SAAK,GACb;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBjC;AAqBD,eAAO,MAAM,cAAc,6FAajB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAKvD;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAA0B,GACzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,4BAA4B,YAAY,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBzD;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,SAAK,GACb;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBjC;AAqBD,eAAO,MAAM,cAAc,6FAajB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAKvD;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAA0B,GACzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAWD,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAErE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB5D;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,GAAG,MAAM,CAMrE;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,SAAS,GAAG,MAAM,EAC1B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,MAAM,CAAC,CAe5D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKnD"}
|
|
@@ -77,9 +77,38 @@ export function semanticProps(attributes, contract, defaults = DEFAULT_SEMANTIC_
|
|
|
77
77
|
const input = Object.fromEntries(SEMANTIC_KEYS
|
|
78
78
|
.filter((key) => attributes[key] !== undefined)
|
|
79
79
|
.map((key) => [key, attributes[key]]));
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
if (contract) {
|
|
81
|
+
return resolveDynamicStyleflowProps(input, defaults, contract);
|
|
82
|
+
}
|
|
83
|
+
const resolved = { ...defaults, ...input };
|
|
84
|
+
for (const key of ["tone", "intensity", "foreground"]) {
|
|
85
|
+
if (input[key] === "inherit") {
|
|
86
|
+
delete resolved[key];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return resolved;
|
|
90
|
+
}
|
|
91
|
+
const TEXT_ALIGNMENTS = new Set([
|
|
92
|
+
"left",
|
|
93
|
+
"center",
|
|
94
|
+
"right",
|
|
95
|
+
"justify",
|
|
96
|
+
"start",
|
|
97
|
+
"end"
|
|
98
|
+
]);
|
|
99
|
+
/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */
|
|
100
|
+
export function textAlignmentStyle(attributes) {
|
|
101
|
+
const style = attributes.style && typeof attributes.style === "object"
|
|
102
|
+
&& !Array.isArray(attributes.style)
|
|
103
|
+
? attributes.style
|
|
104
|
+
: {};
|
|
105
|
+
const typography = style.typography && typeof style.typography === "object"
|
|
106
|
+
&& !Array.isArray(style.typography)
|
|
107
|
+
? style.typography
|
|
108
|
+
: {};
|
|
109
|
+
const candidate = typography.textAlign ?? attributes.textAlign;
|
|
110
|
+
const alignment = String(candidate ?? "");
|
|
111
|
+
return TEXT_ALIGNMENTS.has(alignment) ? `text-align: ${alignment};` : undefined;
|
|
83
112
|
}
|
|
84
113
|
export function prefixedTextSemanticProps(attributes, prefix, contract, defaults = {}) {
|
|
85
114
|
const attributeName = (name) => `${prefix}${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveDynamicStyleflowProps,\n type StyleflowContract\n} from \"../../styleflow.js\";\nimport type { FlowpressBlock } from \"../../types.js\";\n\nexport const DEFAULT_SEMANTIC_PROPS = {\n surface: \"default\",\n layoutRole: \"stack\",\n density: \"md\"\n};\n\nexport const DEFAULT_HERO_OBJECT_POSITION = \"50% 50%\";\n\nexport function heroObjectPosition(value: unknown): string {\n if (typeof value !== \"string\") {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n const match = value.trim().match(\n /^(\\d+(?:\\.\\d+)?|\\.\\d+)%\\s+(\\d+(?:\\.\\d+)?|\\.\\d+)%$/\n );\n if (\n !match\n || [match[1], match[2]].some((coordinate) => {\n const numeric = Number(coordinate);\n return !Number.isFinite(numeric) || numeric < 0 || numeric > 100;\n })\n ) {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n return `${match[1]}% ${match[2]}%`;\n}\n\nexport function blockHtmlAttributes(\n attributes: Record<string, unknown>,\n baseClass = \"\"\n): { id?: string; class?: string } {\n const anchor = typeof attributes.anchor === \"string\"\n ? attributes.anchor.trim()\n : \"\";\n const customClass = typeof attributes.className === \"string\"\n ? attributes.className.trim()\n : \"\";\n const className = [baseClass.trim(), customClass]\n .filter(Boolean)\n .join(\" \")\n .replace(/\\s+/g, \" \");\n\n return {\n ...(anchor ? { id: anchor } : {}),\n ...(className ? { class: className } : {})\n };\n}\n\nconst SEMANTIC_KEYS = [\n \"tone\",\n \"intensity\",\n \"surface\",\n \"layoutRole\",\n \"density\",\n \"ty\",\n \"v\",\n \"w\",\n \"foreground\",\n \"interactivePriority\",\n \"noBackground\",\n \"noBorder\",\n \"noPadding\",\n \"noGap\",\n \"noRadius\",\n \"noForeground\"\n] as const;\n\nexport const TEXT_HTML_TAGS = [\n \"span\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"strong\",\n \"em\",\n \"small\",\n \"mark\"\n] as const;\n\nexport type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];\n\nexport function textHtmlTag(value: unknown): TextHtmlTag {\n const candidate = String(value ?? \"span\");\n return TEXT_HTML_TAGS.includes(candidate as TextHtmlTag)\n ? candidate as TextHtmlTag\n : \"span\";\n}\n\nexport function semanticProps(\n attributes: Record<string, unknown>,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = DEFAULT_SEMANTIC_PROPS\n): Record<string, unknown> {\n const input = Object.fromEntries(\n SEMANTIC_KEYS\n .filter((key) => attributes[key] !== undefined)\n .map((key) => [key, attributes[key]])\n );\n return contract\n ? resolveDynamicStyleflowProps(input, defaults, contract)\n : { ...defaults, ...input };\n}\n\nexport function prefixedTextSemanticProps(\n attributes: Record<string, unknown>,\n prefix: string,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = {}\n): Record<string, unknown> {\n const attributeName = (name: string) =>\n `${prefix}${name.charAt(0).toUpperCase()}${name.slice(1)}`;\n return semanticProps({\n ty: attributes[attributeName(\"ty\")],\n v: attributes[attributeName(\"v\")],\n w: attributes[attributeName(\"w\")],\n foreground: attributes[attributeName(\"foreground\")]\n }, contract, defaults);\n}\n\nexport function objectValue(\n block: FlowpressBlock,\n key: string\n): Record<string, unknown> {\n const value = block.attributes[key];\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {};\n}\n\nexport function textValue(block: FlowpressBlock, key = \"text\"): string {\n return String(block.attributes[key] ?? \"\");\n}\n\n/**\n * Keep intentional blank lines visible across current and legacy RichText\n * serializations. Gutenberg can represent them either as repeated `<br>` tags,\n * empty paragraph elements, or literal newlines in an attribute value.\n */\nexport function preserveRichTextSpacing(html: string): string {\n const visibleEmptyBlocks = html\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(\n /<(p|div)(\\s[^>]*)?>(?:\\s| | )*<\\/\\1>/gi,\n (_match, tag: string, attributes = \"\") =>\n `<${tag}${attributes}> </${tag}>`\n );\n\n return visibleEmptyBlocks\n .split(/(<[^>]+>)/g)\n .map((part) => {\n if (part.startsWith(\"<\") || part.trim() === \"\") {\n return part;\n }\n return part.replace(/\\n(?:[ \\t]*\\n)+/g, (newlines) =>\n \"<br>\".repeat((newlines.match(/\\n/g) || []).length)\n );\n })\n .join(\"\");\n}\n\n/** Keep an empty text element at its typographic line height without visible text. */\nexport function preserveEmptyTextBlock(html: string): string {\n return html.trim() === \"\" ? \" \" : html;\n}\n\nexport function linkValue(block: FlowpressBlock, key = \"link\"): string {\n const value = block.attributes[key];\n const href = typeof value === \"string\"\n ? value\n : String(objectValue(block, key).url ?? \"\");\n return /^(?:\\/(?!\\/)|#|https?:\\/\\/|mailto:|tel:)/i.test(href) ? href : \"\";\n}\n\nexport function responsiveValues(\n attributes: Record<string, unknown>,\n prefix: \"columns\" | \"span\",\n fallback: number\n): Record<\"base\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\", number> {\n const keys = [\"base\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\"] as const;\n const result = {} as Record<(typeof keys)[number], number>;\n let inherited = fallback;\n for (const key of keys) {\n const suffix = key === \"base\"\n ? \"Base\"\n : key === \"2xl\" ? \"2xl\" : key.charAt(0).toUpperCase() + key.slice(1);\n const candidate = Number(attributes[`${prefix}${suffix}`]);\n if (Number.isInteger(candidate) && candidate >= 1 && candidate <= 12) {\n inherited = candidate;\n }\n result[key] = inherited;\n }\n return result;\n}\n\nexport function unwrapCoreHtml(html: string): string {\n const match = html.trim().match(\n /^<(p|h[1-6]|ul|ol|li|blockquote)(?:\\s[^>]*)?>([\\s\\S]*)<\\/\\1>$/\n );\n return match?.[2] ?? html;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/astro/blocks/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveDynamicStyleflowProps,\n type StyleflowContract\n} from \"../../styleflow.js\";\nimport type { FlowpressBlock } from \"../../types.js\";\n\nexport const DEFAULT_SEMANTIC_PROPS = {\n surface: \"default\",\n layoutRole: \"stack\",\n density: \"md\"\n};\n\nexport const DEFAULT_HERO_OBJECT_POSITION = \"50% 50%\";\n\nexport function heroObjectPosition(value: unknown): string {\n if (typeof value !== \"string\") {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n const match = value.trim().match(\n /^(\\d+(?:\\.\\d+)?|\\.\\d+)%\\s+(\\d+(?:\\.\\d+)?|\\.\\d+)%$/\n );\n if (\n !match\n || [match[1], match[2]].some((coordinate) => {\n const numeric = Number(coordinate);\n return !Number.isFinite(numeric) || numeric < 0 || numeric > 100;\n })\n ) {\n return DEFAULT_HERO_OBJECT_POSITION;\n }\n\n return `${match[1]}% ${match[2]}%`;\n}\n\nexport function blockHtmlAttributes(\n attributes: Record<string, unknown>,\n baseClass = \"\"\n): { id?: string; class?: string } {\n const anchor = typeof attributes.anchor === \"string\"\n ? attributes.anchor.trim()\n : \"\";\n const customClass = typeof attributes.className === \"string\"\n ? attributes.className.trim()\n : \"\";\n const className = [baseClass.trim(), customClass]\n .filter(Boolean)\n .join(\" \")\n .replace(/\\s+/g, \" \");\n\n return {\n ...(anchor ? { id: anchor } : {}),\n ...(className ? { class: className } : {})\n };\n}\n\nconst SEMANTIC_KEYS = [\n \"tone\",\n \"intensity\",\n \"surface\",\n \"layoutRole\",\n \"density\",\n \"ty\",\n \"v\",\n \"w\",\n \"foreground\",\n \"interactivePriority\",\n \"noBackground\",\n \"noBorder\",\n \"noPadding\",\n \"noGap\",\n \"noRadius\",\n \"noForeground\"\n] as const;\n\nexport const TEXT_HTML_TAGS = [\n \"span\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"strong\",\n \"em\",\n \"small\",\n \"mark\"\n] as const;\n\nexport type TextHtmlTag = (typeof TEXT_HTML_TAGS)[number];\n\nexport function textHtmlTag(value: unknown): TextHtmlTag {\n const candidate = String(value ?? \"span\");\n return TEXT_HTML_TAGS.includes(candidate as TextHtmlTag)\n ? candidate as TextHtmlTag\n : \"span\";\n}\n\nexport function semanticProps(\n attributes: Record<string, unknown>,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = DEFAULT_SEMANTIC_PROPS\n): Record<string, unknown> {\n const input = Object.fromEntries(\n SEMANTIC_KEYS\n .filter((key) => attributes[key] !== undefined)\n .map((key) => [key, attributes[key]])\n );\n if (contract) {\n return resolveDynamicStyleflowProps(input, defaults, contract);\n }\n\n const resolved = { ...defaults, ...input };\n for (const key of [\"tone\", \"intensity\", \"foreground\"]) {\n if (input[key] === \"inherit\") {\n delete resolved[key];\n }\n }\n return resolved;\n}\n\nconst TEXT_ALIGNMENTS = new Set([\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\"\n]);\n\n/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */\nexport function textAlignmentStyle(\n attributes: Record<string, unknown>\n): string | undefined {\n const style = attributes.style && typeof attributes.style === \"object\"\n && !Array.isArray(attributes.style)\n ? attributes.style as Record<string, unknown>\n : {};\n const typography = style.typography && typeof style.typography === \"object\"\n && !Array.isArray(style.typography)\n ? style.typography as Record<string, unknown>\n : {};\n const candidate = typography.textAlign ?? attributes.textAlign;\n const alignment = String(candidate ?? \"\");\n return TEXT_ALIGNMENTS.has(alignment) ? `text-align: ${alignment};` : undefined;\n}\n\nexport function prefixedTextSemanticProps(\n attributes: Record<string, unknown>,\n prefix: string,\n contract?: StyleflowContract,\n defaults: Record<string, unknown> = {}\n): Record<string, unknown> {\n const attributeName = (name: string) =>\n `${prefix}${name.charAt(0).toUpperCase()}${name.slice(1)}`;\n return semanticProps({\n ty: attributes[attributeName(\"ty\")],\n v: attributes[attributeName(\"v\")],\n w: attributes[attributeName(\"w\")],\n foreground: attributes[attributeName(\"foreground\")]\n }, contract, defaults);\n}\n\nexport function objectValue(\n block: FlowpressBlock,\n key: string\n): Record<string, unknown> {\n const value = block.attributes[key];\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {};\n}\n\nexport function textValue(block: FlowpressBlock, key = \"text\"): string {\n return String(block.attributes[key] ?? \"\");\n}\n\n/**\n * Keep intentional blank lines visible across current and legacy RichText\n * serializations. Gutenberg can represent them either as repeated `<br>` tags,\n * empty paragraph elements, or literal newlines in an attribute value.\n */\nexport function preserveRichTextSpacing(html: string): string {\n const visibleEmptyBlocks = html\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(\n /<(p|div)(\\s[^>]*)?>(?:\\s| | )*<\\/\\1>/gi,\n (_match, tag: string, attributes = \"\") =>\n `<${tag}${attributes}> </${tag}>`\n );\n\n return visibleEmptyBlocks\n .split(/(<[^>]+>)/g)\n .map((part) => {\n if (part.startsWith(\"<\") || part.trim() === \"\") {\n return part;\n }\n return part.replace(/\\n(?:[ \\t]*\\n)+/g, (newlines) =>\n \"<br>\".repeat((newlines.match(/\\n/g) || []).length)\n );\n })\n .join(\"\");\n}\n\n/** Keep an empty text element at its typographic line height without visible text. */\nexport function preserveEmptyTextBlock(html: string): string {\n return html.trim() === \"\" ? \" \" : html;\n}\n\nexport function linkValue(block: FlowpressBlock, key = \"link\"): string {\n const value = block.attributes[key];\n const href = typeof value === \"string\"\n ? value\n : String(objectValue(block, key).url ?? \"\");\n return /^(?:\\/(?!\\/)|#|https?:\\/\\/|mailto:|tel:)/i.test(href) ? href : \"\";\n}\n\nexport function responsiveValues(\n attributes: Record<string, unknown>,\n prefix: \"columns\" | \"span\",\n fallback: number\n): Record<\"base\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\", number> {\n const keys = [\"base\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\"] as const;\n const result = {} as Record<(typeof keys)[number], number>;\n let inherited = fallback;\n for (const key of keys) {\n const suffix = key === \"base\"\n ? \"Base\"\n : key === \"2xl\" ? \"2xl\" : key.charAt(0).toUpperCase() + key.slice(1);\n const candidate = Number(attributes[`${prefix}${suffix}`]);\n if (Number.isInteger(candidate) && candidate >= 1 && candidate <= 12) {\n inherited = candidate;\n }\n result[key] = inherited;\n }\n return result;\n}\n\nexport function unwrapCoreHtml(html: string): string {\n const match = html.trim().match(\n /^<(p|h[1-6]|ul|ol|li|blockquote)(?:\\s[^>]*)?>([\\s\\S]*)<\\/\\1>$/\n );\n return match?.[2] ?? html;\n}\n"]}
|
|
@@ -107,9 +107,43 @@ export function semanticProps(
|
|
|
107
107
|
.filter((key) => attributes[key] !== undefined)
|
|
108
108
|
.map((key) => [key, attributes[key]])
|
|
109
109
|
);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
if (contract) {
|
|
111
|
+
return resolveDynamicStyleflowProps(input, defaults, contract);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const resolved = { ...defaults, ...input };
|
|
115
|
+
for (const key of ["tone", "intensity", "foreground"]) {
|
|
116
|
+
if (input[key] === "inherit") {
|
|
117
|
+
delete resolved[key];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return resolved;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const TEXT_ALIGNMENTS = new Set([
|
|
124
|
+
"left",
|
|
125
|
+
"center",
|
|
126
|
+
"right",
|
|
127
|
+
"justify",
|
|
128
|
+
"start",
|
|
129
|
+
"end"
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
/** Resolve only Gutenberg's supported text-alignment values to inline CSS. */
|
|
133
|
+
export function textAlignmentStyle(
|
|
134
|
+
attributes: Record<string, unknown>
|
|
135
|
+
): string | undefined {
|
|
136
|
+
const style = attributes.style && typeof attributes.style === "object"
|
|
137
|
+
&& !Array.isArray(attributes.style)
|
|
138
|
+
? attributes.style as Record<string, unknown>
|
|
139
|
+
: {};
|
|
140
|
+
const typography = style.typography && typeof style.typography === "object"
|
|
141
|
+
&& !Array.isArray(style.typography)
|
|
142
|
+
? style.typography as Record<string, unknown>
|
|
143
|
+
: {};
|
|
144
|
+
const candidate = typography.textAlign ?? attributes.textAlign;
|
|
145
|
+
const alignment = String(candidate ?? "");
|
|
146
|
+
return TEXT_ALIGNMENTS.has(alignment) ? `text-align: ${alignment};` : undefined;
|
|
113
147
|
}
|
|
114
148
|
|
|
115
149
|
export function prefixedTextSemanticProps(
|
|
@@ -5,6 +5,18 @@ export interface FlowpressBlockRendererProps {
|
|
|
5
5
|
block: FlowpressBlock;
|
|
6
6
|
contract?: StyleflowContract;
|
|
7
7
|
}
|
|
8
|
+
export interface FlowpressIconRendererProps {
|
|
9
|
+
name: string;
|
|
10
|
+
display?: "inline" | "block";
|
|
11
|
+
foreground?: string;
|
|
12
|
+
tone?: string;
|
|
13
|
+
intensity?: string | number;
|
|
14
|
+
size?: number;
|
|
15
|
+
label?: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
class?: string;
|
|
18
|
+
}
|
|
8
19
|
export type FlowpressBlockRenderer = AstroComponentFactory;
|
|
20
|
+
export type FlowpressIconRenderer = AstroComponentFactory;
|
|
9
21
|
export type FlowpressBlockRenderers = Readonly<Record<string, FlowpressBlockRenderer>>;
|
|
10
22
|
//# sourceMappingURL=block-renderers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-renderers.d.ts","sourceRoot":"","sources":["../src/block-renderers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAE3D,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAC5C,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CACvC,CAAC"}
|
|
1
|
+
{"version":3,"file":"block-renderers.d.ts","sourceRoot":"","sources":["../src/block-renderers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAE1D,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAC5C,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CACvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-renderers.js","sourceRoot":"","sources":["../src/block-renderers.ts"],"names":[],"mappings":"","sourcesContent":["import type { AstroComponentFactory } from \"astro/runtime/server/index.js\";\nimport type { StyleflowContract } from \"./styleflow.js\";\nimport type { FlowpressBlock } from \"./types.js\";\n\nexport interface FlowpressBlockRendererProps {\n block: FlowpressBlock;\n contract?: StyleflowContract;\n}\n\nexport type FlowpressBlockRenderer = AstroComponentFactory;\n\nexport type FlowpressBlockRenderers = Readonly<\n Record<string, FlowpressBlockRenderer>\n>;\n"]}
|
|
1
|
+
{"version":3,"file":"block-renderers.js","sourceRoot":"","sources":["../src/block-renderers.ts"],"names":[],"mappings":"","sourcesContent":["import type { AstroComponentFactory } from \"astro/runtime/server/index.js\";\nimport type { StyleflowContract } from \"./styleflow.js\";\nimport type { FlowpressBlock } from \"./types.js\";\n\nexport interface FlowpressBlockRendererProps {\n block: FlowpressBlock;\n contract?: StyleflowContract;\n}\n\nexport interface FlowpressIconRendererProps {\n name: string;\n display?: \"inline\" | \"block\";\n foreground?: string;\n tone?: string;\n intensity?: string | number;\n size?: number;\n label?: string;\n id?: string;\n class?: string;\n}\n\nexport type FlowpressBlockRenderer = AstroComponentFactory;\n\nexport type FlowpressIconRenderer = AstroComponentFactory;\n\nexport type FlowpressBlockRenderers = Readonly<\n Record<string, FlowpressBlockRenderer>\n>;\n"]}
|
package/dist/styleflow.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const INHERITED_COLOR_PROPS = new Set(["tone", "intensity"]);
|
|
1
|
+
const INHERITED_COLOR_PROPS = new Set(["tone", "intensity", "foreground"]);
|
|
2
2
|
const FOREGROUND_ROLES = ["primary", "secondary", "tertiary", "muted", "accent"];
|
|
3
3
|
const AXIS_BY_PROP = {
|
|
4
4
|
tone: ["color", "tones"],
|
package/dist/styleflow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleflow.js","sourceRoot":"","sources":["../src/styleflow.ts"],"names":[],"mappings":"AA2BA,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"styleflow.js","sourceRoot":"","sources":["../src/styleflow.ts"],"names":[],"mappings":"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","sourcesContent":["export interface StyleflowContractAxes {\n color: {\n tones: string[];\n intensities: Array<string | number>;\n surfaces: string[];\n };\n layout: {\n roles: string[];\n densities: string[];\n };\n typography: {\n types: string[];\n variants: Record<string, string[]>;\n weights: string[];\n };\n interaction: {\n priorities: string[];\n states: string[];\n };\n}\n\nexport interface StyleflowContract {\n axes: StyleflowContractAxes;\n}\n\nexport type DynamicStyleflowProps = Record<string, unknown>;\n\nconst INHERITED_COLOR_PROPS = new Set([\"tone\", \"intensity\", \"foreground\"]);\nconst FOREGROUND_ROLES = [\"primary\", \"secondary\", \"tertiary\", \"muted\", \"accent\"];\n\nconst AXIS_BY_PROP = {\n tone: [\"color\", \"tones\"],\n intensity: [\"color\", \"intensities\"],\n surface: [\"color\", \"surfaces\"],\n layoutRole: [\"layout\", \"roles\"],\n density: [\"layout\", \"densities\"],\n ty: [\"typography\", \"types\"],\n w: [\"typography\", \"weights\"],\n interactivePriority: [\"interaction\", \"priorities\"],\n interactionState: [\"interaction\", \"states\"]\n} as const;\n\nfunction sameAxisValue(candidate: unknown, allowed: unknown): boolean {\n return String(candidate) === String(allowed);\n}\n\n/**\n * CMS values can outlive a contract revision. Invalid values fail closed to\n * component defaults before reaching Styleflow's Astro runtime.\n */\nexport function resolveDynamicStyleflowProps(\n input: DynamicStyleflowProps,\n defaults: DynamicStyleflowProps,\n contract: StyleflowContract\n): DynamicStyleflowProps {\n const resolved: DynamicStyleflowProps = { ...defaults };\n\n for (const [key, value] of Object.entries(input)) {\n if (value === undefined || value === null || value === \"\") {\n continue;\n }\n\n if (INHERITED_COLOR_PROPS.has(key) && value === \"inherit\") {\n delete resolved[key];\n continue;\n }\n\n if (key === \"v\") {\n const type = String(input.ty ?? defaults.ty ?? \"\");\n const variants = contract.axes.typography.variants[type] ?? [];\n resolved.v = variants.some((variant) => sameAxisValue(value, variant))\n ? value\n : defaults.v;\n continue;\n }\n\n if (key === \"foreground\") {\n resolved.foreground = FOREGROUND_ROLES.includes(String(value))\n ? value\n : defaults.foreground;\n continue;\n }\n\n const axisPath = AXIS_BY_PROP[key as keyof typeof AXIS_BY_PROP];\n if (!axisPath) {\n resolved[key] = value;\n continue;\n }\n\n const [group, axis] = axisPath;\n const groups = contract.axes as unknown as Record<\n string,\n Record<string, unknown[]>\n >;\n const allowed = groups[group]?.[axis] ?? [];\n resolved[key] = allowed.some((item) => sameAxisValue(value, item))\n ? value\n : defaults[key];\n }\n\n return resolved;\n}\n"]}
|
package/package.json
CHANGED