@rpg-engine/long-bow 0.7.91 → 0.7.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/components/CraftBook/CraftingTooltip.d.ts +13 -0
  2. package/dist/components/CraftBook/components/CraftBookHeader.d.ts +9 -0
  3. package/dist/components/CraftBook/components/CraftBookPagination.d.ts +0 -0
  4. package/dist/components/CraftBook/components/CraftBookSearch.d.ts +0 -0
  5. package/dist/components/CraftBook/hooks/useCraftBookFilters.d.ts +9 -0
  6. package/dist/components/CraftBook/hooks/useFilteredItems.d.ts +9 -0
  7. package/dist/components/CraftBook/hooks/usePagination.d.ts +13 -0
  8. package/dist/components/CraftBook/hooks/useResponsiveSize.d.ts +6 -0
  9. package/dist/components/CraftBook/utils/modifyString.d.ts +1 -0
  10. package/dist/components/shared/Pagination/Pagination.d.ts +9 -0
  11. package/dist/components/shared/SearchBar/SearchBar.d.ts +10 -0
  12. package/dist/hooks/useLocalStorage.d.ts +1 -0
  13. package/dist/long-bow.cjs.development.js +448 -293
  14. package/dist/long-bow.cjs.development.js.map +1 -1
  15. package/dist/long-bow.cjs.production.min.js +1 -1
  16. package/dist/long-bow.cjs.production.min.js.map +1 -1
  17. package/dist/long-bow.esm.js +448 -294
  18. package/dist/long-bow.esm.js.map +1 -1
  19. package/dist/stories/Features/craftbook/CraftBook.stories.d.ts +2 -0
  20. package/package.json +1 -1
  21. package/src/components/CraftBook/CraftBook.tsx +281 -138
  22. package/src/components/CraftBook/CraftingRecipe.tsx +97 -97
  23. package/src/components/CraftBook/CraftingTooltip.tsx +137 -0
  24. package/src/components/CraftBook/components/CraftBookHeader.tsx +81 -0
  25. package/src/components/CraftBook/components/CraftBookPagination.tsx +1 -0
  26. package/src/components/CraftBook/components/CraftBookSearch.tsx +1 -0
  27. package/src/components/CraftBook/hooks/useCraftBookFilters.ts +39 -0
  28. package/src/components/CraftBook/hooks/useFilteredItems.ts +39 -0
  29. package/src/components/CraftBook/hooks/usePagination.ts +39 -0
  30. package/src/components/CraftBook/hooks/useResponsiveSize.ts +50 -0
  31. package/src/components/CraftBook/utils/modifyString.ts +11 -0
  32. package/src/components/shared/Pagination/Pagination.tsx +69 -0
  33. package/src/components/shared/SearchBar/SearchBar.tsx +52 -0
  34. package/src/hooks/useLocalStorage.ts +44 -0
  35. package/src/stories/Features/craftbook/CraftBook.stories.tsx +41 -1
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
3
+ import styled from 'styled-components';
4
+ import { uiColors } from '../../../constants/uiColors';
5
+
6
+ interface PaginationProps {
7
+ currentPage: number;
8
+ totalPages: number;
9
+ onPageChange: (page: number) => void;
10
+ className?: string;
11
+ }
12
+
13
+ export const Pagination: React.FC<PaginationProps> = ({
14
+ currentPage,
15
+ totalPages,
16
+ onPageChange,
17
+ className,
18
+ }) => {
19
+ return (
20
+ <Container className={className}>
21
+ <PaginationButton
22
+ onClick={() => onPageChange(Math.max(1, currentPage - 1))}
23
+ disabled={currentPage === 1}
24
+ >
25
+ <FaChevronLeft size={12} />
26
+ </PaginationButton>
27
+ <PageInfo>
28
+ Page {currentPage} of {totalPages}
29
+ </PageInfo>
30
+ <PaginationButton
31
+ onClick={() => onPageChange(Math.min(totalPages, currentPage + 1))}
32
+ disabled={currentPage === totalPages}
33
+ >
34
+ <FaChevronRight size={12} />
35
+ </PaginationButton>
36
+ </Container>
37
+ );
38
+ };
39
+
40
+ const Container = styled.div`
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ gap: 16px;
45
+ padding: 8px;
46
+ `;
47
+
48
+ const PaginationButton = styled.button<{ disabled?: boolean }>`
49
+ background: none;
50
+ border: none;
51
+ color: ${props => (props.disabled ? uiColors.darkGray : uiColors.yellow)};
52
+ cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
53
+ opacity: ${props => (props.disabled ? 0.5 : 0.8)};
54
+ padding: 4px;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ transition: opacity 0.2s;
59
+
60
+ &:hover:not(:disabled) {
61
+ opacity: 1;
62
+ }
63
+ `;
64
+
65
+ const PageInfo = styled.div`
66
+ color: ${uiColors.lightGray};
67
+ font-size: 0.8rem;
68
+ font-family: 'Press Start 2P', cursive;
69
+ `;
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ interface SearchBarProps {
5
+ value: string;
6
+ onChange: (value: string) => void;
7
+ placeholder?: string;
8
+ className?: string;
9
+ autoFocus?: boolean;
10
+ }
11
+
12
+ export const SearchBar: React.FC<SearchBarProps> = ({
13
+ value,
14
+ onChange,
15
+ placeholder = 'Search...',
16
+ className,
17
+ autoFocus = false,
18
+ }) => {
19
+ return (
20
+ <Container className={className}>
21
+ <input
22
+ type="text"
23
+ className="rpgui-input"
24
+ placeholder={placeholder}
25
+ value={value}
26
+ onChange={e => onChange(e.target.value)}
27
+ autoFocus={autoFocus}
28
+ />
29
+ </Container>
30
+ );
31
+ };
32
+
33
+ const Container = styled.div`
34
+ input {
35
+ width: 100%;
36
+ font-size: 0.8rem;
37
+ padding: 8px 12px;
38
+ background-color: rgba(0, 0, 0, 0.3);
39
+ border: none;
40
+ color: white;
41
+ border-radius: 4px;
42
+
43
+ &::placeholder {
44
+ color: rgba(255, 255, 255, 0.5);
45
+ }
46
+
47
+ &:focus {
48
+ outline: none;
49
+ background-color: rgba(0, 0, 0, 0.4);
50
+ }
51
+ }
52
+ `;
@@ -0,0 +1,44 @@
1
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
2
+
3
+ import { useState } from 'react';
4
+
5
+ export function useLocalStorage<T>(key: string, initialValue: T) {
6
+ // State to store our value
7
+ // Pass initial state function to useState so logic is only executed once
8
+ const [storedValue, setStoredValue] = useState<T>(() => {
9
+ if (typeof window === 'undefined') {
10
+ return initialValue;
11
+ }
12
+ try {
13
+ // Get from local storage by key
14
+ const item = window.localStorage.getItem(key);
15
+ // Parse stored json or if none return initialValue
16
+ return item ? JSON.parse(item) : initialValue;
17
+ } catch (error) {
18
+ // If error also return initialValue
19
+ console.log(error);
20
+ return initialValue;
21
+ }
22
+ });
23
+
24
+ // Return a wrapped version of useState's setter function that ...
25
+ // ... persists the new value to localStorage.
26
+ const setValue = (value: T | ((val: T) => T)) => {
27
+ try {
28
+ // Allow value to be a function so we have same API as useState
29
+ const valueToStore =
30
+ value instanceof Function ? value(storedValue) : value;
31
+ // Save state
32
+ setStoredValue(valueToStore);
33
+ // Save to local storage
34
+ if (typeof window !== 'undefined') {
35
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
36
+ }
37
+ } catch (error) {
38
+ // A more advanced implementation would handle the error case
39
+ console.log(error);
40
+ }
41
+ };
42
+
43
+ return [storedValue, setValue] as const;
44
+ }
@@ -7,9 +7,37 @@ import atlasJSON from '../../../mocks/atlas/items/items.json';
7
7
  import atlasIMG from '../../../mocks/atlas/items/items.png';
8
8
  import { equipmentSetMock } from '../../../mocks/equipmentSet.mocks';
9
9
 
10
+ // Generate more mock items for pagination testing
11
+ const generateMoreItems = (baseItems: typeof craftableItems) => {
12
+ const moreItems = [...baseItems];
13
+
14
+ // Create 3 variations of each item
15
+ baseItems.forEach(item => {
16
+ for (let i = 1; i <= 3; i++) {
17
+ moreItems.push({
18
+ ...item,
19
+ key: `${item.key}-${i}`,
20
+ name: `${item.name} ${i}`,
21
+ ingredients: item.ingredients.map(ing => ({
22
+ ...ing,
23
+ key: `${ing.key}-${i}`,
24
+ qty: ing.qty + i,
25
+ })),
26
+ });
27
+ }
28
+ });
29
+
30
+ return moreItems;
31
+ };
32
+
33
+ const extendedCraftableItems = generateMoreItems(craftableItems);
34
+
10
35
  const meta: Meta = {
11
36
  title: 'Features/Crafting/Craft Book',
12
37
  component: CraftBook,
38
+ parameters: {
39
+ layout: 'fullscreen',
40
+ },
13
41
  };
14
42
 
15
43
  export default meta;
@@ -21,7 +49,7 @@ const Template: Story = args => (
21
49
  atlasJSON={atlasJSON}
22
50
  onSelect={onSelect}
23
51
  onClose={() => console.log('closing Equipment Set Container')}
24
- craftablesItems={craftableItems}
52
+ craftablesItems={extendedCraftableItems}
25
53
  onCraftItem={(value, maxCraftable) => {
26
54
  console.log('Crafting:', {
27
55
  itemKey: value,
@@ -41,3 +69,15 @@ const onSelect = (value: string) => {
41
69
  };
42
70
 
43
71
  Default.args = {};
72
+
73
+ // Add a story with search pre-filled
74
+ export const WithSearch = Template.bind({});
75
+ WithSearch.args = {
76
+ searchTerm: 'sword',
77
+ };
78
+
79
+ // Add a story with a specific category selected
80
+ export const WithCategory = Template.bind({});
81
+ WithCategory.args = {
82
+ savedSelectedType: 'Weapon',
83
+ };