@asafarim/shared-i18n 0.6.6 → 0.8.0

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 (80) hide show
  1. package/demo/dist/Icon Dropdown_Limited Languages.png +0 -0
  2. package/demo/dist/Select Dropdown_Text Only.png +0 -0
  3. package/demo/dist/assets/favicon-BZYZvBLo.svg +4 -0
  4. package/demo/dist/assets/index-BdjqKw_N.css +1 -0
  5. package/demo/dist/assets/index-C1Tq1uEr.js +191 -0
  6. package/demo/dist/favicon.svg +4 -0
  7. package/demo/dist/index.html +27 -0
  8. package/demo/dist/logo.svg +24 -0
  9. package/demo/node_modules/.bin/browserslist +21 -0
  10. package/demo/node_modules/.bin/browserslist.CMD +12 -0
  11. package/demo/node_modules/.bin/browserslist.ps1 +41 -0
  12. package/demo/node_modules/.bin/tsc +4 -4
  13. package/demo/node_modules/.bin/tsc.CMD +12 -0
  14. package/demo/node_modules/.bin/tsc.ps1 +41 -0
  15. package/demo/node_modules/.bin/tsserver +4 -4
  16. package/demo/node_modules/.bin/tsserver.CMD +12 -0
  17. package/demo/node_modules/.bin/tsserver.ps1 +41 -0
  18. package/demo/node_modules/.bin/vite +4 -4
  19. package/demo/node_modules/.bin/vite.CMD +12 -0
  20. package/demo/node_modules/.bin/vite.ps1 +41 -0
  21. package/demo/node_modules/.vite/deps/@asafarim_country-language-selector.js +848 -0
  22. package/demo/node_modules/.vite/deps/@asafarim_country-language-selector.js.map +7 -0
  23. package/demo/node_modules/.vite/deps/_metadata.json +76 -0
  24. package/demo/node_modules/.vite/deps/chunk-5WRI5ZAA.js +30 -0
  25. package/demo/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +7 -0
  26. package/demo/node_modules/.vite/deps/chunk-B3AHR5EX.js +1004 -0
  27. package/demo/node_modules/.vite/deps/chunk-B3AHR5EX.js.map +7 -0
  28. package/demo/node_modules/.vite/deps/chunk-E6BG6WAU.js +292 -0
  29. package/demo/node_modules/.vite/deps/chunk-E6BG6WAU.js.map +7 -0
  30. package/demo/node_modules/.vite/deps/chunk-MVARZQEG.js +280 -0
  31. package/demo/node_modules/.vite/deps/chunk-MVARZQEG.js.map +7 -0
  32. package/demo/node_modules/.vite/deps/i18next-browser-languagedetector.js +400 -0
  33. package/demo/node_modules/.vite/deps/i18next-browser-languagedetector.js.map +7 -0
  34. package/demo/node_modules/.vite/deps/i18next.js +2392 -0
  35. package/demo/node_modules/.vite/deps/i18next.js.map +7 -0
  36. package/demo/node_modules/.vite/deps/package.json +3 -0
  37. package/demo/node_modules/.vite/deps/react-dom.js +6 -0
  38. package/demo/node_modules/.vite/deps/react-dom.js.map +7 -0
  39. package/demo/node_modules/.vite/deps/react-dom_client.js +20217 -0
  40. package/demo/node_modules/.vite/deps/react-dom_client.js.map +7 -0
  41. package/demo/node_modules/.vite/deps/react-i18next.js +869 -0
  42. package/demo/node_modules/.vite/deps/react-i18next.js.map +7 -0
  43. package/demo/node_modules/.vite/deps/react.js +5 -0
  44. package/demo/node_modules/.vite/deps/react.js.map +7 -0
  45. package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +278 -0
  46. package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  47. package/demo/node_modules/.vite/deps/react_jsx-runtime.js +6 -0
  48. package/demo/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
  49. package/demo/package.json +27 -24
  50. package/demo/public/favicon.svg +4 -4
  51. package/demo/public/logo.svg +24 -24
  52. package/demo/src/App.tsx +129 -116
  53. package/demo/src/components/CountryLanguageDemo.tsx +140 -0
  54. package/demo/src/components/GetStartedSection.tsx +56 -56
  55. package/demo/src/components/KeyTable.tsx +29 -29
  56. package/demo/src/components/LanguageBar.tsx +102 -18
  57. package/demo/src/components/LanguageSwitcherDemo.module.css +114 -113
  58. package/demo/src/components/LanguageSwitcherDemo.tsx +256 -202
  59. package/demo/src/components/Logo.tsx +6 -6
  60. package/demo/src/components/OverviewSection.tsx +43 -43
  61. package/demo/src/components/Panel.tsx +15 -15
  62. package/demo/src/components/StatusCard.tsx +109 -109
  63. package/demo/src/index.css +644 -605
  64. package/demo/src/locales/de/demo.json +85 -0
  65. package/demo/src/locales/en/demo.json +85 -85
  66. package/demo/src/locales/fr/demo.json +85 -85
  67. package/demo/src/locales/it/demo.json +85 -0
  68. package/demo/src/locales/nl/demo.json +85 -85
  69. package/demo/src/main.tsx +29 -24
  70. package/demo/tsconfig.json +18 -18
  71. package/demo/tsconfig.node.json +10 -10
  72. package/demo/tsconfig.tsbuildinfo +1 -1
  73. package/demo/vite-env.d.ts +7 -7
  74. package/demo/vite.config.d.ts +2 -2
  75. package/demo/vite.config.js +10 -10
  76. package/dist/components/LanguageSwitcher.module.css +303 -303
  77. package/dist/locales/de/common.json +68 -0
  78. package/dist/locales/it/common.json +68 -0
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +85 -84
@@ -1,202 +1,256 @@
1
- import { LanguageSwitcher } from '@asafarim/shared-i18n'
2
- import styles from './LanguageSwitcherDemo.module.css'
3
-
4
- interface DemoItemProps {
5
- title: string
6
- description: string
7
- code: string
8
- children: React.ReactNode
9
- }
10
-
11
- function DemoItem({ title, description, code, children }: DemoItemProps) {
12
- return (
13
- <div className={styles.demoItem}>
14
- <div className={styles.demoHeader}>
15
- <h4 className={styles.demoTitle}>{title}</h4>
16
- <p className={styles.demoDescription}>{description}</p>
17
- </div>
18
- <div className={styles.demoContent}>
19
- <div className={styles.demoPreview}>
20
- <div className={styles.previewLabel}>Preview</div>
21
- {children}
22
- </div>
23
- <div className={styles.demoCode}>
24
- <div className={styles.codeLabel}>Code</div>
25
- <pre className={styles.codeBlock}>{code}</pre>
26
- </div>
27
- </div>
28
- </div>
29
- )
30
- }
31
-
32
- export default function LanguageSwitcherDemo() {
33
- return (
34
- <div className={styles.container}>
35
- <DemoItem
36
- title="Buttons Variant"
37
- description="Display all languages as individual button options"
38
- code={`<LanguageSwitcher
39
- variant="buttons"
40
- buttonClassName="lang-button"
41
- unstyled={false}
42
- />`}
43
- >
44
- <LanguageSwitcher
45
- variant="buttons"
46
- buttonClassName="lang-button"
47
- unstyled={false}
48
- />
49
- </DemoItem>
50
-
51
- <DemoItem
52
- title="Select Dropdown - Text Only"
53
- description="Dropdown with language names, no emojis"
54
- code={`<LanguageSwitcher
55
- variant="select"
56
- selectClassName="lang-select"
57
- unstyled={false}
58
- showEmoji={false}
59
- />`}
60
- >
61
- <LanguageSwitcher
62
- variant="select"
63
- unstyled={true}
64
- showEmoji={false}
65
- showLabel={true}
66
- />
67
- </DemoItem>
68
-
69
- <DemoItem
70
- title="Select Dropdown - Emoji Only (2 Languages)"
71
- description="Compact dropdown showing only emojis for language selection"
72
- code={`<LanguageSwitcher
73
- variant="select"
74
- selectClassName="lang-select"
75
- unstyled={true}
76
- showEmoji={true}
77
- languages={['en', 'nl']}
78
- isToggler={false}
79
- />`}
80
- >
81
- <LanguageSwitcher
82
- variant="select"
83
- selectClassName="lang-select"
84
- unstyled={true}
85
- showEmoji={true}
86
- languages={['en', 'nl']}
87
- isToggler={false}
88
- />
89
- </DemoItem>
90
-
91
- <DemoItem
92
- title="Toggle Button (2 Languages)"
93
- description="Automatic toggle button when exactly 2 languages are provided"
94
- code={`<LanguageSwitcher
95
- variant="select"
96
- selectClassName="lang-select"
97
- unstyled={true}
98
- showEmoji={true}
99
- languages={['en', 'nl']}
100
- isToggler={true}
101
- />`}
102
- >
103
- <LanguageSwitcher
104
- variant="select"
105
- selectClassName="lang-select"
106
- unstyled={true}
107
- showEmoji={true}
108
- languages={['en', 'nl']}
109
- isToggler={true}
110
- />
111
- </DemoItem>
112
-
113
- <DemoItem
114
- title="Icon Dropdown"
115
- description="Minimal icon-based dropdown for all languages"
116
- code={`<LanguageSwitcher
117
- variant="icon-dropdown"
118
- unstyled={false}
119
- />`}
120
- >
121
- <LanguageSwitcher
122
- variant="icon-dropdown"
123
- unstyled={false}
124
- />
125
- </DemoItem>
126
-
127
- <DemoItem
128
- title="Icon Dropdown - Limited Languages"
129
- description="Icon dropdown restricted to specific languages"
130
- code={`<LanguageSwitcher
131
- variant="icon-dropdown"
132
- languages={['en', 'nl']}
133
- unstyled={false}
134
- />`}
135
- >
136
- <LanguageSwitcher
137
- variant="icon-dropdown"
138
- languages={['en', 'nl']}
139
- unstyled={false}
140
- />
141
- </DemoItem>
142
-
143
- <DemoItem
144
- title="Icon Dropdown - Limited Languages with Labels"
145
- description="Icon dropdown with language names displayed next to flags"
146
- code={`<LanguageSwitcher
147
- variant="icon-dropdown"
148
- languages={['en', 'nl']}
149
- unstyled={false}
150
- showLabelInIconDropdown={true}
151
- />`}
152
- >
153
- <LanguageSwitcher
154
- variant="icon-dropdown"
155
- languages={['en', 'nl']}
156
- unstyled={false}
157
- showLabelInIconDropdown={true}
158
- />
159
- </DemoItem>
160
-
161
- <DemoItem
162
- title="Select Dropdown - Text Only (2 Languages)"
163
- description="Standard dropdown with text labels for 2 languages"
164
- code={`<LanguageSwitcher
165
- variant="select"
166
- selectClassName="lang-select"
167
- unstyled={false}
168
- showEmoji={false}
169
- languages={['en', 'nl']}
170
- isToggler={false}
171
- />`}
172
- >
173
- <LanguageSwitcher
174
- variant="select"
175
- selectClassName="lang-select"
176
- unstyled={false}
177
- showEmoji={false}
178
- languages={['en', 'nl']}
179
- isToggler={false}
180
- />
181
- </DemoItem>
182
-
183
- <DemoItem
184
- title="Buttons Variant - Limited Languages"
185
- description="Button variant restricted to specific languages"
186
- code={`<LanguageSwitcher
187
- variant="buttons"
188
- buttonClassName="lang-button"
189
- unstyled={false}
190
- languages={['en', 'nl']}
191
- />`}
192
- >
193
- <LanguageSwitcher
194
- variant="buttons"
195
- buttonClassName="lang-button"
196
- unstyled={false}
197
- languages={['en', 'nl']}
198
- />
199
- </DemoItem>
200
- </div>
201
- )
202
- }
1
+ import { LanguageSwitcher } from '@asafarim/shared-i18n'
2
+ import { CountryLanguageSelector } from '@asafarim/country-language-selector'
3
+ import styles from './LanguageSwitcherDemo.module.css'
4
+
5
+ interface DemoItemProps {
6
+ title: string
7
+ description: string
8
+ code: string
9
+ children: React.ReactNode
10
+ }
11
+
12
+ function DemoItem({ title, description, code, children }: DemoItemProps) {
13
+ return (
14
+ <div className={styles.demoItem}>
15
+ <div className={styles.demoHeader}>
16
+ <h4 className={styles.demoTitle}>{title}</h4>
17
+ <p className={styles.demoDescription}>{description}</p>
18
+ </div>
19
+ <div className={styles.demoContent}>
20
+ <div className={styles.demoPreview}>
21
+ <div className={styles.previewLabel}>Preview</div>
22
+ {children}
23
+ </div>
24
+ <div className={styles.demoCode}>
25
+ <div className={styles.codeLabel}>Code</div>
26
+ <pre className={styles.codeBlock}>{code}</pre>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ )
31
+ }
32
+
33
+ export default function LanguageSwitcherDemo() {
34
+ const countries = [
35
+ {
36
+ code: 'BE',
37
+ name: 'Belgium',
38
+ nativeName: 'België',
39
+ flag: '🇧🇪',
40
+ languages: [
41
+ { code: 'nl', label: 'Dutch', nativeLabel: 'Nederlands' },
42
+ { code: 'fr', label: 'French', nativeLabel: 'Français' },
43
+ { code: 'de', label: 'German', nativeLabel: 'Deutsch' }
44
+ ]
45
+ },
46
+ {
47
+ code: 'CH',
48
+ name: 'Switzerland',
49
+ nativeName: 'Schweiz',
50
+ flag: '🇨🇭',
51
+ languages: [
52
+ { code: 'de', label: 'German', nativeLabel: 'Deutsch' },
53
+ { code: 'fr', label: 'French', nativeLabel: 'Français' },
54
+ { code: 'it', label: 'Italian', nativeLabel: 'Italiano' },
55
+ { code: 'rm', label: 'Romansh', nativeLabel: 'Rumantsch' }
56
+ ]
57
+ },
58
+ {
59
+ code: 'CA',
60
+ name: 'Canada',
61
+ nativeName: 'Canada',
62
+ flag: '🇨🇦',
63
+ languages: [
64
+ { code: 'en', label: 'English' },
65
+ { code: 'fr', label: 'French', nativeLabel: 'Français' }
66
+ ]
67
+ }
68
+ ]
69
+
70
+ return (
71
+ <div className={styles.container}>
72
+ <DemoItem
73
+ title="Buttons Variant"
74
+ description="Display all languages as individual button options"
75
+ code={`<LanguageSwitcher
76
+ variant="buttons"
77
+ buttonClassName="lang-button"
78
+ unstyled={false}
79
+ />`}
80
+ >
81
+ <LanguageSwitcher
82
+ variant="buttons"
83
+ buttonClassName="lang-button"
84
+ unstyled={false}
85
+ />
86
+ </DemoItem>
87
+
88
+ <DemoItem
89
+ title="Select Dropdown - Text Only"
90
+ description="Dropdown with language names, no emojis"
91
+ code={`<LanguageSwitcher
92
+ variant="select"
93
+ selectClassName="lang-select"
94
+ unstyled={false}
95
+ showEmoji={false}
96
+ />`}
97
+ >
98
+ <LanguageSwitcher
99
+ variant="select"
100
+ unstyled={true}
101
+ showEmoji={false}
102
+ showLabel={true}
103
+ />
104
+ </DemoItem>
105
+
106
+ <DemoItem
107
+ title="Select Dropdown - Emoji Only (2 Languages)"
108
+ description="Compact dropdown showing only emojis for language selection"
109
+ code={`<LanguageSwitcher
110
+ variant="select"
111
+ selectClassName="lang-select"
112
+ unstyled={true}
113
+ showEmoji={true}
114
+ languages={['en', 'nl']}
115
+ isToggler={false}
116
+ />`}
117
+ >
118
+ <LanguageSwitcher
119
+ variant="select"
120
+ selectClassName="lang-select"
121
+ unstyled={true}
122
+ showEmoji={true}
123
+ languages={['en', 'nl']}
124
+ isToggler={false}
125
+ />
126
+ </DemoItem>
127
+
128
+ <DemoItem
129
+ title="Toggle Button (2 Languages)"
130
+ description="Automatic toggle button when exactly 2 languages are provided"
131
+ code={`<LanguageSwitcher
132
+ variant="select"
133
+ selectClassName="lang-select"
134
+ unstyled={true}
135
+ showEmoji={true}
136
+ languages={['en', 'nl']}
137
+ isToggler={true}
138
+ />`}
139
+ >
140
+ <LanguageSwitcher
141
+ variant="select"
142
+ selectClassName="lang-select"
143
+ unstyled={true}
144
+ showEmoji={true}
145
+ languages={['en', 'nl']}
146
+ isToggler={true}
147
+ />
148
+ </DemoItem>
149
+
150
+ <DemoItem
151
+ title="Icon Dropdown"
152
+ description="Minimal icon-based dropdown for all languages"
153
+ code={`<LanguageSwitcher
154
+ variant="icon-dropdown"
155
+ unstyled={false}
156
+ />`}
157
+ >
158
+ <LanguageSwitcher
159
+ variant="icon-dropdown"
160
+ unstyled={false}
161
+ />
162
+ </DemoItem>
163
+
164
+ <DemoItem
165
+ title="Icon Dropdown - Limited Languages"
166
+ description="Icon dropdown restricted to specific languages"
167
+ code={`<LanguageSwitcher
168
+ variant="icon-dropdown"
169
+ languages={['en', 'nl']}
170
+ unstyled={false}
171
+ />`}
172
+ >
173
+ <LanguageSwitcher
174
+ variant="icon-dropdown"
175
+ languages={['en', 'nl']}
176
+ unstyled={false}
177
+ />
178
+ </DemoItem>
179
+
180
+ <DemoItem
181
+ title="Icon Dropdown - Limited Languages with Labels"
182
+ description="Icon dropdown with language names displayed next to flags"
183
+ code={`<LanguageSwitcher
184
+ variant="icon-dropdown"
185
+ languages={['en', 'nl']}
186
+ unstyled={false}
187
+ showLabelInIconDropdown={true}
188
+ />`}
189
+ >
190
+ <LanguageSwitcher
191
+ variant="icon-dropdown"
192
+ languages={['en', 'nl']}
193
+ unstyled={false}
194
+ showLabelInIconDropdown={true}
195
+ />
196
+ </DemoItem>
197
+
198
+ <DemoItem
199
+ title="Select Dropdown - Text Only (2 Languages)"
200
+ description="Standard dropdown with text labels for 2 languages"
201
+ code={`<LanguageSwitcher
202
+ variant="select"
203
+ selectClassName="lang-select"
204
+ unstyled={false}
205
+ showEmoji={false}
206
+ languages={['en', 'nl']}
207
+ isToggler={false}
208
+ />`}
209
+ >
210
+ <LanguageSwitcher
211
+ variant="select"
212
+ selectClassName="lang-select"
213
+ unstyled={false}
214
+ showEmoji={false}
215
+ languages={['en', 'nl']}
216
+ isToggler={false}
217
+ />
218
+ </DemoItem>
219
+
220
+ <DemoItem
221
+ title="Buttons Variant - Limited Languages"
222
+ description="Button variant restricted to specific languages"
223
+ code={`<LanguageSwitcher
224
+ variant="buttons"
225
+ buttonClassName="lang-button"
226
+ unstyled={false}
227
+ languages={['en', 'nl']}
228
+ />`}
229
+ >
230
+ <LanguageSwitcher
231
+ variant="buttons"
232
+ buttonClassName="lang-button"
233
+ unstyled={false}
234
+ languages={['en', 'nl']}
235
+ />
236
+ </DemoItem>
237
+
238
+ <DemoItem
239
+ title="Country-Language Selector (Header)"
240
+ description="The header now uses CountryLanguageSelector for Belgium, Switzerland, and Canada with their official languages"
241
+ code={`<CountryLanguageSelector
242
+ countries={countries}
243
+ defaultValue={{ country: 'BE', language: 'nl' }}
244
+ persistKey="demo-locale"
245
+ triggerVariant="compact"
246
+ onChange={(locale) => i18n.changeLanguage(locale.language)}
247
+ />`}
248
+ >
249
+ <div style={{ padding: '1rem', border: '1px solid #ccc', borderRadius: '4px' }}>
250
+ <p>The country-language selector is now in the header above.</p>
251
+ <p>Try selecting different countries and languages to see the interface change!</p>
252
+ </div>
253
+ </DemoItem>
254
+ </div>
255
+ )
256
+ }
@@ -1,7 +1,7 @@
1
- export default function Logo({width = 70}: {width?: number}) {
2
- return (
3
- <div className="logo">
4
- <img src={import.meta.env.BASE_URL + "logo.svg"} alt="Logo" width={width} />
5
- </div>
6
- )
1
+ export default function Logo({width = 70}: {width?: number}) {
2
+ return (
3
+ <div className="logo">
4
+ <img src={import.meta.env.BASE_URL + "logo.svg"} alt="Logo" width={width} />
5
+ </div>
6
+ )
7
7
  }
@@ -1,43 +1,43 @@
1
- import { useTranslation } from '@asafarim/shared-i18n'
2
-
3
- export default function OverviewSection() {
4
- const { t } = useTranslation('demo')
5
- const overview = t('overview', { returnObjects: true }) as any
6
-
7
- return (
8
- <div className="overview-section">
9
- <div className="overview-header">
10
- <h2 className="overview-title">{overview.heading}</h2>
11
- <p className="overview-description">{overview.description}</p>
12
- </div>
13
-
14
- <div className="overview-grid">
15
- <div className="feature-card">
16
- <div className="feature-icon">✨</div>
17
- <h3>{overview.features.title}</h3>
18
- <ul className="feature-list">
19
- {overview.features.items.map((item: string, idx: number) => (
20
- <li key={idx}>
21
- <span className="feature-dot">•</span>
22
- {item}
23
- </li>
24
- ))}
25
- </ul>
26
- </div>
27
-
28
- <div className="feature-card">
29
- <div className="feature-icon">🎯</div>
30
- <h3>{overview.useCases.title}</h3>
31
- <ul className="feature-list">
32
- {overview.useCases.items.map((item: string, idx: number) => (
33
- <li key={idx}>
34
- <span className="feature-dot">→</span>
35
- {item}
36
- </li>
37
- ))}
38
- </ul>
39
- </div>
40
- </div>
41
- </div>
42
- )
43
- }
1
+ import { useTranslation } from '@asafarim/shared-i18n'
2
+
3
+ export default function OverviewSection() {
4
+ const { t } = useTranslation('demo')
5
+ const overview = t('overview', { returnObjects: true }) as any
6
+
7
+ return (
8
+ <div className="overview-section">
9
+ <div className="overview-header">
10
+ <h2 className="overview-title">{overview.heading}</h2>
11
+ <p className="overview-description">{overview.description}</p>
12
+ </div>
13
+
14
+ <div className="overview-grid">
15
+ <div className="feature-card">
16
+ <div className="feature-icon">✨</div>
17
+ <h3>{overview.features.title}</h3>
18
+ <ul className="feature-list">
19
+ {overview.features.items.map((item: string, idx: number) => (
20
+ <li key={idx}>
21
+ <span className="feature-dot">•</span>
22
+ {item}
23
+ </li>
24
+ ))}
25
+ </ul>
26
+ </div>
27
+
28
+ <div className="feature-card">
29
+ <div className="feature-icon">🎯</div>
30
+ <h3>{overview.useCases.title}</h3>
31
+ <ul className="feature-list">
32
+ {overview.useCases.items.map((item: string, idx: number) => (
33
+ <li key={idx}>
34
+ <span className="feature-dot">→</span>
35
+ {item}
36
+ </li>
37
+ ))}
38
+ </ul>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ )
43
+ }
@@ -1,15 +1,15 @@
1
- import { ReactNode } from 'react'
2
-
3
- interface PanelProps {
4
- title: string
5
- children: ReactNode
6
- }
7
-
8
- export default function Panel({ title, children }: PanelProps) {
9
- return (
10
- <div className="panel">
11
- <h2 className="panel-title">{title}</h2>
12
- {children}
13
- </div>
14
- )
15
- }
1
+ import { ReactNode } from 'react'
2
+
3
+ interface PanelProps {
4
+ title: string
5
+ children: ReactNode
6
+ }
7
+
8
+ export default function Panel({ title, children }: PanelProps) {
9
+ return (
10
+ <div className="panel">
11
+ <h2 className="panel-title">{title}</h2>
12
+ {children}
13
+ </div>
14
+ )
15
+ }