@styleflow.app/flowpress-astro-core 0.2.0-beta.11 → 0.2.0-beta.2
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 +0 -49
- package/README.md +1 -22
- package/dist/astro/BaseLayout.astro +1 -4
- package/dist/astro/DefaultTemplate.astro +21 -31
- package/dist/astro/GutenbergRenderer.astro +118 -91
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/styleflow.d.ts.map +1 -1
- package/dist/styleflow.js +0 -7
- package/dist/styleflow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -4
- package/dist/astro/blocks/ColumnBlock.astro +0 -83
- package/dist/astro/blocks/FormBlock.astro +0 -233
- package/dist/astro/blocks/GridBlock.astro +0 -70
- package/dist/astro/blocks/HeroBlock.astro +0 -113
- package/dist/astro/blocks/ListItemFallback.astro +0 -28
- package/dist/astro/blocks/TextBlock.astro +0 -83
- package/dist/astro/blocks/helpers.d.ts +0 -26
- package/dist/astro/blocks/helpers.d.ts.map +0 -1
- package/dist/astro/blocks/helpers.js +0 -108
- package/dist/astro/blocks/helpers.js.map +0 -1
- package/dist/astro/blocks/helpers.ts +0 -148
- package/dist/style-classes.d.ts +0 -9
- package/dist/style-classes.d.ts.map +0 -1
- package/dist/style-classes.js +0 -47
- package/dist/style-classes.js.map +0 -1
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
4
|
-
import type { StyleflowContract } from "../../styleflow.js";
|
|
5
|
-
import {
|
|
6
|
-
blockHtmlAttributes,
|
|
7
|
-
responsiveValues,
|
|
8
|
-
semanticProps
|
|
9
|
-
} from "./helpers.js";
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
block: FlowpressBlock;
|
|
13
|
-
contract?: StyleflowContract;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const { block, contract } = Astro.props;
|
|
17
|
-
const values = responsiveValues(block.attributes, "span", 1);
|
|
18
|
-
const partial = ["start", "end"].includes(String(block.attributes.partialContainer))
|
|
19
|
-
? String(block.attributes.partialContainer)
|
|
20
|
-
: "none";
|
|
21
|
-
const partialBreakpoint = ["base", "sm", "md", "lg", "xl", "2xl"].includes(
|
|
22
|
-
String(block.attributes.partialContainerBreakpoint)
|
|
23
|
-
) ? String(block.attributes.partialContainerBreakpoint) : "lg";
|
|
24
|
-
const semantic = semanticProps(block.attributes, contract);
|
|
25
|
-
const htmlAttributes = blockHtmlAttributes(block.attributes, "flowpress-column");
|
|
26
|
-
const style = [
|
|
27
|
-
`--flowpress-span-base:${values.base}`,
|
|
28
|
-
`--flowpress-span-sm:${values.sm}`,
|
|
29
|
-
`--flowpress-span-md:${values.md}`,
|
|
30
|
-
`--flowpress-span-lg:${values.lg}`,
|
|
31
|
-
`--flowpress-span-xl:${values.xl}`,
|
|
32
|
-
`--flowpress-span-2xl:${values["2xl"]}`
|
|
33
|
-
].join(";");
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
<S
|
|
37
|
-
as="div"
|
|
38
|
-
{...semantic}
|
|
39
|
-
{...htmlAttributes}
|
|
40
|
-
data-partial={partial}
|
|
41
|
-
data-partial-breakpoint={partialBreakpoint}
|
|
42
|
-
style={style}
|
|
43
|
-
>
|
|
44
|
-
<slot />
|
|
45
|
-
</S>
|
|
46
|
-
|
|
47
|
-
<style>
|
|
48
|
-
.flowpress-column {
|
|
49
|
-
grid-column: span var(--flowpress-span-base) / span var(--flowpress-span-base);
|
|
50
|
-
min-width: 0;
|
|
51
|
-
}
|
|
52
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="base"] {
|
|
53
|
-
padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2));
|
|
54
|
-
}
|
|
55
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="base"] {
|
|
56
|
-
padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2));
|
|
57
|
-
}
|
|
58
|
-
@media (min-width: 40rem) {
|
|
59
|
-
.flowpress-column { grid-column: span var(--flowpress-span-sm) / span var(--flowpress-span-sm); }
|
|
60
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="sm"] { padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
61
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="sm"] { padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
62
|
-
}
|
|
63
|
-
@media (min-width: 48rem) {
|
|
64
|
-
.flowpress-column { grid-column: span var(--flowpress-span-md) / span var(--flowpress-span-md); }
|
|
65
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="md"] { padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
66
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="md"] { padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
67
|
-
}
|
|
68
|
-
@media (min-width: 64rem) {
|
|
69
|
-
.flowpress-column { grid-column: span var(--flowpress-span-lg) / span var(--flowpress-span-lg); }
|
|
70
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="lg"] { padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
71
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="lg"] { padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
72
|
-
}
|
|
73
|
-
@media (min-width: 80rem) {
|
|
74
|
-
.flowpress-column { grid-column: span var(--flowpress-span-xl) / span var(--flowpress-span-xl); }
|
|
75
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="xl"] { padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
76
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="xl"] { padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
77
|
-
}
|
|
78
|
-
@media (min-width: 96rem) {
|
|
79
|
-
.flowpress-column { grid-column: span var(--flowpress-span-2xl) / span var(--flowpress-span-2xl); }
|
|
80
|
-
.flowpress-column[data-partial="start"][data-partial-breakpoint="2xl"] { padding-inline-start: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
81
|
-
.flowpress-column[data-partial="end"][data-partial-breakpoint="2xl"] { padding-inline-end: max(var(--sf-padding-inline, 0px), calc((100vw - var(--sf-container-max-width, 100vw)) / 2)); }
|
|
82
|
-
}
|
|
83
|
-
</style>
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
4
|
-
import type { StyleflowContract } from "../../styleflow.js";
|
|
5
|
-
import { blockHtmlAttributes, semanticProps } from "./helpers.js";
|
|
6
|
-
|
|
7
|
-
interface FormField {
|
|
8
|
-
name: string;
|
|
9
|
-
type: string;
|
|
10
|
-
required?: boolean;
|
|
11
|
-
values?: string[];
|
|
12
|
-
labels?: string[];
|
|
13
|
-
options?: string[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface FormSchema {
|
|
17
|
-
id: number;
|
|
18
|
-
title: string;
|
|
19
|
-
fields: FormField[];
|
|
20
|
-
submitUrl: string;
|
|
21
|
-
turnstileSiteKey: string;
|
|
22
|
-
available: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface Props {
|
|
26
|
-
block: FlowpressBlock;
|
|
27
|
-
contract?: StyleflowContract;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const { block, contract } = Astro.props;
|
|
31
|
-
const schema = block.attributes.formSchema as FormSchema | undefined;
|
|
32
|
-
const semantic = semanticProps(block.attributes, contract);
|
|
33
|
-
const htmlAttributes = blockHtmlAttributes(block.attributes);
|
|
34
|
-
const labelFor = (field: FormField): string => field.name
|
|
35
|
-
.replace(/[-_]+/g, " ")
|
|
36
|
-
.replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
37
|
-
const optionLabel = (field: FormField, index: number): string =>
|
|
38
|
-
field.labels?.[index] || field.values?.[index] || "";
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
{schema?.available ? (
|
|
42
|
-
<S as="div" {...semantic} {...htmlAttributes}>
|
|
43
|
-
<flowpress-cf7-form>
|
|
44
|
-
<form action={schema.submitUrl} method="post" enctype="multipart/form-data" novalidate>
|
|
45
|
-
{block.attributes.title || schema.title ? (
|
|
46
|
-
<S as="h2">{String(block.attributes.title || schema.title)}</S>
|
|
47
|
-
) : null}
|
|
48
|
-
{schema.fields.map((field) => {
|
|
49
|
-
if (field.type === "submit") {
|
|
50
|
-
return (
|
|
51
|
-
<button type="submit">
|
|
52
|
-
{field.values?.[0] || "Invia"}
|
|
53
|
-
</button>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
if (field.type === "hidden") {
|
|
57
|
-
return <input type="hidden" name={field.name} value={field.values?.[0] || ""} />;
|
|
58
|
-
}
|
|
59
|
-
if (["checkbox", "radio"].includes(field.type)) {
|
|
60
|
-
return (
|
|
61
|
-
<fieldset>
|
|
62
|
-
<legend>{labelFor(field)}</legend>
|
|
63
|
-
{(field.values || []).map((value, index) => (
|
|
64
|
-
<label>
|
|
65
|
-
<input
|
|
66
|
-
type={field.type}
|
|
67
|
-
name={field.type === "checkbox" ? `${field.name}[]` : field.name}
|
|
68
|
-
value={value}
|
|
69
|
-
required={field.required}
|
|
70
|
-
/>
|
|
71
|
-
{optionLabel(field, index)}
|
|
72
|
-
</label>
|
|
73
|
-
))}
|
|
74
|
-
<span data-field-error={field.name}></span>
|
|
75
|
-
</fieldset>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
if (field.type === "acceptance") {
|
|
79
|
-
return (
|
|
80
|
-
<label>
|
|
81
|
-
<input type="checkbox" name={field.name} value="1" required={field.required} />
|
|
82
|
-
{field.values?.[0] || labelFor(field)}
|
|
83
|
-
<span data-field-error={field.name}></span>
|
|
84
|
-
</label>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
if (field.type === "select") {
|
|
88
|
-
return (
|
|
89
|
-
<label>
|
|
90
|
-
{labelFor(field)}
|
|
91
|
-
<select
|
|
92
|
-
name={field.options?.includes("multiple") ? `${field.name}[]` : field.name}
|
|
93
|
-
required={field.required}
|
|
94
|
-
multiple={field.options?.includes("multiple")}
|
|
95
|
-
>
|
|
96
|
-
{(field.values || []).map((value, index) => (
|
|
97
|
-
<option value={value}>{optionLabel(field, index)}</option>
|
|
98
|
-
))}
|
|
99
|
-
</select>
|
|
100
|
-
<span data-field-error={field.name}></span>
|
|
101
|
-
</label>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
if (field.type === "textarea") {
|
|
105
|
-
return (
|
|
106
|
-
<label>
|
|
107
|
-
{labelFor(field)}
|
|
108
|
-
<textarea name={field.name} required={field.required}></textarea>
|
|
109
|
-
<span data-field-error={field.name}></span>
|
|
110
|
-
</label>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
return (
|
|
114
|
-
<label>
|
|
115
|
-
{labelFor(field)}
|
|
116
|
-
<input
|
|
117
|
-
type={field.type === "file" ? "file" : field.type}
|
|
118
|
-
name={field.name}
|
|
119
|
-
required={field.required}
|
|
120
|
-
/>
|
|
121
|
-
<span data-field-error={field.name}></span>
|
|
122
|
-
</label>
|
|
123
|
-
);
|
|
124
|
-
})}
|
|
125
|
-
<div
|
|
126
|
-
data-turnstile
|
|
127
|
-
data-sitekey={schema.turnstileSiteKey}
|
|
128
|
-
aria-label="Verifica anti-spam"
|
|
129
|
-
></div>
|
|
130
|
-
<p data-form-status role="status" aria-live="polite"></p>
|
|
131
|
-
</form>
|
|
132
|
-
</flowpress-cf7-form>
|
|
133
|
-
</S>
|
|
134
|
-
) : (
|
|
135
|
-
<S as="p" {...semantic} {...htmlAttributes} role="status">
|
|
136
|
-
Il modulo non è temporaneamente disponibile.
|
|
137
|
-
</S>
|
|
138
|
-
)}
|
|
139
|
-
|
|
140
|
-
<script>
|
|
141
|
-
declare global {
|
|
142
|
-
interface Window {
|
|
143
|
-
turnstile?: {
|
|
144
|
-
render(target: Element, options: Record<string, unknown>): string;
|
|
145
|
-
reset(widgetId?: string): void;
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
let turnstilePromise: Promise<void> | undefined;
|
|
151
|
-
const loadTurnstile = (): Promise<void> => {
|
|
152
|
-
if (window.turnstile) return Promise.resolve();
|
|
153
|
-
if (turnstilePromise) return turnstilePromise;
|
|
154
|
-
turnstilePromise = new Promise((resolve, reject) => {
|
|
155
|
-
const existing = document.querySelector<HTMLScriptElement>(
|
|
156
|
-
'script[data-flowpress-turnstile]'
|
|
157
|
-
);
|
|
158
|
-
if (existing) {
|
|
159
|
-
existing.addEventListener("load", () => resolve(), { once: true });
|
|
160
|
-
existing.addEventListener("error", () => reject(new Error("Turnstile unavailable")), { once: true });
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
const script = document.createElement("script");
|
|
164
|
-
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
|
165
|
-
script.async = true;
|
|
166
|
-
script.defer = true;
|
|
167
|
-
script.dataset.flowpressTurnstile = "true";
|
|
168
|
-
script.addEventListener("load", () => resolve(), { once: true });
|
|
169
|
-
script.addEventListener("error", () => reject(new Error("Turnstile unavailable")), { once: true });
|
|
170
|
-
document.head.append(script);
|
|
171
|
-
});
|
|
172
|
-
return turnstilePromise;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
if (!customElements.get("flowpress-cf7-form")) {
|
|
176
|
-
customElements.define("flowpress-cf7-form", class extends HTMLElement {
|
|
177
|
-
private widgetId?: string;
|
|
178
|
-
|
|
179
|
-
connectedCallback() {
|
|
180
|
-
const form = this.querySelector<HTMLFormElement>("form");
|
|
181
|
-
const target = this.querySelector<HTMLElement>("[data-turnstile]");
|
|
182
|
-
const status = this.querySelector<HTMLElement>("[data-form-status]");
|
|
183
|
-
if (!form || !target || !status) return;
|
|
184
|
-
|
|
185
|
-
loadTurnstile()
|
|
186
|
-
.then(() => {
|
|
187
|
-
if (!window.turnstile || this.widgetId) return;
|
|
188
|
-
this.widgetId = window.turnstile.render(target, {
|
|
189
|
-
sitekey: target.dataset.sitekey
|
|
190
|
-
});
|
|
191
|
-
})
|
|
192
|
-
.catch(() => {
|
|
193
|
-
status.textContent = "La verifica anti-spam non è disponibile.";
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
form.addEventListener("submit", async (event) => {
|
|
197
|
-
event.preventDefault();
|
|
198
|
-
status.textContent = "Invio in corso…";
|
|
199
|
-
form.querySelectorAll<HTMLElement>("[data-field-error]")
|
|
200
|
-
.forEach((node) => { node.textContent = ""; });
|
|
201
|
-
const submit = form.querySelector<HTMLButtonElement>('[type="submit"]');
|
|
202
|
-
if (submit) submit.disabled = true;
|
|
203
|
-
try {
|
|
204
|
-
const response = await fetch(form.action, {
|
|
205
|
-
method: "POST",
|
|
206
|
-
body: new FormData(form),
|
|
207
|
-
headers: { Accept: "application/json" }
|
|
208
|
-
});
|
|
209
|
-
const result = await response.json() as {
|
|
210
|
-
message?: string;
|
|
211
|
-
invalidFields?: Array<{ field?: string; into?: string; message?: string }>;
|
|
212
|
-
};
|
|
213
|
-
status.textContent = result.message || (response.ok ? "Messaggio inviato." : "Invio non riuscito.");
|
|
214
|
-
for (const invalid of result.invalidFields || []) {
|
|
215
|
-
const name = invalid.field || invalid.into?.replace(/^span\./, "") || "";
|
|
216
|
-
const node = name
|
|
217
|
-
? form.querySelector<HTMLElement>(`[data-field-error="${CSS.escape(name)}"]`)
|
|
218
|
-
: null;
|
|
219
|
-
if (node) node.textContent = invalid.message || "";
|
|
220
|
-
}
|
|
221
|
-
if (response.ok) form.reset();
|
|
222
|
-
if (window.turnstile) window.turnstile.reset(this.widgetId);
|
|
223
|
-
} catch {
|
|
224
|
-
status.textContent = "Impossibile inviare il modulo. Riprova.";
|
|
225
|
-
if (window.turnstile) window.turnstile.reset(this.widgetId);
|
|
226
|
-
} finally {
|
|
227
|
-
if (submit) submit.disabled = false;
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
</script>
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
4
|
-
import type { StyleflowContract } from "../../styleflow.js";
|
|
5
|
-
import {
|
|
6
|
-
blockHtmlAttributes,
|
|
7
|
-
responsiveValues,
|
|
8
|
-
semanticProps
|
|
9
|
-
} from "./helpers.js";
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
block: FlowpressBlock;
|
|
13
|
-
contract?: StyleflowContract;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const { block, contract } = Astro.props;
|
|
17
|
-
const values = responsiveValues(
|
|
18
|
-
block.attributes,
|
|
19
|
-
"columns",
|
|
20
|
-
Number(block.attributes.columns) || 12
|
|
21
|
-
);
|
|
22
|
-
const align = ["start", "center", "end", "stretch"].includes(
|
|
23
|
-
String(block.attributes.align)
|
|
24
|
-
) ? String(block.attributes.align) : "stretch";
|
|
25
|
-
const semantic = semanticProps(block.attributes, contract, {
|
|
26
|
-
surface: "default",
|
|
27
|
-
layoutRole: "container",
|
|
28
|
-
density: "md"
|
|
29
|
-
});
|
|
30
|
-
const htmlAttributes = blockHtmlAttributes(block.attributes, "flowpress-grid");
|
|
31
|
-
const style = [
|
|
32
|
-
`--flowpress-grid-base:${values.base}`,
|
|
33
|
-
`--flowpress-grid-sm:${values.sm}`,
|
|
34
|
-
`--flowpress-grid-md:${values.md}`,
|
|
35
|
-
`--flowpress-grid-lg:${values.lg}`,
|
|
36
|
-
`--flowpress-grid-xl:${values.xl}`,
|
|
37
|
-
`--flowpress-grid-2xl:${values["2xl"]}`
|
|
38
|
-
].join(";");
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
<S as="div" {...semantic} {...htmlAttributes} data-align={align} style={style}>
|
|
42
|
-
<slot />
|
|
43
|
-
</S>
|
|
44
|
-
|
|
45
|
-
<style>
|
|
46
|
-
.flowpress-grid {
|
|
47
|
-
display: grid;
|
|
48
|
-
grid-template-columns: repeat(var(--flowpress-grid-base), minmax(0, 1fr));
|
|
49
|
-
align-items: var(--flowpress-grid-align, stretch);
|
|
50
|
-
}
|
|
51
|
-
.flowpress-grid[data-align="start"] { --flowpress-grid-align: start; }
|
|
52
|
-
.flowpress-grid[data-align="center"] { --flowpress-grid-align: center; }
|
|
53
|
-
.flowpress-grid[data-align="end"] { --flowpress-grid-align: end; }
|
|
54
|
-
.flowpress-grid[data-align="stretch"] { --flowpress-grid-align: stretch; }
|
|
55
|
-
@media (min-width: 40rem) {
|
|
56
|
-
.flowpress-grid { grid-template-columns: repeat(var(--flowpress-grid-sm), minmax(0, 1fr)); }
|
|
57
|
-
}
|
|
58
|
-
@media (min-width: 48rem) {
|
|
59
|
-
.flowpress-grid { grid-template-columns: repeat(var(--flowpress-grid-md), minmax(0, 1fr)); }
|
|
60
|
-
}
|
|
61
|
-
@media (min-width: 64rem) {
|
|
62
|
-
.flowpress-grid { grid-template-columns: repeat(var(--flowpress-grid-lg), minmax(0, 1fr)); }
|
|
63
|
-
}
|
|
64
|
-
@media (min-width: 80rem) {
|
|
65
|
-
.flowpress-grid { grid-template-columns: repeat(var(--flowpress-grid-xl), minmax(0, 1fr)); }
|
|
66
|
-
}
|
|
67
|
-
@media (min-width: 96rem) {
|
|
68
|
-
.flowpress-grid { grid-template-columns: repeat(var(--flowpress-grid-2xl), minmax(0, 1fr)); }
|
|
69
|
-
}
|
|
70
|
-
</style>
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
4
|
-
import type { StyleflowContract } from "../../styleflow.js";
|
|
5
|
-
import {
|
|
6
|
-
blockHtmlAttributes,
|
|
7
|
-
objectValue,
|
|
8
|
-
semanticProps
|
|
9
|
-
} from "./helpers.js";
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
block: FlowpressBlock;
|
|
13
|
-
contract?: StyleflowContract;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const { block, contract } = Astro.props;
|
|
17
|
-
const attributes = block.attributes;
|
|
18
|
-
const semantic = semanticProps(attributes, contract, {
|
|
19
|
-
surface: "default",
|
|
20
|
-
layoutRole: "region",
|
|
21
|
-
density: "md"
|
|
22
|
-
});
|
|
23
|
-
const htmlAttributes = blockHtmlAttributes(attributes, "flowpress-hero");
|
|
24
|
-
const backgroundType = ["color", "image", "video"].includes(
|
|
25
|
-
String(attributes.backgroundType)
|
|
26
|
-
) ? String(attributes.backgroundType) : "color";
|
|
27
|
-
const image = objectValue(block, "backgroundImage");
|
|
28
|
-
const video = objectValue(block, "backgroundVideo");
|
|
29
|
-
const imageSrc = String(image.url ?? image.sourceUrl ?? "");
|
|
30
|
-
const videoSrc = String(video.url ?? video.sourceUrl ?? video.mediaItemUrl ?? "");
|
|
31
|
-
const scrimEnabled = Boolean(attributes.scrimEnabled) && backgroundType !== "color";
|
|
32
|
-
const scrimIntensity = Math.min(10, Math.max(1, Number(attributes.scrimIntensity) || 6));
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
<S
|
|
36
|
-
as="section"
|
|
37
|
-
{...semantic}
|
|
38
|
-
{...htmlAttributes}
|
|
39
|
-
style={`--flowpress-scrim-opacity:${scrimIntensity * 10}%`}
|
|
40
|
-
>
|
|
41
|
-
{backgroundType === "image" && imageSrc ? (
|
|
42
|
-
<img
|
|
43
|
-
class="flowpress-hero__media"
|
|
44
|
-
src={imageSrc}
|
|
45
|
-
alt=""
|
|
46
|
-
aria-hidden="true"
|
|
47
|
-
loading="eager"
|
|
48
|
-
decoding="async"
|
|
49
|
-
/>
|
|
50
|
-
) : null}
|
|
51
|
-
{backgroundType === "video" && videoSrc ? (
|
|
52
|
-
<video
|
|
53
|
-
class="flowpress-hero__media"
|
|
54
|
-
src={videoSrc}
|
|
55
|
-
poster={imageSrc || undefined}
|
|
56
|
-
autoplay
|
|
57
|
-
muted
|
|
58
|
-
loop
|
|
59
|
-
playsinline
|
|
60
|
-
preload="metadata"
|
|
61
|
-
aria-hidden="true"
|
|
62
|
-
tabindex="-1"
|
|
63
|
-
/>
|
|
64
|
-
) : null}
|
|
65
|
-
{scrimEnabled ? <span class="flowpress-hero__scrim" aria-hidden="true"></span> : null}
|
|
66
|
-
<div class="flowpress-hero__content">
|
|
67
|
-
<slot />
|
|
68
|
-
</div>
|
|
69
|
-
</S>
|
|
70
|
-
|
|
71
|
-
<style>
|
|
72
|
-
.flowpress-hero {
|
|
73
|
-
position: relative;
|
|
74
|
-
display: grid;
|
|
75
|
-
overflow: hidden;
|
|
76
|
-
isolation: isolate;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.flowpress-hero__media,
|
|
80
|
-
.flowpress-hero__scrim {
|
|
81
|
-
position: absolute;
|
|
82
|
-
inset: 0;
|
|
83
|
-
width: 100%;
|
|
84
|
-
height: 100%;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.flowpress-hero__media {
|
|
88
|
-
z-index: -2;
|
|
89
|
-
object-fit: cover;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.flowpress-hero__scrim {
|
|
93
|
-
z-index: -1;
|
|
94
|
-
background: color-mix(
|
|
95
|
-
in srgb,
|
|
96
|
-
var(--sf-background) var(--flowpress-scrim-opacity),
|
|
97
|
-
transparent
|
|
98
|
-
);
|
|
99
|
-
pointer-events: none;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.flowpress-hero__content {
|
|
103
|
-
position: relative;
|
|
104
|
-
display: grid;
|
|
105
|
-
gap: inherit;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@media (prefers-reduced-motion: reduce) {
|
|
109
|
-
.flowpress-hero__media:is(video) {
|
|
110
|
-
display: none;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
</style>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
item: Record<string, unknown>;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const { item } = Astro.props;
|
|
9
|
-
const image = item.image && typeof item.image === "object" && !Array.isArray(item.image)
|
|
10
|
-
? item.image as Record<string, unknown>
|
|
11
|
-
: {};
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
{image.url ? (
|
|
15
|
-
<img
|
|
16
|
-
src={String(image.url)}
|
|
17
|
-
alt={String(image.alt ?? "")}
|
|
18
|
-
loading="lazy"
|
|
19
|
-
decoding="async"
|
|
20
|
-
/>
|
|
21
|
-
) : null}
|
|
22
|
-
{item.uri ? (
|
|
23
|
-
<S as="a" href={String(item.uri)}>{String(item.title ?? "")}</S>
|
|
24
|
-
) : (
|
|
25
|
-
<S as="span">{String(item.title ?? "")}</S>
|
|
26
|
-
)}
|
|
27
|
-
{item.excerpt ? <S as="p">{String(item.excerpt)}</S> : null}
|
|
28
|
-
{item.priceHtml ? <S as="div" set:html={String(item.priceHtml)} /> : null}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import S from "@styleflow.app/astro/S.astro";
|
|
3
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
4
|
-
import type { StyleflowContract } from "../../styleflow.js";
|
|
5
|
-
import {
|
|
6
|
-
blockHtmlAttributes,
|
|
7
|
-
preserveEmptyTextBlock,
|
|
8
|
-
preserveRichTextSpacing,
|
|
9
|
-
semanticProps,
|
|
10
|
-
textValue,
|
|
11
|
-
unwrapCoreHtml
|
|
12
|
-
} from "./helpers.js";
|
|
13
|
-
|
|
14
|
-
interface Props {
|
|
15
|
-
block: FlowpressBlock;
|
|
16
|
-
contract?: StyleflowContract;
|
|
17
|
-
hasChildren?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const { block, contract, hasChildren = false } = Astro.props;
|
|
21
|
-
const name = block.name.replace(/^sf\//, "");
|
|
22
|
-
const attributes = block.attributes;
|
|
23
|
-
const heading = name === "heading" || name === "core/heading";
|
|
24
|
-
const level = Math.min(6, Math.max(1, Number(attributes.level ?? 2)));
|
|
25
|
-
const headingTag = `h${level}` as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
26
|
-
const defaults = heading
|
|
27
|
-
? {
|
|
28
|
-
ty: "heading",
|
|
29
|
-
v: String(attributes.v ?? attributes.variant ?? level),
|
|
30
|
-
w: String(attributes.w ?? attributes.weight ?? "strong"),
|
|
31
|
-
foreground: "primary"
|
|
32
|
-
}
|
|
33
|
-
: {
|
|
34
|
-
ty: "body",
|
|
35
|
-
v: String(attributes.v ?? (name.includes("quote") ? "lg" : "md")),
|
|
36
|
-
w: String(attributes.w ?? "default"),
|
|
37
|
-
foreground: "primary"
|
|
38
|
-
};
|
|
39
|
-
const semantic = semanticProps(attributes, contract, defaults);
|
|
40
|
-
const htmlAttributes = blockHtmlAttributes(attributes);
|
|
41
|
-
const coreHtml = String(
|
|
42
|
-
attributes.content
|
|
43
|
-
?? attributes.value
|
|
44
|
-
?? block.innerHtml
|
|
45
|
-
?? ""
|
|
46
|
-
);
|
|
47
|
-
const normalizedHtml = name === "heading"
|
|
48
|
-
? textValue(block)
|
|
49
|
-
: name === "rich-text"
|
|
50
|
-
? preserveRichTextSpacing(String(attributes.content ?? ""))
|
|
51
|
-
: name === "quote"
|
|
52
|
-
? textValue(block, "quote")
|
|
53
|
-
: unwrapCoreHtml(preserveRichTextSpacing(coreHtml));
|
|
54
|
-
const html = name === "core/list"
|
|
55
|
-
? normalizedHtml
|
|
56
|
-
: preserveEmptyTextBlock(normalizedHtml);
|
|
57
|
-
const listTag = Boolean(attributes.ordered) ? "ol" : "ul";
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
{heading ? (
|
|
61
|
-
<S as={headingTag} {...semantic} {...htmlAttributes} set:html={html} />
|
|
62
|
-
) : name === "core/list" ? (
|
|
63
|
-
<S as={listTag} {...semantic} {...htmlAttributes}>
|
|
64
|
-
{hasChildren ? <slot /> : <Fragment set:html={html} />}
|
|
65
|
-
</S>
|
|
66
|
-
) : name === "core/list-item" ? (
|
|
67
|
-
<S as="li" {...semantic} {...htmlAttributes}>
|
|
68
|
-
<span set:html={html}></span>
|
|
69
|
-
{hasChildren ? <slot /> : null}
|
|
70
|
-
</S>
|
|
71
|
-
) : name === "quote" || name === "core/quote" ? (
|
|
72
|
-
<S as="blockquote" {...semantic} {...htmlAttributes}>
|
|
73
|
-
{hasChildren ? <slot /> : <div set:html={html}></div>}
|
|
74
|
-
{attributes.citation ? <cite>{String(attributes.citation)}</cite> : null}
|
|
75
|
-
</S>
|
|
76
|
-
) : (
|
|
77
|
-
<S
|
|
78
|
-
as={name === "core/paragraph" ? "p" : "div"}
|
|
79
|
-
{...semantic}
|
|
80
|
-
{...htmlAttributes}
|
|
81
|
-
set:html={html}
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type StyleflowContract } from "../../styleflow.js";
|
|
2
|
-
import type { FlowpressBlock } from "../../types.js";
|
|
3
|
-
export declare const DEFAULT_SEMANTIC_PROPS: {
|
|
4
|
-
surface: string;
|
|
5
|
-
layoutRole: string;
|
|
6
|
-
density: string;
|
|
7
|
-
};
|
|
8
|
-
export declare function blockHtmlAttributes(attributes: Record<string, unknown>, baseClass?: string): {
|
|
9
|
-
id?: string;
|
|
10
|
-
class?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function semanticProps(attributes: Record<string, unknown>, contract?: StyleflowContract, defaults?: Record<string, unknown>): Record<string, unknown>;
|
|
13
|
-
export declare function objectValue(block: FlowpressBlock, key: string): Record<string, unknown>;
|
|
14
|
-
export declare function textValue(block: FlowpressBlock, key?: string): string;
|
|
15
|
-
/**
|
|
16
|
-
* Keep intentional blank lines visible across current and legacy RichText
|
|
17
|
-
* serializations. Gutenberg can represent them either as repeated `<br>` tags,
|
|
18
|
-
* empty paragraph elements, or literal newlines in an attribute value.
|
|
19
|
-
*/
|
|
20
|
-
export declare function preserveRichTextSpacing(html: string): string;
|
|
21
|
-
/** Keep an empty text element at its typographic line height without visible text. */
|
|
22
|
-
export declare function preserveEmptyTextBlock(html: string): string;
|
|
23
|
-
export declare function linkValue(block: FlowpressBlock, key?: string): string;
|
|
24
|
-
export declare function responsiveValues(attributes: Record<string, unknown>, prefix: "columns" | "span", fallback: number): Record<"base" | "sm" | "md" | "lg" | "xl" | "2xl", number>;
|
|
25
|
-
export declare function unwrapCoreHtml(html: string): string;
|
|
26
|
-
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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,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,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,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"}
|