Skip to content

Commit

Permalink
feat: add inline component implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Aug 12, 2024
1 parent 014a00a commit 1fb447e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export type Numberish = number | `${number}`;

export type AriaLabelProps = {
id: string;
for: string;
for?: string;
};

export type AriaDescriptionProps = {
Expand Down
39 changes: 36 additions & 3 deletions packages/core/src/useFormGroup/useFormGroup.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { computed, Ref, shallowRef } from 'vue';
import { computed, createBlock, defineComponent, Fragment, openBlock, Ref, shallowRef, toValue, VNode } from 'vue';
import { useLabel } from '../a11y/useLabel';
import { FieldTypePrefixes } from '../constants';
import { FormObject, Reactivify, TypedSchema } from '../types';
import { AriaLabelableProps, AriaLabelProps, FormObject, Reactivify, TypedSchema } from '../types';
import { normalizeProps, useUniqId, withRefCapture } from '../utils/common';

export interface FormGroupProps<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput> {
label?: string;
schema?: TypedSchema<TInput, TOutput>;
}

interface GroupProps extends AriaLabelableProps {
id: string;
role?: 'group';
}

export function useFormGroup<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput>(
_props: Reactivify<FormGroupProps<TInput, TOutput>>,
elementRef?: Ref<HTMLElement>,
Expand All @@ -23,7 +28,7 @@ export function useFormGroup<TInput extends FormObject = FormObject, TOutput ext
targetRef: groupRef,
});

const groupProps = computed(() => {
const groupProps = computed<GroupProps>(() => {
const isFieldSet = groupRef.value?.tagName === 'FIELDSET';

return withRefCapture(
Expand All @@ -37,9 +42,37 @@ export function useFormGroup<TInput extends FormObject = FormObject, TOutput ext
);
});

const FormGroup = createInlineFormGroupComponent({ groupProps, labelProps });

return {
groupRef,
labelProps,
groupProps,
FormGroup,
};
}

interface InlineComponentProps {
groupProps: GroupProps;
labelProps: AriaLabelProps;
}

function createInlineFormGroupComponent({ groupProps, labelProps }: Reactivify<InlineComponentProps>) {
const impl = defineComponent({
setup(_, { slots }) {
return () => (
openBlock(),
createBlock(Fragment),
slots.default?.({ groupProps: toValue(groupProps), labelProps: toValue(labelProps) })
);
},
});

return impl as typeof impl & {
new (): {
$slots: {
default: (arg: InlineComponentProps) => VNode[];
};
};
};
}
14 changes: 10 additions & 4 deletions packages/playground/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
<template>
<div class="flex flex-col">
<FormGroup label="Shipping Information">
<InputText label="deep" name="some.deep.path" />
<InputText label="arr" name="some.array.0.path" />
<FormGroup v-slot="{ groupProps, labelProps }">
<div v-bind="groupProps">
<div v-bind="labelProps">Shipping Address</div>

<InputText label="deep" name="some.deep.path" />
<InputText label="arr" name="some.array.0.path" />
</div>
</FormGroup>
</div>
</template>

<script lang="ts" setup>
import InputText from '@/components/InputText.vue';
import FormGroup from '@/components/FormGroup.vue';
// import FormGroup from '@/components/FormGroup.vue';
import { useForm, useFormGroup } from '@formwerk/core';
import { defineSchema } from '@formwerk/schema-zod';
import { z } from 'zod';
const { FormGroup } = useFormGroup({ label: 'Shipping Information' });
const form = useForm({
schema: defineSchema(
z.object({
Expand Down

0 comments on commit 1fb447e

Please sign in to comment.