|
1 | 1 | export const defaultJsx = [ |
2 | | - 'const Item = ({ value }) => <li>{value}</li>', |
3 | | - 'const List = ({ items, onClick }) => (', |
4 | | - ' <ul onClick={onClick}>', |
5 | | - ' {items.map(item => <Item key={item} value={item} />)}', |
6 | | - ' </ul>', |
| 2 | + 'type CounterButtonProps = {', |
| 3 | + ' label: string', |
| 4 | + ' onClick: (event: MouseEvent) => void', |
| 5 | + '}', |
| 6 | + '', |
| 7 | + 'const CounterButton = ({ label, onClick }: CounterButtonProps) => (', |
| 8 | + ' <button id="counter-button" type="button" onClick={onClick}>', |
| 9 | + ' {label}', |
| 10 | + ' </button>', |
7 | 11 | ')', |
8 | | - 'const Checkbox = ({ checked = false }) => <input type="checkbox" checked={checked} />', |
| 12 | + '', |
9 | 13 | 'const App = () => {', |
10 | | - " const items = ['apple', 'banana', 'orange']", |
11 | | - ' const checkbox = <Checkbox checked={true} />', |
12 | | - ' const onClickList = evt => {', |
13 | | - ' if (evt.target.contains(checkbox)) {', |
14 | | - ' checkbox.remove()', |
15 | | - ' } else {', |
16 | | - ' evt.target.appendChild(checkbox)', |
17 | | - ' }', |
| 14 | + ' let count = 0', |
| 15 | + ' const handleClick = (event: MouseEvent) => {', |
| 16 | + ' count += 1', |
| 17 | + ' const button = event.currentTarget as HTMLButtonElement', |
| 18 | + ' button.textContent = `Clicks: ${count}`', |
| 19 | + " button.dataset.active = count % 2 === 0 ? 'false' : 'true'", |
| 20 | + " button.classList.toggle('is-even', count % 2 === 0)", |
18 | 21 | ' }', |
19 | 22 | '', |
20 | | - ' return <List items={items} onClick={onClickList} />', |
| 23 | + " return <CounterButton label='Clicks: 0' onClick={handleClick} />", |
21 | 24 | '}', |
22 | 25 | '', |
23 | 26 | ].join('\n') |
24 | 27 |
|
25 | | -export const defaultCss = `ul { |
26 | | - --list-bg: linear-gradient(160deg, #d4dcec 0%, #c4cfe6 100%); |
27 | | - --list-border: #a5b4d8; |
28 | | - --item-bg: #b9bcc4; |
29 | | - --item-hover: #c5c8cf; |
30 | | - --item-text: #1f2a44; |
31 | | - --item-accent: #3658c8; |
32 | | - --check-ring: #6d86d1; |
| 28 | +export const defaultReactJsx = [ |
| 29 | + 'type CounterButtonProps = {', |
| 30 | + ' label: string', |
| 31 | + ' active: boolean', |
| 32 | + ' onClick: (event: MouseEvent) => void', |
| 33 | + '}', |
| 34 | + '', |
| 35 | + 'const CounterButton = ({ label, active, onClick }: CounterButtonProps) => (', |
| 36 | + ' <button', |
| 37 | + ' id="counter-button"', |
| 38 | + ' type="button"', |
| 39 | + ' data-active={active ? "true" : "false"}', |
| 40 | + ' className={active ? "is-even" : ""}', |
| 41 | + ' onClick={onClick}', |
| 42 | + ' >', |
| 43 | + ' {label}', |
| 44 | + ' </button>', |
| 45 | + ')', |
| 46 | + '', |
| 47 | + 'const App = () => {', |
| 48 | + ' const { useState } = React', |
| 49 | + ' const [count, setCount] = useState(0)', |
| 50 | + ' const handleClick = (_event: MouseEvent) => {', |
| 51 | + ' setCount(current => current + 1)', |
| 52 | + ' }', |
| 53 | + '', |
| 54 | + ' return (', |
| 55 | + ' <CounterButton', |
| 56 | + ' label={`React clicks: ${count}`}', |
| 57 | + ' active={count % 2 === 0}', |
| 58 | + ' onClick={handleClick}', |
| 59 | + ' />', |
| 60 | + ' )', |
| 61 | + '}', |
| 62 | + '', |
| 63 | +].join('\n') |
33 | 64 |
|
| 65 | +export const defaultCss = `#counter-button { |
34 | 66 | margin: 0; |
35 | | - padding: 14px; |
36 | | - list-style: none; |
37 | | - display: grid; |
38 | | - gap: 10px; |
39 | | - max-width: 340px; |
40 | | - border-radius: 16px; |
41 | | - border: 1px solid var(--list-border); |
42 | | - background: var(--list-bg); |
43 | | - box-shadow: |
44 | | - 0 14px 30px rgba(17, 27, 56, 0.16), |
45 | | - inset 0 1px 0 rgba(255, 255, 255, 0.55); |
46 | | -} |
47 | | -
|
48 | | -li { |
49 | | - display: flex; |
50 | | - align-items: center; |
51 | | - justify-content: space-between; |
52 | | - gap: 10px; |
53 | | - min-height: 40px; |
54 | | - padding: 10px 12px; |
55 | | - border-radius: 12px; |
56 | | - border: 1px solid rgba(54, 88, 200, 0.24); |
57 | | - background: var(--item-bg); |
58 | | - color: var(--item-text); |
59 | | - font-weight: 650; |
60 | | - letter-spacing: 0.01em; |
| 67 | + padding: 0.75rem 1rem; |
| 68 | + border: 1px solid #3558b8; |
| 69 | + border-radius: 0.5rem; |
| 70 | + background: #e9efff; |
| 71 | + color: #1a2a52; |
| 72 | + font-weight: 600; |
61 | 73 | cursor: pointer; |
62 | | - user-select: none; |
63 | | - transition: |
64 | | - transform 130ms ease, |
65 | | - background-color 130ms ease, |
66 | | - border-color 130ms ease, |
67 | | - box-shadow 130ms ease; |
68 | | -} |
69 | | -
|
70 | | -li:hover { |
71 | | - transform: translateY(-1px); |
72 | | - background: var(--item-hover); |
73 | | - border-color: rgba(54, 88, 200, 0.34); |
74 | | - box-shadow: 0 8px 18px rgba(24, 40, 95, 0.16); |
75 | | -} |
76 | | -
|
77 | | -input[type='checkbox'] { |
78 | | - appearance: none; |
79 | | - width: 18px; |
80 | | - height: 18px; |
81 | | - margin: 0; |
82 | | - border-radius: 5px; |
83 | | - border: 1.5px solid #4a63b6; |
84 | | - background: #fff; |
85 | | - display: inline-grid; |
86 | | - place-items: center; |
87 | | - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7); |
| 74 | + transition: background-color 120ms ease; |
88 | 75 | } |
89 | 76 |
|
90 | | -input[type='checkbox']::after { |
91 | | - content: ''; |
92 | | - width: 8px; |
93 | | - height: 4px; |
94 | | - border: 2px solid #fff; |
95 | | - border-top: 0; |
96 | | - border-right: 0; |
97 | | - transform: rotate(-45deg) scale(0); |
98 | | - transition: transform 120ms ease; |
| 77 | +#counter-button:hover { |
| 78 | + background: #dce6ff; |
99 | 79 | } |
100 | 80 |
|
101 | | -input[type='checkbox']:checked { |
102 | | - background: linear-gradient(145deg, var(--item-accent), #345ee0); |
103 | | - border-color: var(--item-accent); |
| 81 | +#counter-button[data-active='true'] { |
| 82 | + background: #3558b8; |
| 83 | + color: #fff; |
104 | 84 | } |
105 | 85 |
|
106 | | -input[type='checkbox']:checked::after { |
107 | | - transform: rotate(-45deg) scale(1); |
| 86 | +#counter-button.is-even { |
| 87 | + border-style: dashed; |
108 | 88 | } |
109 | 89 |
|
110 | | -input[type='checkbox']:focus-visible { |
111 | | - outline: 2px solid var(--check-ring); |
| 90 | +#counter-button:focus-visible { |
| 91 | + outline: 2px solid #6a84d8; |
112 | 92 | outline-offset: 2px; |
113 | 93 | } |
114 | 94 | ` |
0 commit comments