@styleflow.app/flowpress-astro-core 0.2.0-beta.11 → 0.2.0-beta.3

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 CHANGED
@@ -2,49 +2,6 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 0.2.0-beta.11
6
-
7
- - Rendered empty Gutenberg and FlowPress text blocks with an internal
8
- ` `, preserving their typographic line height without visible
9
- characters or synthetic break elements.
10
-
11
- ## 0.2.0-beta.10
12
-
13
- - Preserved intentionally empty core Gutenberg paragraphs as visible line
14
- breaks, including paragraphs resolved through FlowPress templates.
15
- - Exported safe recursive collection of CMS-authored block class names for
16
- Tailwind `@source inline()` generation.
17
-
18
- ## 0.2.0-beta.9
19
-
20
- - Preserved repeated Gutenberg RichText spacing across `<br>` sequences,
21
- legacy empty paragraphs and literal double/triple newlines.
22
-
23
- ## 0.2.0-beta.8
24
-
25
- - Applied Gutenberg `anchor` and `className` attributes to each rendered
26
- block root, merging custom classes with the required FlowPress renderer
27
- classes and preserving transparent template blocks when neither is set.
28
-
29
- ## 0.2.0-beta.5
30
-
31
- - Split Gutenberg rendering into dedicated hero, responsive layout, text,
32
- list/template and CF7 modules.
33
- - Added semantic foreground/modifier propagation and core text block
34
- rendering.
35
- - Added responsive 12-column inheritance, token-based partial containers,
36
- hero media/scrim rendering and reduced-motion handling.
37
- - Added repeated query-item template rendering with the previous plain-list
38
- fallback.
39
- - Added an accessible Turnstile/CF7 browser form compatible with static and
40
- server builds.
41
- - Added Astro component checking to the release gate.
42
-
43
- ## 0.2.0-beta.4
44
-
45
- - Updated the exact StyleFlow Astro dependency to `0.3.0-beta.2`.
46
- - Validated the npm Trusted Publisher path with a new OIDC-only publication.
47
-
48
5
  ## 0.2.0-beta.3
49
6
 
50
7
  - Updated the exact StyleFlow Astro dependency to `0.3.0-beta.1`.
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.11
12
+ pnpm add @styleflow.app/flowpress-astro-core@0.2.0-beta.3
13
13
  ```
14
14
 
15
15
  Prereleases are pinned exactly. The package expects Astro 7 or newer and the
@@ -30,20 +30,6 @@ For local Cloudflare development, prefer an HTTP loopback endpoint dedicated
30
30
  to server-to-server traffic. Keep the public HTTPS backend URL separate for
31
31
  canonical URL rewriting.
32
32
 
33
- `GutenbergRenderer.astro` renders the responsive hero/grid/column contract,
34
- StyleFlow text axes and resolved content/query templates. CF7 schemas
35
- serialized by WordPress become accessible client forms that submit directly
36
- to the protected FlowPress REST endpoint, so the same component works in
37
- static and server output modes. Gutenberg `anchor` and `className` attributes
38
- are applied to the rendered block root as HTML `id` and `class`. Rich Text
39
- preserves intentional double, triple and longer line breaks, including content
40
- saved by older editor versions as empty paragraphs. Empty textual blocks render
41
- an internal `&nbsp;`, preserving their typographic line height without adding
42
- visible characters. The exported
43
- `collectFlowpressClassNames()` helper recursively extracts safe class tokens
44
- from rendered CMS blocks so consumers can generate Tailwind
45
- `@source inline()` directives before compiling their frontend CSS.
46
-
47
33
  ## Release
48
34
 
49
35
  ```bash
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  import type { SfSeo } from "../types.js";
3
- import S from "@styleflow.app/astro/S.astro";
4
3
 
5
4
  interface Props {
6
5
  lang?: string;
@@ -45,8 +44,6 @@ const jsonLd = seo?.jsonLd ? JSON.stringify(seo.jsonLd) : null;
45
44
  <slot name="head" />
46
45
  </head>
47
46
  <body>
48
- <S.main tone="neutral" intensity={1} surface="default" layoutRole="none" density="md">
49
- <slot />
50
- </S.main>
47
+ <slot />
51
48
  </body>
52
49
  </html>
@@ -7,38 +7,28 @@ import type { FlowpressTemplateProps } from "../types.js";
7
7
  const { route, content, styleflowContract } = Astro.props as FlowpressTemplateProps;
8
8
  const title = content?.title || route.seo?.title || "Contenuto";
9
9
  const isNotFound = route.queryType === "404" || route.status === 404;
10
- const hasGutembergBlocks = Array.isArray(content?.contentBlocks) && content.contentBlocks.length > 0 ? true : false;
11
- //TODO SET GLOBAL LOCAL ON ENV
12
10
  ---
13
11
 
14
12
  <BaseLayout lang={route.locale || "it"} seo={route.seo}>
15
-
16
- {hasGutembergBlocks ? (
17
- <GutenbergRenderer
18
- blocks={content?.contentBlocks as import("../types.js").FlowpressBlock[]}
19
- contract={styleflowContract}
20
- />
21
- ) : (
22
- <S.section tone="neutral" intensity={1} surface="default" layoutRole="section" density="md">
23
- <S.h1 ty="heading" v="1" w="strong">{isNotFound ? "Pagina non trovata" : title}</S.h1>
24
- {content?.excerpt && <S.p ty="body" v="md" w="default">{content.excerpt}</S.p>}
25
- {Array.isArray(content?.contentBlocks) && content.contentBlocks.length > 0 ? (
26
- <GutenbergRenderer
27
- blocks={content.contentBlocks as import("../types.js").FlowpressBlock[]}
28
- contract={styleflowContract}
29
- />
30
- ) : content?.content && (
31
- <S.div
32
- tone="neutral"
33
- intensity={1}
34
- surface="default"
35
- layoutRole="stack"
36
- density="md"
37
- set:html={String(content.content)}
38
- />
39
- )}
40
- </S.section>
41
- )}
42
-
43
-
13
+ <S.main tone="neutral" intensity={1} surface="default" layoutRole="container" density="md">
14
+ <S.section tone="neutral" intensity={1} surface="default" layoutRole="section" density="md">
15
+ <S.h1 ty="heading" v="1" w="strong">{isNotFound ? "Pagina non trovata" : title}</S.h1>
16
+ {content?.excerpt && <S.p ty="body" v="md" w="default">{content.excerpt}</S.p>}
17
+ {Array.isArray(content?.contentBlocks) && content.contentBlocks.length > 0 ? (
18
+ <GutenbergRenderer
19
+ blocks={content.contentBlocks as import("../types.js").FlowpressBlock[]}
20
+ contract={styleflowContract}
21
+ />
22
+ ) : content?.content && (
23
+ <S.div
24
+ tone="neutral"
25
+ intensity={1}
26
+ surface="default"
27
+ layoutRole="stack"
28
+ density="md"
29
+ set:html={String(content.content)}
30
+ />
31
+ )}
32
+ </S.section>
33
+ </S.main>
44
34
  </BaseLayout>
@@ -1,20 +1,10 @@
1
1
  ---
2
2
  import S from "@styleflow.app/astro/S.astro";
3
- import type { StyleflowContract } from "../styleflow.js";
4
- import type { FlowpressBlock } from "../types.js";
5
- import ColumnBlock from "./blocks/ColumnBlock.astro";
6
- import FormBlock from "./blocks/FormBlock.astro";
7
- import GridBlock from "./blocks/GridBlock.astro";
8
- import HeroBlock from "./blocks/HeroBlock.astro";
9
- import ListItemFallback from "./blocks/ListItemFallback.astro";
10
- import TextBlock from "./blocks/TextBlock.astro";
11
3
  import {
12
- blockHtmlAttributes,
13
- linkValue,
14
- objectValue,
15
- semanticProps,
16
- textValue
17
- } from "./blocks/helpers.js";
4
+ resolveDynamicStyleflowProps,
5
+ type StyleflowContract
6
+ } from "../styleflow.js";
7
+ import type { FlowpressBlock } from "../types.js";
18
8
 
19
9
  interface Props {
20
10
  blocks: FlowpressBlock[];
@@ -23,6 +13,57 @@ interface Props {
23
13
 
24
14
  const { blocks, contract } = Astro.props;
25
15
 
16
+ const defaults = {
17
+ surface: "default",
18
+ layoutRole: "stack",
19
+ density: "md"
20
+ };
21
+
22
+ function styleflowProps(attributes: Record<string, unknown>) {
23
+ if (!contract) return defaults;
24
+ return resolveDynamicStyleflowProps(attributes, defaults, contract);
25
+ }
26
+
27
+ function dynamicProps(
28
+ attributes: Record<string, unknown>,
29
+ fallback: Record<string, unknown>
30
+ ) {
31
+ if (!contract) return fallback;
32
+ return resolveDynamicStyleflowProps(attributes, fallback, contract);
33
+ }
34
+
35
+ function text(block: FlowpressBlock, key = "text"): string {
36
+ return String(block.attributes[key] ?? "");
37
+ }
38
+
39
+ function objectValue(
40
+ block: FlowpressBlock,
41
+ key: string
42
+ ): Record<string, unknown> {
43
+ const value = block.attributes[key];
44
+ return value && typeof value === "object" && !Array.isArray(value)
45
+ ? value as Record<string, unknown>
46
+ : {};
47
+ }
48
+
49
+ function linkValue(block: FlowpressBlock, key = "link"): string {
50
+ const value = block.attributes[key];
51
+ const href = typeof value === "string"
52
+ ? value
53
+ : String(objectValue(block, key).url ?? "");
54
+ if (/^(?:\/(?!\/)|#|https?:\/\/|mailto:|tel:)/i.test(href)) {
55
+ return href;
56
+ }
57
+ return "";
58
+ }
59
+
60
+ function itemImage(item: Record<string, unknown>): Record<string, unknown> {
61
+ const value = item.image;
62
+ return value && typeof value === "object" && !Array.isArray(value)
63
+ ? value as Record<string, unknown>
64
+ : {};
65
+ }
66
+
26
67
  function youtubeEmbedUrl(value: unknown): string | null {
27
68
  try {
28
69
  const url = new URL(String(value ?? ""));
@@ -44,64 +85,52 @@ function youtubeEmbedUrl(value: unknown): string | null {
44
85
  {blocks.map((block) => {
45
86
  const name = block.name.replace(/^sf\//, "");
46
87
  const children = block.innerBlocks ?? [];
47
- const semantic = semanticProps(block.attributes, contract);
48
- const htmlAttributes = blockHtmlAttributes(block.attributes);
88
+ const semantic = styleflowProps(block.attributes);
49
89
 
50
- if (name === "hero") {
51
- return (
52
- <HeroBlock block={block} contract={contract}>
53
- <Astro.self blocks={children} contract={contract} />
54
- </HeroBlock>
90
+ if (name === "heading") {
91
+ const level = Math.min(6, Math.max(1, Number(block.attributes.level ?? 2)));
92
+ const headingTag = `h${level}` as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
93
+ const typography = dynamicProps(
94
+ {
95
+ ty: "heading",
96
+ v: String(block.attributes.variant ?? level),
97
+ w: String(block.attributes.weight ?? "strong")
98
+ },
99
+ { ty: "heading", v: String(level), w: "strong" }
55
100
  );
56
- }
57
-
58
- if (name === "grid") {
59
101
  return (
60
- <GridBlock block={block} contract={contract}>
61
- <Astro.self blocks={children} contract={contract} />
62
- </GridBlock>
63
- );
64
- }
65
-
66
- if (name === "column") {
67
- return (
68
- <ColumnBlock block={block} contract={contract}>
69
- <Astro.self blocks={children} contract={contract} />
70
- </ColumnBlock>
102
+ <S
103
+ as={headingTag}
104
+ {...semantic}
105
+ {...typography}
106
+ set:html={text(block)}
107
+ />
71
108
  );
72
109
  }
73
110
 
74
- if ([
75
- "heading",
76
- "rich-text",
77
- "quote",
78
- "core/paragraph",
79
- "core/heading",
80
- "core/list",
81
- "core/list-item",
82
- "core/quote"
83
- ].includes(name)) {
84
- return (
85
- <TextBlock block={block} contract={contract} hasChildren={children.length > 0}>
86
- <Astro.self blocks={children} contract={contract} />
87
- </TextBlock>
88
- );
111
+ if (name === "rich-text" || name === "core/paragraph") {
112
+ const html = String(block.attributes.content ?? block.innerHtml ?? "");
113
+ return <S as="div" {...semantic} set:html={html} />;
89
114
  }
90
115
 
91
116
  if (name === "button") {
92
117
  const href = linkValue(block, "href") || "#";
93
- const link = objectValue(block, "href");
94
- const opensInNewTab = Boolean(link.opensInNewTab);
118
+ const interaction = dynamicProps(
119
+ {
120
+ interactivePriority: String(
121
+ block.attributes.interactivePriority ?? "primary"
122
+ )
123
+ },
124
+ { interactivePriority: "primary" }
125
+ );
95
126
  return (
96
127
  <S
97
128
  as="a"
98
129
  href={href}
99
- target={opensInNewTab ? "_blank" : undefined}
100
- rel={opensInNewTab ? "noopener noreferrer" : undefined}
101
130
  {...semantic}
102
- {...htmlAttributes}
131
+ {...interaction}
103
132
  >
104
- {textValue(block, "label")}
133
+ {text(block, "label")}
105
134
  </S>
106
135
  );
107
136
  }
@@ -115,7 +144,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
115
144
  } | undefined;
116
145
  const src = image?.url ?? image?.sourceUrl;
117
146
  return src ? (
118
- <S as="div" {...semantic} {...htmlAttributes}>
147
+ <S as="div" {...semantic}>
119
148
  <img
120
149
  src={src}
121
150
  alt={String(block.attributes.alt ?? image?.alt ?? image?.altText ?? "")}
@@ -131,7 +160,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
131
160
  ? block.attributes.images as Array<Record<string, unknown>>
132
161
  : [];
133
162
  return (
134
- <S as="div" {...semantic} {...htmlAttributes}>
163
+ <S as="div" {...semantic}>
135
164
  {images.map((image) => image.url ? (
136
165
  <img
137
166
  src={String(image.url)}
@@ -148,7 +177,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
148
177
  const video = objectValue(block, "video");
149
178
  const poster = objectValue(block, "poster");
150
179
  return video.url ? (
151
- <S as="div" {...semantic} {...htmlAttributes}>
180
+ <S as="div" {...semantic}>
152
181
  <video
153
182
  src={String(video.url)}
154
183
  poster={poster.url ? String(poster.url) : undefined}
@@ -164,7 +193,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
164
193
  if (name === "video-youtube") {
165
194
  const embed = youtubeEmbedUrl(block.attributes.url);
166
195
  return embed ? (
167
- <S as="div" {...semantic} {...htmlAttributes}>
196
+ <S as="div" {...semantic}>
168
197
  <iframe
169
198
  src={embed}
170
199
  title={String(block.attributes.title ?? "YouTube video")}
@@ -176,19 +205,24 @@ function youtubeEmbedUrl(value: unknown): string | null {
176
205
  ) : null;
177
206
  }
178
207
 
179
- if (name === "chip") {
208
+ if (name === "quote") {
180
209
  return (
181
- <S as="span" {...semantic} {...htmlAttributes}>
182
- {textValue(block, "label")}
210
+ <S as="blockquote" {...semantic}>
211
+ <S as="p" set:html={text(block, "quote")} />
212
+ {block.attributes.citation && <cite>{String(block.attributes.citation)}</cite>}
183
213
  </S>
184
214
  );
185
215
  }
186
216
 
217
+ if (name === "chip") {
218
+ return <S as="span" {...semantic}>{text(block, "label")}</S>;
219
+ }
220
+
187
221
  if (name === "card") {
188
222
  const media = objectValue(block, "image");
189
223
  const href = linkValue(block);
190
224
  return (
191
- <S as="article" {...semantic} {...htmlAttributes}>
225
+ <S as="article" {...semantic}>
192
226
  {media.url && (
193
227
  <img src={String(media.url)} alt={String(media.alt ?? "")} loading="lazy" />
194
228
  )}
@@ -203,41 +237,34 @@ function youtubeEmbedUrl(value: unknown): string | null {
203
237
  const items = Array.isArray(block.attributes.resolvedItems)
204
238
  ? block.attributes.resolvedItems as Array<Record<string, unknown>>
205
239
  : [];
206
- const resolvedBlocks = Array.isArray(block.attributes.resolvedBlocks)
207
- ? block.attributes.resolvedBlocks as FlowpressBlock[][]
208
- : [];
209
240
  return (
210
- <S as="ul" {...semantic} {...htmlAttributes}>
211
- {items.map((item, index) => (
241
+ <S as="ul" {...semantic}>
242
+ {items.map((item) => (
212
243
  <S as="li">
213
- {resolvedBlocks[index]?.length ? (
214
- <Astro.self blocks={resolvedBlocks[index]} contract={contract} />
244
+ {itemImage(item).url && (
245
+ <img
246
+ src={String(itemImage(item).url)}
247
+ alt={String(itemImage(item).alt ?? "")}
248
+ loading="lazy"
249
+ decoding="async"
250
+ />
251
+ )}
252
+ {item.uri ? (
253
+ <S as="a" href={String(item.uri)}>{String(item.title ?? "")}</S>
215
254
  ) : (
216
- <ListItemFallback item={item} />
255
+ <S as="span">{String(item.title ?? "")}</S>
217
256
  )}
257
+ {item.excerpt && <S as="p">{String(item.excerpt)}</S>}
258
+ {item.priceHtml && <S as="div" set:html={String(item.priceHtml)} />}
218
259
  </S>
219
260
  ))}
220
261
  </S>
221
262
  );
222
263
  }
223
264
 
224
- if (name === "template") {
225
- return Object.keys(htmlAttributes).length > 0 ? (
226
- <div {...htmlAttributes}>
227
- <Astro.self blocks={children} contract={contract} />
228
- </div>
229
- ) : (
230
- <Astro.self blocks={children} contract={contract} />
231
- );
232
- }
233
-
234
- if (name === "form") {
235
- return <FormBlock block={block} contract={contract} />;
236
- }
237
-
238
265
  if (name === "accordion-item") {
239
266
  return (
240
- <S as="div" {...semantic} {...htmlAttributes}>
267
+ <S as="div" {...semantic}>
241
268
  <details>
242
269
  <summary>{String(block.attributes.title ?? "")}</summary>
243
270
  <Astro.self blocks={children} contract={contract} />
@@ -263,7 +290,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
263
290
  + `?key=${encodeURIComponent(googleMapsApiKey)}`
264
291
  + `&q=${encodeURIComponent(query)}`;
265
292
  return (
266
- <S as="div" {...semantic} {...htmlAttributes}>
293
+ <S as="div" {...semantic}>
267
294
  <iframe
268
295
  src={source}
269
296
  title={address || "Map"}
@@ -274,7 +301,7 @@ function youtubeEmbedUrl(value: unknown): string | null {
274
301
  );
275
302
  }
276
303
  return query ? (
277
- <S as="div" {...semantic} {...htmlAttributes}>
304
+ <S as="div" {...semantic}>
278
305
  <S
279
306
  as="a"
280
307
  href={`https://www.openstreetmap.org/search?query=${encodeURIComponent(query)}`}
@@ -286,9 +313,9 @@ function youtubeEmbedUrl(value: unknown): string | null {
286
313
  ) : null;
287
314
  }
288
315
 
289
- const layoutTag = name === "section" ? "section" : "div";
316
+ const layoutTag = ["section", "hero"].includes(name) ? "section" : "div";
290
317
  return (
291
- <S as={layoutTag} {...semantic} {...htmlAttributes}>
318
+ <S as={layoutTag} {...semantic}>
292
319
  {block.innerHtml && children.length === 0
293
320
  ? <S as="div" set:html={block.innerHtml} />
294
321
  : <Astro.self blocks={children} contract={contract} />}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from "./client.js";
2
2
  export * from "./env.js";
3
3
  export * from "./styleflow.js";
4
- export * from "./style-classes.js";
5
4
  export * from "./template-hierarchy.js";
6
5
  export * from "./types.js";
7
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from "./client.js";
2
2
  export * from "./env.js";
3
3
  export * from "./styleflow.js";
4
- export * from "./style-classes.js";
5
4
  export * from "./template-hierarchy.js";
6
5
  export * from "./types.js";
7
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./client.js\";\nexport * from \"./env.js\";\nexport * from \"./styleflow.js\";\nexport * from \"./style-classes.js\";\nexport * from \"./template-hierarchy.js\";\nexport * from \"./types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./client.js\";\nexport * from \"./env.js\";\nexport * from \"./styleflow.js\";\nexport * from \"./template-hierarchy.js\";\nexport * from \"./types.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"styleflow.d.ts","sourceRoot":"","sources":["../src/styleflow.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,WAAW,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,qBAAqB,CAAC;CAC7B;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAqB5D;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,qBAAqB,EAC5B,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB,CA+CvB"}
1
+ {"version":3,"file":"styleflow.d.ts","sourceRoot":"","sources":["../src/styleflow.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,WAAW,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,qBAAqB,CAAC;CAC7B;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoB5D;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,qBAAqB,EAC5B,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,iBAAiB,GAC1B,qBAAqB,CAwCvB"}
package/dist/styleflow.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const INHERITED_COLOR_PROPS = new Set(["tone", "intensity"]);
2
- const FOREGROUND_ROLES = ["primary", "secondary", "tertiary", "muted", "accent"];
3
2
  const AXIS_BY_PROP = {
4
3
  tone: ["color", "tones"],
5
4
  intensity: ["color", "intensities"],
@@ -36,12 +35,6 @@ export function resolveDynamicStyleflowProps(input, defaults, contract) {
36
35
  : defaults.v;
37
36
  continue;
38
37
  }
39
- if (key === "foreground") {
40
- resolved.foreground = FOREGROUND_ROLES.includes(String(value))
41
- ? value
42
- : defaults.foreground;
43
- continue;
44
- }
45
38
  const axisPath = AXIS_BY_PROP[key];
46
39
  if (!axisPath) {
47
40
  resolved[key] = value;
@@ -1 +1 @@
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\"]);\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"]}
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;AAE7D,MAAM,YAAY,GAAG;IACnB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC;IACnC,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9B,UAAU,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC/B,OAAO,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;IAChC,EAAE,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC;IAC3B,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;IAC5B,mBAAmB,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC;IAClD,gBAAgB,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;CACnC,CAAC;AAEX,SAAS,aAAa,CAAC,SAAkB,EAAE,OAAgB;IACzD,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAA4B,EAC5B,QAA+B,EAC/B,QAA2B;IAE3B,MAAM,QAAQ,GAA0B,EAAE,GAAG,QAAQ,EAAE,CAAC;IAExD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,IAAI,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/D,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACpE,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAgC,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACtB,SAAS;QACX,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAGvB,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,QAAQ,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAChE,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","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\"]);\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 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"]}
@@ -1 +1 @@
1
- {"root":["../src/astro.d.ts","../src/client.ts","../src/env.ts","../src/index.ts","../src/style-classes.ts","../src/styleflow.ts","../src/template-hierarchy.ts","../src/templates.ts","../src/types.ts","../src/astro/blocks/helpers.ts"],"version":"5.9.3"}
1
+ {"root":["../src/astro.d.ts","../src/client.ts","../src/env.ts","../src/index.ts","../src/styleflow.ts","../src/template-hierarchy.ts","../src/templates.ts","../src/types.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@styleflow.app/flowpress-astro-core",
3
- "version": "0.2.0-beta.11",
3
+ "version": "0.2.0-beta.3",
4
4
  "description": "Project-agnostic WordPress routing, templates, SEO and GraphQL runtime for FlowPress Astro apps.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "scripts": {
37
37
  "build": "tsc -b && node ./scripts/copy-astro.mjs",
38
- "typecheck": "tsc -b --pretty false && node ./scripts/copy-astro.mjs && astro check",
38
+ "typecheck": "tsc -b --pretty false && node ./scripts/copy-astro.mjs",
39
39
  "test": "vitest run",
40
40
  "release:check": "npm run typecheck && npm test && npm pack --dry-run",
41
41
  "release:publish:next": "npm publish --access public --tag next",
@@ -43,13 +43,12 @@
43
43
  "prepublishOnly": "npm run typecheck && npm test && npm run build"
44
44
  },
45
45
  "dependencies": {
46
- "@styleflow.app/astro": "0.3.0-beta.3"
46
+ "@styleflow.app/astro": "0.3.0-beta.1"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "astro": ">=7.0.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@astrojs/check": "^0.9.9",
53
52
  "@types/node": "^22.19.3",
54
53
  "astro": "^7.0.4",
55
54
  "typescript": "^5.9.3",