feat: useLayoutWrapper
This commit is contained in:
@@ -96,7 +96,11 @@
|
||||
"min": "",
|
||||
"max": "",
|
||||
"acfe_flexible_modal_edit_size": "",
|
||||
"acfe_flexible_settings": ["group_layout_contained"],
|
||||
"acfe_flexible_settings": [
|
||||
"group_layout_colored",
|
||||
"group_layout_contained",
|
||||
"group_layout_padded"
|
||||
],
|
||||
"acfe_flexible_settings_size": "large",
|
||||
"acfe_flexible_render_template": false,
|
||||
"acfe_flexible_render_style": false,
|
||||
@@ -190,7 +194,7 @@
|
||||
"min": "",
|
||||
"max": "",
|
||||
"acfe_flexible_modal_edit_size": "",
|
||||
"acfe_flexible_settings": "",
|
||||
"acfe_flexible_settings": ["group_layout_colored", "group_layout_padded"],
|
||||
"acfe_flexible_settings_size": "large",
|
||||
"acfe_flexible_render_template": false,
|
||||
"acfe_flexible_render_style": false,
|
||||
@@ -236,5 +240,5 @@
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1769779666
|
||||
"modified": 1770740697
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"key": "group_layout_colored",
|
||||
"title": "Layout - Colored",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_693c8c945ce51",
|
||||
"label": "Variante de couleur",
|
||||
"name": "color",
|
||||
"aria-label": "",
|
||||
"type": "button_group",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"default": "Par défaut",
|
||||
"muted": "Atténué",
|
||||
"elevated": "Surélevé",
|
||||
"accented": "Accentué",
|
||||
"inverted": "Inversé",
|
||||
"primary": "Couleur principale"
|
||||
},
|
||||
"default_value": "default",
|
||||
"return_format": "value",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"layout": "horizontal",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "color",
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupLayoutColored",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1770132035
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_68dc29d78941c",
|
||||
"label": "Conteneur",
|
||||
"label": "Largeur du contenu",
|
||||
"name": "container",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"type": "button_group",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
@@ -21,101 +21,17 @@
|
||||
"xl": "1280px",
|
||||
"lg": "1024px",
|
||||
"fluid": "Largeur fluide",
|
||||
"none": "Pleine largeur"
|
||||
"fullbleed": "Pleine largeur"
|
||||
},
|
||||
"default_value": "default",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"max": "",
|
||||
"prepend": "",
|
||||
"append": "",
|
||||
"required_message": "",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"layout": "horizontal",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "container",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": "",
|
||||
"min": ""
|
||||
},
|
||||
{
|
||||
"key": "field_693c8c3b5ce50",
|
||||
"label": "Espacement vertical",
|
||||
"name": "vertical_padding",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"sm": "Petit (12px)",
|
||||
"md": "Medium (24px)",
|
||||
"lg": "Grand (48px)"
|
||||
},
|
||||
"default_value": "md",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "verticalPadding",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": ""
|
||||
},
|
||||
{
|
||||
"key": "field_693c8c945ce51",
|
||||
"label": "Couleur d'arrière-plan",
|
||||
"name": "bg_color",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"default": "Par défaut",
|
||||
"muted": "Atténué",
|
||||
"inverted": "Inversé"
|
||||
},
|
||||
"default_value": "default",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "bgColor",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": ""
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
@@ -143,5 +59,5 @@
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1768358794
|
||||
"modified": 1770740626
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"key": "group_layout_padded",
|
||||
"title": "Layout - Padded",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_693c8c3b5ce50",
|
||||
"label": "Espacement intérieur vertical",
|
||||
"name": "vertical_padding",
|
||||
"aria-label": "",
|
||||
"type": "button_group",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"none": "Aucun",
|
||||
"sm": "Petit (12px)",
|
||||
"md": "Medium (24px)",
|
||||
"lg": "Grand (48px)"
|
||||
},
|
||||
"default_value": "md",
|
||||
"return_format": "value",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"layout": "horizontal",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "verticalPadding",
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "default",
|
||||
"label_placement": "left",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupLayoutPadded",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1770740636
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fragment LayoutColored on GroupLayoutColored_Fields {
|
||||
color
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
fragment LayoutContained on GroupLayoutContained_Fields {
|
||||
container
|
||||
verticalPadding
|
||||
bgColor
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import type { LayoutContainedFragment } from "#graphql/operations";
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
|
||||
const props = defineProps<LayoutContainedFragment>();
|
||||
|
||||
const layoutWrapperVariants = tv({
|
||||
slots: {
|
||||
base: "",
|
||||
inner: "",
|
||||
},
|
||||
variants: {
|
||||
container: {
|
||||
default: { inner: "container" },
|
||||
lg: { inner: "container-lg" },
|
||||
xl: { inner: "container-xl" },
|
||||
fluid: { inner: "container-fluid" },
|
||||
none: { inner: "container-none" },
|
||||
},
|
||||
verticalPadding: {
|
||||
sm: { base: "py-3" },
|
||||
md: { base: "py-6" },
|
||||
lg: { base: "py-12" },
|
||||
},
|
||||
bgColor: {
|
||||
default: { base: "bg-default" },
|
||||
muted: { base: "bg-muted" },
|
||||
inverted: { base: "bg-inverted text-inverted" },
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
container: "default",
|
||||
verticalPadding: "md",
|
||||
bgColor: "default",
|
||||
},
|
||||
});
|
||||
const { base, inner } = layoutWrapperVariants({
|
||||
container: props.container[0],
|
||||
verticalPadding: props.verticalPadding[0],
|
||||
bgColor: props.bgColor[0],
|
||||
} as VariantProps<typeof layoutWrapperVariants>);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section :class="base()">
|
||||
<div :class="inner()">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,3 @@
|
||||
fragment LayoutPadded on GroupLayoutPadded_Fields {
|
||||
verticalPadding
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ layoutSettings?: LayoutSettings }>();
|
||||
const { base, inner } = useLayoutWrapper(props.layoutSettings);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section :class="base()">
|
||||
<div :class="inner()">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -6,9 +6,7 @@ defineProps<NodePageFragment>();
|
||||
|
||||
<template>
|
||||
<div id="node-page">
|
||||
<h1 v-if="!isFrontPage" class="text-4xl font-bold">
|
||||
{{ title }}
|
||||
</h1>
|
||||
<PageHeader v-if="!isFrontPage" :title="title"></PageHeader>
|
||||
<BuilderSections :sections="groupPostPage?.sections || []" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
title?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header v-if="title" class="bg-accented py-6">
|
||||
<div class="container">
|
||||
<h1 class="heading-1">
|
||||
{{ title }}
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
@@ -1,18 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
const { isLoggedIn } = useAuth();
|
||||
const { isRedirecting } = useAuthConnexion();
|
||||
const layoutSettings: LayoutWrapperProps = {
|
||||
container: "lg",
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section data-section-name="auth-connexion" class="py-12">
|
||||
<div class="container-sm">
|
||||
<AuthState>
|
||||
<AuthRedirecting v-if="isRedirecting" />
|
||||
<template v-else>
|
||||
<AuthLogoutForm v-if="isLoggedIn" />
|
||||
<AuthLoginForm v-else />
|
||||
</template>
|
||||
</AuthState>
|
||||
</div>
|
||||
</section>
|
||||
<LayoutWrapper data-section-name="auth-connexion" :layout-settings="layoutSettings">
|
||||
<AuthState>
|
||||
<AuthRedirecting v-if="isRedirecting" />
|
||||
<template v-else>
|
||||
<AuthLogoutForm v-if="isLoggedIn" />
|
||||
<AuthLoginForm v-else />
|
||||
</template>
|
||||
</AuthState>
|
||||
</LayoutWrapper>
|
||||
</template>
|
||||
|
||||
@@ -2,4 +2,8 @@ fragment SectionHeroSplit on GroupAbstractBuilderSectionsHeroSplitLayout {
|
||||
content
|
||||
reverse
|
||||
...AcfMedia
|
||||
layoutSettings {
|
||||
...LayoutColored
|
||||
...LayoutPadded
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import { tv, type VariantProps } from "tailwind-variants";
|
||||
import type { SectionHeroSplitFragment } from "#graphql/operations";
|
||||
|
||||
const tvSectionHeroSplit = tv({
|
||||
extend: tvLayoutWrapper,
|
||||
slots: {
|
||||
base: "py-6",
|
||||
container: "container flex flex-col items-center gap-6",
|
||||
content: "flex-1",
|
||||
media: "w-full basis-1/2",
|
||||
@@ -27,6 +27,7 @@ const tvSectionHeroSplit = tv({
|
||||
const props = defineProps<SectionHeroSplitFragment>();
|
||||
const classes = tvSectionHeroSplit({
|
||||
reverse: props.reverse,
|
||||
...props.layoutSettings,
|
||||
} as VariantProps<typeof tvSectionHeroSplit>);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
fragment SectionTextBlock on GroupAbstractBuilderSectionsTextBlockLayout {
|
||||
content
|
||||
layoutSettings {
|
||||
...LayoutColored
|
||||
...LayoutContained
|
||||
...LayoutPadded
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ defineProps<SectionTextBlockFragment>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LayoutContained data-section-type="text-block" v-bind="layoutSettings!">
|
||||
<LayoutWrapper data-section-type="text-block" :layout-settings="layoutSettings">
|
||||
<UiProse :content="content" />
|
||||
</LayoutContained>
|
||||
</LayoutWrapper>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
import * as z from "zod";
|
||||
|
||||
// Tailwind Variants for LayoutWrapper
|
||||
export const tvLayoutWrapper = tv({
|
||||
slots: {
|
||||
base: "",
|
||||
inner: "",
|
||||
},
|
||||
variants: {
|
||||
// LayoutColored
|
||||
color: {
|
||||
default: { base: "bg-default" },
|
||||
muted: { base: "bg-muted" },
|
||||
elevated: { base: "bg-elevated" },
|
||||
accented: { base: "bg-accented" },
|
||||
inverted: { base: "bg-inverted text-inverted" },
|
||||
primary: { base: "bg-primary text-inverted" },
|
||||
},
|
||||
// LayoutContained
|
||||
container: {
|
||||
default: { inner: "container" },
|
||||
xl: { inner: "container-xl" },
|
||||
lg: { inner: "container-lg" },
|
||||
fluid: { inner: "container-fluid" },
|
||||
fullbleed: { inner: "container-fullbleed" },
|
||||
},
|
||||
// LayoutPadded
|
||||
verticalPadding: {
|
||||
sm: { base: "py-3" },
|
||||
md: { base: "py-6" },
|
||||
lg: { base: "py-12" },
|
||||
none: {},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
color: "default",
|
||||
container: "default",
|
||||
verticalPadding: "md",
|
||||
},
|
||||
});
|
||||
|
||||
export type LayoutWrapperProps = VariantProps<typeof tvLayoutWrapper>;
|
||||
|
||||
// Zod schemas for validating layout settings
|
||||
const colorEnum = z.enum(["default", "muted", "elevated", "accented", "inverted", "primary"]);
|
||||
const containerEnum = z.enum(["default", "xl", "lg", "fluid", "fullbleed"]);
|
||||
const verticalPaddingEnum = z.enum(["sm", "md", "lg", "none"]);
|
||||
|
||||
const layoutSettingsSchema = z.object({
|
||||
color: z.string().pipe(colorEnum).optional(),
|
||||
container: z.string().pipe(containerEnum).optional(),
|
||||
verticalPadding: z.string().pipe(verticalPaddingEnum).optional(),
|
||||
});
|
||||
|
||||
export type LayoutSettings = z.input<typeof layoutSettingsSchema>;
|
||||
|
||||
export function useLayoutWrapper(input?: LayoutSettings) {
|
||||
try {
|
||||
return tvLayoutWrapper(layoutSettingsSchema.parse(input));
|
||||
} catch {
|
||||
return tvLayoutWrapper();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user