Skip to content

Commit

Permalink
Fixes input, adds byond global (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
jlsnow301 authored Nov 22, 2024
1 parent 796ae40 commit 160dcb6
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 25 deletions.
1 change: 1 addition & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const config: StorybookConfig = {
'@storybook/addon-essentials',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
'@storybook/addon-console',
{
name: 'storybook-addon-sass-postcss',
options: {
Expand Down
3 changes: 3 additions & 0 deletions .storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script type="text/javascript">
var Byond = (window.Byond = {});
</script>
58 changes: 34 additions & 24 deletions lib/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,24 @@ type OptionalProps = Partial<{
/** Fires when user is 'done typing': Clicked out, blur, enter key */
onChange: (event: SyntheticEvent<HTMLInputElement>, value: string) => void;
/** Fires once the enter key is pressed */
onEnter?: (event: SyntheticEvent<HTMLInputElement>, value: string) => void;
onEnter: (event: SyntheticEvent<HTMLInputElement>, value: string) => void;
/** Fires once the escape key is pressed */
onEscape: (event: SyntheticEvent<HTMLInputElement>) => void;
/** The placeholder text when everything is cleared */
placeholder: string;
/** Clears the input value on enter */
selfClear: boolean;
/** Auto-updates the input value on props change, ie, data from Byond */
updateOnPropsChange: boolean;
/** The state variable of the input. */
value: string | number;
}>;

type Props = OptionalProps & ConditionalProps & BoxProps;
type Props = OptionalProps & ConditionalProps & Omit<BoxProps, 'children'>;

export function toInputValue(value: string | number | undefined): string {
type InputValue = string | number | undefined;

export function toInputValue(value: InputValue): string {
return typeof value !== 'number' && typeof value !== 'string'
? ''
: String(value);
Expand Down Expand Up @@ -93,11 +97,11 @@ export function Input(props: Props) {
onInput,
placeholder,
selfClear,
updateOnPropsChange,
value,
...rest
} = props;

// The ref to the input field
const inputRef = useRef<HTMLInputElement>(null);

function handleInput(event: SyntheticEvent<HTMLInputElement>) {
Expand Down Expand Up @@ -133,38 +137,44 @@ export function Input(props: Props) {
}
}

/** Focuses the input on mount */
useEffect(() => {
function setValue(newValue: InputValue) {
const input = inputRef.current;
if (!input) return;

const newValue = toInputValue(value);
const changed = toInputValue(newValue);
if (input.value === changed) return;

input.value = changed;
}

/** Focuses the input on mount */
useEffect(() => {
const input = inputRef.current;

if (input.value !== newValue) input.value = newValue;
if (input) {
setValue(value);

if (!autoFocus && !autoSelect) return;
const hasFocusOrSelect = autoFocus || autoSelect;
const isActive = document.activeElement === input;

setTimeout(() => {
input.focus();
if (hasFocusOrSelect && !isActive) {
setTimeout(() => {
input.focus();

if (autoSelect) {
input.select();
if (autoSelect) {
input.select();
}
}, 1);
}
}, 1);
}
}, []);

/** Updates the initial value on props change */
useEffect(() => {
const input = inputRef.current;
if (!input) return;

if (document.activeElement === input) {
return;
if (updateOnPropsChange) {
setValue(value);
}

const newValue = toInputValue(value);

if (input.value !== newValue) input.value = newValue;
});
}, [value]);

return (
<Box
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@biomejs/biome": "1.9.4",
"@chromatic-com/storybook": "3.2.2",
"@popperjs/core": "^2.11.8",
"@storybook/addon-console": "^3.0.0",
"@storybook/addon-essentials": "8.4.4",
"@storybook/addon-interactions": "8.4.4",
"@storybook/addon-onboarding": "8.4.4",
Expand Down
15 changes: 15 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 47 additions & 1 deletion stories/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { withConsole } from '@storybook/addon-console';
import type { Meta, StoryObj } from '@storybook/react';
import type { ComponentProps } from 'react';
import { Input } from '../lib/components/Input';
Expand All @@ -7,12 +8,57 @@ type StoryProps = ComponentProps<typeof Input>;
export default {
component: Input,
title: 'Components/Input',
decorators: [(storyFn, context) => withConsole()(storyFn)(context)],
} satisfies Meta<StoryProps>;

type Story = StoryObj<StoryProps>;

export const Default: Story = {
args: {
children: 'Input',
autoFocus: true,
autoSelect: false,
disabled: false,
fluid: false,
maxLength: 100,
placeholder: 'Type something here...',
value: 'Hello, world!',
},
};

export const AutoSelect: Story = {
args: {
...Default.args,
autoSelect: true,
},
};

export const Disabled: Story = {
args: {
...Default.args,
disabled: true,
},
};

export const Expensive: Story = {
args: {
...Default.args,
expensive: true,
onInput: (_e, v) => console.log('New value: ', v),
value: "I'm debounced!",
},
};

export const Fluid: Story = {
args: {
...Default.args,
fluid: true,
},
};

export const UpdateOnExternalChange: Story = {
args: {
...Default.args,
updateOnPropsChange: true,
value: 'Change my value',
},
};

0 comments on commit 160dcb6

Please sign in to comment.