Skip to content

Commit

Permalink
feat: add props for across/down clue labels
Browse files Browse the repository at this point in the history
fix #132
  • Loading branch information
JaredReisinger committed Feb 25, 2022
1 parent b7e0cf2 commit c41c64d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 48 deletions.
11 changes: 10 additions & 1 deletion .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"imageSize": 100,
"badgeTemplate": "[![contributors](https://img.shields.io/badge/contributors-<%= contributors.length %>-orange.svg)](#contributors-)",
"commit": true,
"commit": false,
"skipCi": true,
"commitConvention": "angular",
"contributorsPerLine": 7,
Expand Down Expand Up @@ -57,6 +57,15 @@
"contributions": [
"ideas"
]
},
{
"login": "lorddaedra",
"name": "lorddaedra",
"avatar_url": "https://avatars.githubusercontent.com/u/26400787?v=4",
"profile": "https://github.com/lorddaedra",
"contributions": [
"ideas"
]
}
]
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
![more badges](https://img.shields.io/badge/badges-%F0%9F%91%8D%20are%20fun-orange)
[![commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![contributors](https://img.shields.io/badge/contributors-5-orange.svg)](#contributors-)
[![contributors](https://img.shields.io/badge/contributors-6-orange.svg)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->

Expand Down Expand Up @@ -161,6 +161,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://github.com/embeddedt"><img src="https://avatars.githubusercontent.com/u/42941056?v=4?s=100" width="100px;" alt=""/><br /><sub><b>embeddedt</b></sub></a><br /><a href="https://github.com/JaredReisinger/react-crossword/commits?author=embeddedt" title="Code">💻</a></td>
<td align="center"><a href="https://www.soindaial.com.br/"><img src="https://avatars.githubusercontent.com/u/42916864?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Albranco</b></sub></a><br /><a href="#ideas-drero" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://www.robmccollough.dev/"><img src="https://avatars.githubusercontent.com/u/42196611?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rob McCollough</b></sub></a><br /><a href="#ideas-robmccollough" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/lorddaedra"><img src="https://avatars.githubusercontent.com/u/26400787?v=4?s=100" width="100px;" alt=""/><br /><sub><b>lorddaedra</b></sub></a><br /><a href="#ideas-lorddaedra" title="Ideas, Planning, & Feedback">🤔</a></td>
</tr>
</table>

Expand Down
31 changes: 31 additions & 0 deletions src/Crossword.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,37 @@ The following imperative methods can be called on a "ref" handle to the componen
| `isCrosswordCorrect()` | _(none)_ | Returns whether the crossword is entirely correct or not. |
| `setGuess(row, col, guess)` | `(row: number, col: number, guess: string)` | Sets the “guess” value for a specific grid position. |

### Clue direction labels

Providing the `acrossLabel` and/or `downLabel` properties will override the default "ACROSS" and "DOWN" used for the clues.

```jsx
import Crossword from '@jaredreisinger/react-crossword';

const data = {
across: {
1: {
clue: 'one plus one',
answer: 'TWO',
row: 0,
col: 0,
},
},
down: {
2: {
clue: 'three minus two',
answer: 'ONE',
row: 0,
col: 2,
},
},
};

<div style={{ width: '25em', display: 'flex' }}>
<Crossword data={data} acrossLabel="Lefty-righty" downLabel="Upsie-downsie" />
</div>;
```

### Another example

Purely to show the grid rendering...
Expand Down
34 changes: 27 additions & 7 deletions src/Crossword.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useImperativeHandle, useRef } from 'react';
// import PropTypes from 'prop-types';
import PropTypes from 'prop-types';

// import produce from 'immer';
import styled from 'styled-components';

import { EnhancedProps } from './types';

import CrosswordProvider, {
CrosswordProviderImperative,
CrosswordProviderProps,
Expand Down Expand Up @@ -58,12 +60,26 @@ const CluesWrapper = styled.div.attrs((/* props */) => ({
}
`;

const crosswordPropTypes = { ...crosswordProviderPropTypes };
const crosswordPropTypes = {
...crosswordProviderPropTypes,

/** the label for the "across" clues */
acrossLabel: PropTypes.string,

/** the label for the "down" clues */
downLabel: PropTypes.string,
};

// @ts-expect-error TS doesn't allow non-optional props to be deleted, but we're
// building this into a new type!
delete crosswordPropTypes.children;

export type CrosswordProps = Omit<CrosswordProviderProps, 'children'>;
// This somewhat non-obvious construction is to get the typings from
// CrosswordProvider where they are "better" than the default inferred types.
export type CrosswordProps = EnhancedProps<
typeof crosswordPropTypes,
Omit<CrosswordProviderProps, 'children'>
>;
export type CrosswordImperative = CrosswordProviderImperative;

/**
Expand All @@ -72,7 +88,7 @@ export type CrosswordImperative = CrosswordProviderImperative;
* functionality.
*/
const Crossword = React.forwardRef<CrosswordImperative, CrosswordProps>(
(props, ref) => {
({ acrossLabel, downLabel, ...props }, ref) => {
const providerRef = useRef<CrosswordProviderImperative>(null);

// expose some imperative methods
Expand Down Expand Up @@ -118,8 +134,8 @@ const Crossword = React.forwardRef<CrosswordImperative, CrosswordProps>(
<CrosswordProvider {...props} ref={providerRef}>
<CrosswordGrid />
<CluesWrapper>
<DirectionClues direction="across" />
<DirectionClues direction="down" />
<DirectionClues direction="across" label={acrossLabel} />
<DirectionClues direction="down" label={downLabel} />
</CluesWrapper>
</CrosswordProvider>
);
Expand All @@ -128,6 +144,10 @@ const Crossword = React.forwardRef<CrosswordImperative, CrosswordProps>(

Crossword.displayName = 'Crossword';
Crossword.propTypes = crosswordPropTypes;
Crossword.defaultProps = CrosswordProvider.defaultProps;
Crossword.defaultProps = {
...CrosswordProvider.defaultProps,
acrossLabel: undefined,
downLabel: undefined,
};

export default Crossword;
2 changes: 1 addition & 1 deletion src/CrosswordGrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ const data = {
<div style={{ width: '10em' }}>
<CrosswordGrid />
</div>
</CrosswordContext.Provider>;
</CrosswordProvider>;
```
38 changes: 35 additions & 3 deletions src/DirectionClues.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,43 @@ const data = {
col: 0,
},
},
down: {
},
down: {},
};

<CrosswordProvider data={data}>
<DirectionClues direction="across" />
</CrosswordContext.Provider>;
</CrosswordProvider>;
```

### Alternate label

If you don't want the default heading label (of either "ACROSS" or "DOWN"), you can provide your own:

```jsx
import {
CrosswordProvider,
DirectionClues,
} from '@jaredreisinger/react-crossword';

const data = {
across: {
1: {
clue: 'This is a clue.',
answer: 'ANSWER',
row: 0,
col: 0,
},
2: {
clue: 'This is another clue.',
answer: 'ANOTHER',
row: 1,
col: 0,
},
},
down: {},
};

<CrosswordProvider data={data}>
<DirectionClues direction="across" label="Lefty-righty" />
</CrosswordProvider>;
```
48 changes: 13 additions & 35 deletions src/DirectionClues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,26 @@ import Clue from './Clue';
const directionCluesPropTypes = {
/** direction of this list of clues ("across" or "down") */
direction: PropTypes.string.isRequired,
// /** clues for this List's direction */
// clues: PropTypes.arrayOf(
// PropTypes.shape({
// /** number of the clue (the label shown) */
// number: PropTypes.string.isRequired,
// /** clue text */
// clue: PropTypes.node.isRequired,
// /** whether the answer/guess is correct */
// correct: PropTypes.bool,
// })
// ).isRequired,

/** a label to use instead of the (English) default */
label: PropTypes.string,
};

export type DirectionCluesProps = EnhancedProps<
typeof directionCluesPropTypes,
{ direction: Direction }
>;

export default function DirectionClues({ direction }: DirectionCluesProps) {
const {
clues,
// selectedPosition: { row: focusedRow, col: focusedCol },
// selectedDirection: currentDirection,
// selectedNumber: currentNumber,
} = useContext(CrosswordContext);
export default function DirectionClues({
direction,
label,
}: DirectionCluesProps) {
const { clues } = useContext(CrosswordContext);

return (
<div className="direction">
{/* use something other than h3? */}
<h3 className="header">{direction.toUpperCase()}</h3>
<h3 className="header">{label || direction.toUpperCase()}</h3>
{clues?.[direction].map(({ number, clue, correct }) => (
<Clue
key={number}
Expand All @@ -60,20 +50,8 @@ export default function DirectionClues({ direction }: DirectionCluesProps) {
);
}

DirectionClues.propTypes = {
/** direction of this list of clues ("across" or "down") */
direction: PropTypes.string.isRequired,
// /** clues for this List's direction */
// clues: PropTypes.arrayOf(
// PropTypes.shape({
// /** number of the clue (the label shown) */
// number: PropTypes.string.isRequired,
// /** clue text */
// clue: PropTypes.node.isRequired,
// /** whether the answer/guess is correct */
// correct: PropTypes.bool,
// })
// ).isRequired,
};
DirectionClues.propTypes = directionCluesPropTypes;

DirectionClues.defaultProps = {};
DirectionClues.defaultProps = {
label: undefined,
};

0 comments on commit c41c64d

Please sign in to comment.