ginskill-init 1.0.2 → 2.4.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.

Potentially problematic release.


This version of ginskill-init might be problematic. Click here for more details.

@@ -0,0 +1,310 @@
1
+ # Ant Design — Navigation Components (Menu, Tabs, Layout, Grid)
2
+
3
+ ## Menu
4
+
5
+ ```typescript
6
+ import { Menu } from 'antd';
7
+ import type { MenuProps } from 'antd';
8
+ type MenuItem = Required<MenuProps>['items'][number];
9
+ ```
10
+
11
+ ### MenuProps
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `items` | `ItemType[]` | — | Menu items array (preferred over JSX children) |
16
+ | `mode` | `'vertical' \| 'horizontal' \| 'inline'` | `'vertical'` | Layout orientation |
17
+ | `theme` | `'light' \| 'dark'` | `'light'` | Color scheme |
18
+ | `selectedKeys` | `string[]` | — | Controlled selected keys |
19
+ | `defaultSelectedKeys` | `string[]` | — | Initial selected keys (uncontrolled) |
20
+ | `openKeys` | `string[]` | — | Controlled open submenu keys |
21
+ | `defaultOpenKeys` | `string[]` | — | Initial open submenu keys (uncontrolled) |
22
+ | `inlineCollapsed` | `boolean` | — | Collapse/expand inline menu |
23
+ | `inlineIndent` | `number` | `24` | Pixel indent per nesting level |
24
+ | `multiple` | `boolean` | `false` | Allow multi-selection |
25
+ | `triggerSubMenuAction` | `'hover' \| 'click'` | `'hover'` | What opens submenus |
26
+ | `onClick` | `({ key, keyPath, domEvent }) => void` | — | Item click handler |
27
+ | `onSelect` | `({ key, keyPath, selectedKeys }) => void` | — | Item select handler |
28
+ | `onOpenChange` | `(openKeys: string[]) => void` | — | Submenu open state change |
29
+
30
+ ### ItemType Variants
31
+
32
+ ```typescript
33
+ // Menu item
34
+ type MenuItemType = {
35
+ key: string;
36
+ label: ReactNode;
37
+ icon?: ReactNode;
38
+ disabled?: boolean;
39
+ danger?: boolean; // red danger styling
40
+ title?: string; // tooltip when collapsed
41
+ };
42
+
43
+ // Submenu
44
+ type SubMenuType = {
45
+ key: string;
46
+ label: ReactNode;
47
+ icon?: ReactNode;
48
+ children: ItemType[];
49
+ popupClassName?: string;
50
+ };
51
+
52
+ // Group
53
+ type MenuItemGroupType = { type: 'group'; label?: ReactNode; children?: MenuItemType[] };
54
+
55
+ // Divider
56
+ type MenuDividerType = { type: 'divider'; dashed?: boolean };
57
+ ```
58
+
59
+ ### Patterns
60
+
61
+ ```tsx
62
+ // Sidebar (inline collapsible)
63
+ const items: MenuItem[] = [
64
+ { key: '1', icon: <PieChartOutlined />, label: 'Dashboard' },
65
+ { key: '2', icon: <MailOutlined />, label: 'Inbox' },
66
+ {
67
+ key: 'sub1', label: 'Settings', icon: <SettingOutlined />,
68
+ children: [
69
+ { key: '5', label: 'Profile' },
70
+ { key: '6', label: 'Security' },
71
+ ],
72
+ },
73
+ { type: 'divider' },
74
+ { type: 'group', label: 'Admin', children: [{ key: 'g1', label: 'Users', danger: true }] },
75
+ ];
76
+
77
+ <Menu mode="inline" theme="dark" inlineCollapsed={collapsed}
78
+ selectedKeys={[current]} onClick={({ key }) => setCurrent(key)} items={items} />
79
+
80
+ // Horizontal nav
81
+ <Menu mode="horizontal" items={items} style={{ flex: 1, minWidth: 0 }} />
82
+ ```
83
+
84
+ ### Common Mistakes
85
+ - **Use `items` prop**, not JSX children (`<Menu.Item>`) — deprecated
86
+ - **`openKeys` (controlled) requires `onOpenChange`** — or submenus never open; use `defaultOpenKeys` for uncontrolled
87
+ - **`key` must be unique** across the entire items tree
88
+ - **`inlineCollapsed` only works with `mode="inline"`**
89
+ - **Horizontal menu needs `style={{ flex: 1, minWidth: 0 }}`** to handle overflow correctly
90
+
91
+ ---
92
+
93
+ ## Tabs
94
+
95
+ ```typescript
96
+ import { Tabs } from 'antd';
97
+ import type { TabsProps } from 'antd';
98
+ ```
99
+
100
+ ### TabsProps
101
+
102
+ | Prop | Type | Default | Description |
103
+ |------|------|---------|-------------|
104
+ | `items` | `TabItemType[]` | `[]` | Tab definitions |
105
+ | `activeKey` | `string` | — | Controlled active key |
106
+ | `defaultActiveKey` | `string` | First key | Initial active key (uncontrolled) |
107
+ | `type` | `'line' \| 'card' \| 'editable-card'` | `'line'` | Visual style |
108
+ | `tabPlacement` | `'top' \| 'end' \| 'bottom' \| 'start'` | `'top'` | Tab bar position |
109
+ | `size` | `'large' \| 'middle' \| 'small'` | `'middle'` | Tab size |
110
+ | `centered` | `boolean` | `false` | Center the tab bar |
111
+ | `destroyOnHidden` | `boolean` | `false` | Unmount inactive panes |
112
+ | `animated` | `boolean \| { inkBar, tabPane }` | `{ inkBar: true, tabPane: false }` | Animation config |
113
+ | `tabBarExtraContent` | `ReactNode \| { left?, right? }` | — | Extra content in tab bar |
114
+ | `onChange` | `(activeKey: string) => void` | — | Active tab change |
115
+ | `onEdit` | `(targetKey, action: 'add' \| 'remove') => void` | — | Add/remove (editable-card only) |
116
+
117
+ ### TabItemType
118
+
119
+ | Prop | Type | Default | Description |
120
+ |------|------|---------|-------------|
121
+ | `key` | `string` | — | Unique identifier |
122
+ | `label` | `ReactNode` | — | Tab header |
123
+ | `icon` | `ReactNode` | — | Icon in header |
124
+ | `children` | `ReactNode` | — | Tab pane content |
125
+ | `disabled` | `boolean` | `false` | Disable the tab |
126
+ | `closable` | `boolean` | `true` | Show close button (editable-card) |
127
+ | `destroyOnHidden` | `boolean` | `false` | Per-tab unmount override |
128
+ | `forceRender` | `boolean` | `false` | Render before first activation |
129
+
130
+ ### Patterns
131
+
132
+ ```tsx
133
+ // Basic
134
+ const items: TabsProps['items'] = [
135
+ { key: '1', label: 'Tab 1', icon: <AppleOutlined />, children: <Content /> },
136
+ { key: '2', label: 'Tab 2', children: <Content />, disabled: true },
137
+ ];
138
+ <Tabs defaultActiveKey="1" items={items} onChange={setActiveKey} />
139
+
140
+ // Editable-card (add/remove tabs)
141
+ const onEdit = (targetKey: string, action: 'add' | 'remove') => {
142
+ if (action === 'add') addTab();
143
+ else setItems(items.filter(i => i.key !== targetKey));
144
+ };
145
+ <Tabs type="editable-card" activeKey={activeKey} onChange={setActiveKey}
146
+ onEdit={onEdit} items={items} />
147
+
148
+ // Side placement + extra content
149
+ <Tabs tabPlacement="start" items={items}
150
+ tabBarExtraContent={{ right: <Button>Action</Button> }} />
151
+ ```
152
+
153
+ ### Common Mistakes
154
+ - **`tabPosition` is deprecated** — use `tabPlacement`; values changed: `'left'/'right'` → `'start'/'end'`
155
+ - **`destroyInactiveTabPane` is deprecated** — use `destroyOnHidden`
156
+ - **`onEdit` only fires for `type="editable-card"`**
157
+ - **Tab `key` must be a string**, even for numeric IDs
158
+
159
+ ---
160
+
161
+ ## Layout
162
+
163
+ ```typescript
164
+ import { Layout } from 'antd';
165
+ const { Header, Sider, Content, Footer } = Layout;
166
+ ```
167
+
168
+ ### Layout.Sider Props
169
+
170
+ | Prop | Type | Default | Description |
171
+ |------|------|---------|-------------|
172
+ | `collapsed` | `boolean` | — | Controlled collapsed state |
173
+ | `collapsible` | `boolean` | `false` | Show collapse trigger |
174
+ | `defaultCollapsed` | `boolean` | `false` | Initial state (uncontrolled) |
175
+ | `collapsedWidth` | `number \| string` | `80` | Width when collapsed; `0` = fully hidden |
176
+ | `width` | `number \| string` | `200` | Width when expanded |
177
+ | `breakpoint` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'xxl'` | — | Responsive auto-collapse |
178
+ | `theme` | `'light' \| 'dark'` | `'dark'` | Sider color scheme |
179
+ | `trigger` | `ReactNode` | — | Custom trigger; `null` = hide trigger |
180
+ | `reverseArrow` | `boolean` | `false` | Flip arrow (for right-side siders) |
181
+ | `onCollapse` | `(collapsed, type) => void` | — | Collapse state change |
182
+ | `onBreakpoint` | `(broken: boolean) => void` | — | Responsive breakpoint hit |
183
+
184
+ ### Patterns
185
+
186
+ ```tsx
187
+ // Classic admin dashboard
188
+ <Layout style={{ minHeight: '100vh' }}>
189
+ <Sider collapsible collapsed={collapsed} onCollapse={setCollapsed}>
190
+ <Menu theme="dark" mode="inline" items={menuItems} />
191
+ </Sider>
192
+ <Layout>
193
+ <Header style={{ padding: 0, background: colorBgContainer }} />
194
+ <Content style={{ margin: 16 }}>
195
+ <div style={{ padding: 24, background: colorBgContainer, borderRadius: borderRadiusLG }}>
196
+ Page Content
197
+ </div>
198
+ </Content>
199
+ <Footer style={{ textAlign: 'center' }}>App ©{new Date().getFullYear()}</Footer>
200
+ </Layout>
201
+ </Layout>
202
+
203
+ // Custom trigger in header (not Sider)
204
+ <Sider trigger={null} collapsible collapsed={collapsed}>...</Sider>
205
+ <Header>
206
+ <Button type="text" icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
207
+ onClick={() => setCollapsed(!collapsed)} />
208
+ </Header>
209
+
210
+ // Responsive auto-collapse at lg
211
+ <Sider breakpoint="lg" collapsedWidth="0" onBreakpoint={console.log}>
212
+ <Menu theme="dark" mode="inline" items={menuItems} />
213
+ </Sider>
214
+
215
+ // Sticky sider (scrollable content)
216
+ <Layout hasSider>
217
+ <Sider style={{ overflow: 'auto', height: '100vh', position: 'sticky', top: 0, insetInlineStart: 0 }}>
218
+ ...
219
+ </Sider>
220
+ <Layout>...</Layout>
221
+ </Layout>
222
+ ```
223
+
224
+ ### Common Mistakes
225
+ - **Add `hasSider` for SSR** — prevents layout flash during hydration
226
+ - **`trigger={null}` requires your own toggle mechanism**
227
+ - **Sider `theme` and Menu `theme` must match** or background colors conflict
228
+ - **`collapsedWidth={0}` shows a floating trigger button** — style it with `zeroWidthTriggerStyle`
229
+ - **Outer Layout needs `minHeight: '100vh'`** for full-page dashboard backgrounds
230
+
231
+ ---
232
+
233
+ ## Grid (Row / Col)
234
+
235
+ ```typescript
236
+ import { Row, Col, Grid } from 'antd';
237
+ const { useBreakpoint } = Grid;
238
+ ```
239
+
240
+ 24-column Flex-based layout system.
241
+
242
+ ### Breakpoints
243
+
244
+ | Name | Min Width |
245
+ |------|-----------|
246
+ | `xs` | < 576px |
247
+ | `sm` | ≥ 576px |
248
+ | `md` | ≥ 768px |
249
+ | `lg` | ≥ 992px |
250
+ | `xl` | ≥ 1200px |
251
+ | `xxl` | ≥ 1600px |
252
+
253
+ ### Row Props
254
+
255
+ | Prop | Type | Default | Description |
256
+ |------|------|---------|-------------|
257
+ | `gutter` | `number \| [h, v] \| { xs, sm, md, lg, xl, xxl }` | `0` | Column spacing |
258
+ | `justify` | `'start' \| 'end' \| 'center' \| 'space-around' \| 'space-between' \| 'space-evenly'` | `'start'` | Horizontal distribution |
259
+ | `align` | `'top' \| 'middle' \| 'bottom' \| 'stretch'` | `'top'` | Vertical alignment |
260
+ | `wrap` | `boolean` | `true` | Whether columns wrap |
261
+
262
+ ### Col Props
263
+
264
+ | Prop | Type | Default | Description |
265
+ |------|------|---------|-------------|
266
+ | `span` | `number` | — | Columns to span (0–24); `0` = hidden |
267
+ | `offset` | `number` | `0` | Left offset columns |
268
+ | `order` | `number` | `0` | Flex order |
269
+ | `push` / `pull` | `number` | `0` | Visual shift (no DOM change) |
270
+ | `flex` | `number \| string` | — | CSS flex value |
271
+ | `xs/sm/md/lg/xl/xxl` | `number \| ColSize` | — | Responsive config |
272
+
273
+ `ColSize = { span?, offset?, order?, push?, pull?, flex? }`
274
+
275
+ ### Patterns
276
+
277
+ ```tsx
278
+ // Responsive card grid
279
+ <Row gutter={[16, 16]}>
280
+ <Col xs={24} sm={12} md={8} lg={6}><Card /></Col>
281
+ <Col xs={24} sm={12} md={8} lg={6}><Card /></Col>
282
+ <Col xs={24} sm={12} md={8} lg={6}><Card /></Col>
283
+ <Col xs={24} sm={12} md={8} lg={6}><Card /></Col>
284
+ </Row>
285
+
286
+ // Flex ratio layout
287
+ <Row>
288
+ <Col flex={2}>2/5</Col>
289
+ <Col flex={3}>3/5</Col>
290
+ </Row>
291
+
292
+ // Fixed + auto-fill
293
+ <Row>
294
+ <Col flex="100px">Fixed</Col>
295
+ <Col flex="auto">Fills rest</Col>
296
+ </Row>
297
+
298
+ // Responsive hook
299
+ const screens = useBreakpoint();
300
+ // { xs: true, sm: true, md: false, ... }
301
+ const isMobile = !screens.md;
302
+ ```
303
+
304
+ ### Common Mistakes
305
+ - **Spans must sum ≤ 24** or columns wrap (by design)
306
+ - **`gutter` adds padding to Col, negative margin to Row** — don't add extra padding to Col children
307
+ - **Nested grids**: always `Row > Col > Row > Col` — never Col directly inside Col
308
+ - **`offset` vs `push`**: `offset` counts toward total span, `push` is visual-only
309
+ - **Breakpoints are mobile-first** — `xs` applies at all sizes unless overridden
310
+ - **`useBreakpoint` may return `undefined` on SSR** — use strict `=== true` comparisons