Skip to content

Commit

Permalink
feat: add data type to TextInputPropController
Browse files Browse the repository at this point in the history
  • Loading branch information
fikrikarim committed May 8, 2024
1 parent a0ba13c commit 3b5e36e
Show file tree
Hide file tree
Showing 22 changed files with 376 additions and 52 deletions.
6 changes: 6 additions & 0 deletions .changeset/fair-phones-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@makeswift/prop-controllers': minor
'@makeswift/runtime': minor
---

Add data type to legacy `TextInput` prop controller and move it to `@makeswift/prop-controllers`.
12 changes: 12 additions & 0 deletions packages/prop-controllers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,18 @@ export type {
TextAreaPropControllerData,
ResolveTextAreaPropControllerValue,
} from './text-area'
export {
TextInput,
textInputPropControllerDataSchema,
getTextInputPropControllerDataString,
createTextInputPropControllerDataFromString,
} from './text-input'
export type {
TextInputDescriptor,
TextInputOptions,
TextInputPropControllerData,
ResolveTextInputPropControllerValue,
} from './text-input'
export {
TextStyle,
textStylePropControllerDataSchema,
Expand Down
1 change: 1 addition & 0 deletions packages/prop-controllers/src/prop-controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const Types = {
ResponsiveLength: 'ResponsiveLength',
SocialLinks: 'SocialLinks',
TextArea: 'TextArea',
TextInput: 'TextInput',
Table: 'Table',
TableFormFields: 'TableFormFields',
TextStyle: 'TextStyle',
Expand Down
1 change: 1 addition & 0 deletions packages/prop-controllers/src/text-input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './text-input'
80 changes: 80 additions & 0 deletions packages/prop-controllers/src/text-input/text-input.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ControlDataTypeKey, Types } from '../prop-controllers'
import {
TextInputDescriptor,
TextInputPropControllerDataV1,
TextInputPropControllerDataV1Type,
createTextInputPropControllerDataFromString,
getTextInputPropControllerDataString,
} from './text-input'

describe('TextInputPropController', () => {
describe('getTextInputPropControllerDataString', () => {
test('returns value for TextInputPropControllerDataV1Type', () => {
// Arrange
const text = 'test text'
const data: TextInputPropControllerDataV1 = {
[ControlDataTypeKey]: TextInputPropControllerDataV1Type,
value: text,
}

// Act
const result = getTextInputPropControllerDataString(data)

// Assert
expect(result).toBe(text)
})

test('returns value for TextInputPropControllerDataV0 data', () => {
// Arrange
const text = 'test text'

// Act
const result = getTextInputPropControllerDataString(text)

// Assert
expect(result).toBe(text)
})
})

describe('createTextInputPropControllerDataFromString', () => {
test('returns TextInputPropControllerDataV1 when definition version is 1', () => {
// Arrange
const text = 'test text'
const definition: TextInputDescriptor = {
type: Types.TextInput,
version: 1,
options: {},
}

// Act
const result = createTextInputPropControllerDataFromString(
text,
definition,
)

// Assert
expect(result).toEqual({
[ControlDataTypeKey]: TextInputPropControllerDataV1Type,
value: text,
})
})

test('returns string value when definition version is not 1', () => {
// Arrange
const text = 'test text'
const definition: TextInputDescriptor = {
type: Types.TextInput,
options: {},
}

// Act
const result = createTextInputPropControllerDataFromString(
text,
definition,
)

// Assert
expect(result).toBe(text)
})
})
})
94 changes: 94 additions & 0 deletions packages/prop-controllers/src/text-input/text-input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { z } from 'zod'
import { ControlDataTypeKey, Options, Types } from '../prop-controllers'
import { match } from 'ts-pattern'

const textInputPropControllerDataV0Schema = z.string()

export type TextInputPropControllerDataV0 = z.infer<
typeof textInputPropControllerDataV0Schema
>

export const TextInputPropControllerDataV1Type =
'prop-controllers::text-input::v1'

const textInputPropControllerDataV1Schema = z.object({
[ControlDataTypeKey]: z.literal(TextInputPropControllerDataV1Type),
value: z.string(),
})

export type TextInputPropControllerDataV1 = z.infer<
typeof textInputPropControllerDataV1Schema
>

export const textInputPropControllerDataSchema = z.union([
textInputPropControllerDataV0Schema,
textInputPropControllerDataV1Schema,
])

export type TextInputPropControllerData = z.infer<
typeof textInputPropControllerDataSchema
>

export type TextInputOptions = Options<{
label?: string
placeholder?: string
hidden?: boolean
}>

type TextInputDescriptorV0<_T = TextInputPropControllerDataV0> = {
type: typeof Types.TextInput
options: TextInputOptions
}

type TextInputDescriptorV1<
_T = TextInputPropControllerData,
U extends TextInputOptions = TextInputOptions,
> = {
type: typeof Types.TextInput
version: 1
options: U
}

export type TextInputDescriptor<_T = TextInputPropControllerData> =
| TextInputDescriptorV0
| TextInputDescriptorV1

export type ResolveTextInputPropControllerValue<T extends TextInputDescriptor> =
T extends TextInputDescriptor ? string | undefined : never

/**
* @deprecated Imports from @makeswift/prop-controllers are deprecated. Use
* @makeswift/runtime/controls instead.
*/
export function TextInput(
options: TextInputOptions = {},
): TextInputDescriptorV1 {
return { type: Types.TextInput, version: 1, options }
}

export function getTextInputPropControllerDataString(
data: TextInputPropControllerData | undefined,
): string | undefined {
return match(data)
.with(
{ [ControlDataTypeKey]: TextInputPropControllerDataV1Type },
(v1) => v1.value,
)
.otherwise((v0) => v0)
}

export function createTextInputPropControllerDataFromString(
value: string,
definition: TextInputDescriptor,
): TextInputPropControllerData {
return match(definition)
.with(
{ version: 1 },
() =>
({
[ControlDataTypeKey]: TextInputPropControllerDataV1Type,
value,
} as const),
)
.otherwise(() => value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ import {
ResponsiveIconRadioGroupValue as ResponsiveIconRadioGroupControlValue,
ResponsiveSelectDescriptor as ResponsiveSelectControl,
ResponsiveSelectValue as ResponsiveSelectControlValue,
TextInputDescriptor as TextInputControl,
TextInputValue as TextInputControlValue,
PanelDescriptor as PanelControl,
PanelDescriptorType as PanelControlType,
PanelDescriptorValueType as PanelControlValueType,
Expand Down Expand Up @@ -92,6 +90,7 @@ import {
CheckboxDescriptor as CheckboxControl,
TextStyleDescriptor as TextStyleControl,
TextStylePropControllerData,
TextInputDescriptor as TextInputControl,
} from '@makeswift/prop-controllers'

type SerializedShapeControlConfig<T extends Record<string, SerializedPanelControl>> = {
Expand Down Expand Up @@ -645,8 +644,10 @@ function deserializeLinkControl(serializedControl: SerializedLinkControl): Deser

type TextInputControlConfig = { label?: string; placeholder?: string; hidden?: boolean }

type TextInputControlValue = string

type SerializedTextInputControl<_T = TextInputControlValue> = {
type: typeof Controls.Types.TextInput
type: typeof PropControllerTypes.TextInput
options: SerializedConfig<TextInputControlConfig>
}

Expand All @@ -663,7 +664,7 @@ function serializeTextInputControl(
}

type DeserializedTextInputControl<_T = TextInputControlValue> = {
type: typeof Controls.Types.TextInput
type: typeof PropControllerTypes.TextInput
options: DeserializedConfig<TextInputControlConfig>
}

Expand Down Expand Up @@ -1037,7 +1038,7 @@ export function serializeControl<T extends Data>(
case PropControllerTypes.Link:
return serializeLinkControl(control)

case Controls.Types.TextInput:
case PropControllerTypes.TextInput:
return serializeTextInputControl(control)

case PropControllerTypes.TextStyle:
Expand Down Expand Up @@ -1115,7 +1116,7 @@ export function deserializeControl<T extends Data>(
case PropControllerTypes.Link:
return deserializeLinkControl(serializedControl)

case Controls.Types.TextInput:
case PropControllerTypes.TextInput:
return deserializeTextInputControl(serializedControl)

case PropControllerTypes.TextStyle:
Expand Down
3 changes: 2 additions & 1 deletion packages/runtime/src/components/builtin/Button/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Link,
Margin,
ResponsiveColor,
TextInput,
TextStyle,
Width,
} from '@makeswift/prop-controllers'
Expand All @@ -21,7 +22,7 @@ export function registerComponent(runtime: ReactRuntime) {
label: 'Button',
props: {
id: ElementID(),
children: Props.TextInput({ placeholder: 'Button text' }),
children: TextInput({ placeholder: 'Button text' }),
link: Link({
defaultValue: {
type: 'OPEN_PAGE',
Expand Down
13 changes: 5 additions & 8 deletions packages/runtime/src/components/builtin/Countdown/Countdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import { cx } from '@emotion/css'
import { ComponentPropsWithoutRef, ForwardedRef, forwardRef, Ref, useEffect, useState } from 'react'
import {
ResponsiveIconRadioGroupValue,
TextInputValue,
} from '../../../prop-controllers/descriptors'
import { ResponsiveIconRadioGroupValue } from '../../../prop-controllers/descriptors'
import { ResponsiveColor } from '../../../runtimes/react/controls'
import { useStyle } from '../../../runtimes/react/use-style'
import { colorToString } from '../../utils/colorToString'
Expand All @@ -29,10 +26,10 @@ type Props = {
labelColor?: ResponsiveColor | null
width?: string
margin?: string
daysLabel?: TextInputValue
hoursLabel?: TextInputValue
minutesLabel?: TextInputValue
secondsLabel?: TextInputValue
daysLabel?: string
hoursLabel?: string
minutesLabel?: string
secondsLabel?: string
}

const BLOCK_CLASS_NAME = 'block'
Expand Down
9 changes: 5 additions & 4 deletions packages/runtime/src/components/builtin/Countdown/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
GapX,
Margin,
ResponsiveColor,
TextInput,
Width,
} from '@makeswift/prop-controllers'

Expand Down Expand Up @@ -95,13 +96,13 @@ export function registerComponent(runtime: ReactRuntime) {
defaultValue: { value: 560, unit: 'px' },
}),
margin: Margin({ format: Margin.Format.ClassName }),
daysLabel: Props.TextInput({ label: 'Days label', placeholder: 'Days' }),
hoursLabel: Props.TextInput({ label: 'Hours label', placeholder: 'Hours' }),
minutesLabel: Props.TextInput({
daysLabel: TextInput({ label: 'Days label', placeholder: 'Days' }),
hoursLabel: TextInput({ label: 'Hours label', placeholder: 'Hours' }),
minutesLabel: TextInput({
label: 'Minutes label',
placeholder: 'Minutes',
}),
secondsLabel: Props.TextInput({
secondsLabel: TextInput({
label: 'Seconds label',
placeholder: 'Seconds',
}),
Expand Down
3 changes: 1 addition & 2 deletions packages/runtime/src/components/builtin/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import type { TableColumn } from './types'
import {
ResponsiveIconRadioGroupValue,
ResponsiveSelectValue,
TextInputValue,
} from '../../../prop-controllers/descriptors'
import { Link } from '../../shared/Link'
import { BoxModelHandle, getBox } from '../../../box-model'
Expand Down Expand Up @@ -89,7 +88,7 @@ type Props = {
submitTextStyle?: ResponsiveTextStyleData
brandColor?: ResponsiveColor | null
submitTextColor?: ResponsiveColor | null
submitLabel?: TextInputValue
submitLabel?: string
submitVariant?: ResponsiveSelectValue<
'flat' | 'outline' | 'shadow' | 'clear' | 'blocky' | 'bubbly' | 'skewed'
>
Expand Down
3 changes: 2 additions & 1 deletion packages/runtime/src/components/builtin/Form/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ResponsiveLength,
Table,
TableFormFields,
TextInput,
TextStyle,
Width,
} from '@makeswift/prop-controllers'
Expand Down Expand Up @@ -107,7 +108,7 @@ export function registerComponent(runtime: ReactRuntime) {
placeholder: 'white',
hidden: props.tableId == null,
})),
submitLabel: Props.TextInput(props => ({
submitLabel: TextInput(props => ({
label: 'Button label',
placeholder: 'Submit',
hidden: props.tableId == null,
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/src/components/builtin/Image/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState, useEffect, Ref, forwardRef } from 'react'
import NextImage from 'next/image'
import type NextLegacyImageType from 'next/legacy/image'

import { ResponsiveOpacityValue, TextInputValue } from '../../../prop-controllers/descriptors'
import { ResponsiveOpacityValue } from '../../../prop-controllers/descriptors'
import { LinkData, ResponsiveLengthData, ImageData } from '@makeswift/prop-controllers'
import { Breakpoints, findBreakpointOverride } from '../../../state/modules/breakpoints'
import { placeholders } from '../../utils/placeholders'
Expand All @@ -22,7 +22,7 @@ const NextLegacyImage = NextImage as typeof NextLegacyImageType
type Props = {
id?: string
file?: ImageData
altText?: TextInputValue
altText?: string
link?: LinkData
width?: ResponsiveLengthData
margin?: string
Expand Down

0 comments on commit 3b5e36e

Please sign in to comment.