@gtkx/cli 0.9.2 → 0.9.4
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.
- package/dist/create.js +194 -42
- package/package.json +3 -3
package/dist/create.js
CHANGED
|
@@ -188,21 +188,41 @@ render(<App />, "com.example.myapp");
|
|
|
188
188
|
|
|
189
189
|
### Virtual Scrolling Lists
|
|
190
190
|
|
|
191
|
-
**ListView** - High-performance scrollable list:
|
|
191
|
+
**ListView** - High-performance scrollable list with selection:
|
|
192
192
|
\`\`\`tsx
|
|
193
193
|
<ListView.Root
|
|
194
194
|
vexpand
|
|
195
|
+
selected={[selectedId]}
|
|
196
|
+
selectionMode={Gtk.SelectionMode.SINGLE}
|
|
197
|
+
onSelectionChanged={(ids) => setSelectedId(ids[0])}
|
|
195
198
|
renderItem={(item: Item | null) => (
|
|
196
199
|
<Label label={item?.text ?? ""} />
|
|
197
200
|
)}
|
|
198
201
|
>
|
|
199
202
|
{items.map(item => (
|
|
200
|
-
<ListView.Item key={item.id} item={item} />
|
|
203
|
+
<ListView.Item key={item.id} id={item.id} item={item} />
|
|
201
204
|
))}
|
|
202
205
|
</ListView.Root>
|
|
203
206
|
\`\`\`
|
|
204
207
|
|
|
205
|
-
**
|
|
208
|
+
**GridView** - Grid-based virtual scrolling:
|
|
209
|
+
\`\`\`tsx
|
|
210
|
+
<GridView.Root
|
|
211
|
+
vexpand
|
|
212
|
+
renderItem={(item: Item | null) => (
|
|
213
|
+
<Box orientation={Gtk.Orientation.VERTICAL}>
|
|
214
|
+
<Image iconName={item?.icon ?? "image-missing"} />
|
|
215
|
+
<Label label={item?.name ?? ""} />
|
|
216
|
+
</Box>
|
|
217
|
+
)}
|
|
218
|
+
>
|
|
219
|
+
{items.map(item => (
|
|
220
|
+
<GridView.Item key={item.id} id={item.id} item={item} />
|
|
221
|
+
))}
|
|
222
|
+
</GridView.Root>
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
**ColumnView** - Table with sortable columns:
|
|
206
226
|
\`\`\`tsx
|
|
207
227
|
<ColumnView.Root
|
|
208
228
|
sortColumn="name"
|
|
@@ -213,28 +233,54 @@ render(<App />, "com.example.myapp");
|
|
|
213
233
|
title="Name"
|
|
214
234
|
id="name"
|
|
215
235
|
expand
|
|
236
|
+
sortable
|
|
216
237
|
renderCell={(item: Item | null) => (
|
|
217
238
|
<Label label={item?.name ?? ""} />
|
|
218
239
|
)}
|
|
219
240
|
/>
|
|
220
241
|
{items.map(item => (
|
|
221
|
-
<ColumnView.Item key={item.id} item={item} />
|
|
242
|
+
<ColumnView.Item key={item.id} id={item.id} item={item} />
|
|
222
243
|
))}
|
|
223
244
|
</ColumnView.Root>
|
|
224
245
|
\`\`\`
|
|
225
246
|
|
|
226
|
-
**DropDown** -
|
|
247
|
+
**DropDown** - String selection widget:
|
|
227
248
|
\`\`\`tsx
|
|
228
|
-
<DropDown.Root
|
|
229
|
-
itemLabel={(opt: Option) => opt.label}
|
|
230
|
-
onSelectionChanged={(item, index) => setSelected(item.value)}
|
|
231
|
-
>
|
|
249
|
+
<DropDown.Root>
|
|
232
250
|
{options.map(opt => (
|
|
233
|
-
<DropDown.Item key={opt.value}
|
|
251
|
+
<DropDown.Item key={opt.value} id={opt.value} label={opt.label} />
|
|
234
252
|
))}
|
|
235
253
|
</DropDown.Root>
|
|
236
254
|
\`\`\`
|
|
237
255
|
|
|
256
|
+
### HeaderBar
|
|
257
|
+
|
|
258
|
+
Pack widgets at start and end of the title bar:
|
|
259
|
+
\`\`\`tsx
|
|
260
|
+
<HeaderBar.Root>
|
|
261
|
+
<HeaderBar.Start>
|
|
262
|
+
<Button iconName="go-previous-symbolic" />
|
|
263
|
+
</HeaderBar.Start>
|
|
264
|
+
<HeaderBar.End>
|
|
265
|
+
<MenuButton.Root iconName="open-menu-symbolic" />
|
|
266
|
+
</HeaderBar.End>
|
|
267
|
+
</HeaderBar.Root>
|
|
268
|
+
\`\`\`
|
|
269
|
+
|
|
270
|
+
### ActionBar
|
|
271
|
+
|
|
272
|
+
Bottom bar with packed widgets:
|
|
273
|
+
\`\`\`tsx
|
|
274
|
+
<ActionBar.Root>
|
|
275
|
+
<ActionBar.Start>
|
|
276
|
+
<Button label="Cancel" />
|
|
277
|
+
</ActionBar.Start>
|
|
278
|
+
<ActionBar.End>
|
|
279
|
+
<Button label="Save" cssClasses={["suggested-action"]} />
|
|
280
|
+
</ActionBar.End>
|
|
281
|
+
</ActionBar.Root>
|
|
282
|
+
\`\`\`
|
|
283
|
+
|
|
238
284
|
### Controlled Input
|
|
239
285
|
|
|
240
286
|
Entry requires two-way binding:
|
|
@@ -406,24 +452,52 @@ Props:
|
|
|
406
452
|
## Virtual Scrolling Widgets
|
|
407
453
|
|
|
408
454
|
### ListView
|
|
409
|
-
High-performance scrollable list with virtual rendering.
|
|
455
|
+
High-performance scrollable list with virtual rendering and selection support.
|
|
410
456
|
|
|
411
457
|
\`\`\`tsx
|
|
412
458
|
<ListView.Root
|
|
413
459
|
vexpand
|
|
460
|
+
selected={[selectedId]}
|
|
461
|
+
selectionMode={Gtk.SelectionMode.SINGLE}
|
|
462
|
+
onSelectionChanged={(ids) => setSelectedId(ids[0])}
|
|
414
463
|
renderItem={(item: Item | null) => (
|
|
415
464
|
<Label label={item?.text ?? ""} />
|
|
416
465
|
)}
|
|
417
466
|
>
|
|
418
467
|
{items.map(item => (
|
|
419
|
-
<ListView.Item key={item.id} item={item} />
|
|
468
|
+
<ListView.Item key={item.id} id={item.id} item={item} />
|
|
420
469
|
))}
|
|
421
470
|
</ListView.Root>
|
|
422
471
|
\`\`\`
|
|
423
472
|
|
|
424
473
|
Props:
|
|
425
474
|
- \`renderItem\`: \`(item: T | null) => ReactElement\` (required)
|
|
426
|
-
-
|
|
475
|
+
- \`selected\`: string[] (array of selected item IDs)
|
|
476
|
+
- \`selectionMode\`: \`Gtk.SelectionMode.SINGLE\` | \`MULTIPLE\` | \`NONE\`
|
|
477
|
+
- \`onSelectionChanged\`: \`(ids: string[]) => void\`
|
|
478
|
+
|
|
479
|
+
ListView.Item props:
|
|
480
|
+
- \`id\`: string (required, unique identifier for selection)
|
|
481
|
+
- \`item\`: T (the data item)
|
|
482
|
+
|
|
483
|
+
### GridView
|
|
484
|
+
Grid-based virtual scrolling. Same API as ListView but renders items in a grid.
|
|
485
|
+
|
|
486
|
+
\`\`\`tsx
|
|
487
|
+
<GridView.Root
|
|
488
|
+
vexpand
|
|
489
|
+
renderItem={(item: Item | null) => (
|
|
490
|
+
<Box orientation={Gtk.Orientation.VERTICAL}>
|
|
491
|
+
<Image iconName={item?.icon ?? "image-missing"} />
|
|
492
|
+
<Label label={item?.name ?? ""} />
|
|
493
|
+
</Box>
|
|
494
|
+
)}
|
|
495
|
+
>
|
|
496
|
+
{items.map(item => (
|
|
497
|
+
<GridView.Item key={item.id} id={item.id} item={item} />
|
|
498
|
+
))}
|
|
499
|
+
</GridView.Root>
|
|
500
|
+
\`\`\`
|
|
427
501
|
|
|
428
502
|
### ColumnView
|
|
429
503
|
Table with sortable columns.
|
|
@@ -439,30 +513,71 @@ Table with sortable columns.
|
|
|
439
513
|
id="name"
|
|
440
514
|
expand
|
|
441
515
|
resizable
|
|
516
|
+
sortable
|
|
442
517
|
renderCell={(item: Item | null) => (
|
|
443
518
|
<Label label={item?.name ?? ""} />
|
|
444
519
|
)}
|
|
445
520
|
/>
|
|
446
521
|
{items.map(item => (
|
|
447
|
-
<ColumnView.Item key={item.id} item={item} />
|
|
522
|
+
<ColumnView.Item key={item.id} id={item.id} item={item} />
|
|
448
523
|
))}
|
|
449
524
|
</ColumnView.Root>
|
|
450
525
|
\`\`\`
|
|
451
526
|
|
|
527
|
+
ColumnView.Column props:
|
|
528
|
+
- \`title\`: string (column header)
|
|
529
|
+
- \`id\`: string (used for sorting)
|
|
530
|
+
- \`expand\`: boolean (fill available space)
|
|
531
|
+
- \`resizable\`: boolean (user can resize)
|
|
532
|
+
- \`sortable\`: boolean (clicking header triggers sort)
|
|
533
|
+
- \`fixedWidth\`: number (fixed width in pixels)
|
|
534
|
+
- \`renderCell\`: \`(item: T | null) => ReactElement\`
|
|
535
|
+
|
|
452
536
|
### DropDown
|
|
453
|
-
|
|
537
|
+
String selection dropdown.
|
|
454
538
|
|
|
455
539
|
\`\`\`tsx
|
|
456
|
-
<DropDown.Root
|
|
457
|
-
itemLabel={(opt: Option) => opt.label}
|
|
458
|
-
onSelectionChanged={(item, index) => setSelected(item.value)}
|
|
459
|
-
>
|
|
540
|
+
<DropDown.Root>
|
|
460
541
|
{options.map(opt => (
|
|
461
|
-
<DropDown.Item key={opt.value}
|
|
542
|
+
<DropDown.Item key={opt.value} id={opt.value} label={opt.label} />
|
|
462
543
|
))}
|
|
463
544
|
</DropDown.Root>
|
|
464
545
|
\`\`\`
|
|
465
546
|
|
|
547
|
+
DropDown.Item props:
|
|
548
|
+
- \`id\`: string (unique identifier)
|
|
549
|
+
- \`label\`: string (display text)
|
|
550
|
+
|
|
551
|
+
## Header Widgets
|
|
552
|
+
|
|
553
|
+
### HeaderBar
|
|
554
|
+
Title bar with packed widgets at start and end.
|
|
555
|
+
|
|
556
|
+
\`\`\`tsx
|
|
557
|
+
<HeaderBar.Root>
|
|
558
|
+
<HeaderBar.Start>
|
|
559
|
+
<Button iconName="go-previous-symbolic" />
|
|
560
|
+
</HeaderBar.Start>
|
|
561
|
+
<HeaderBar.End>
|
|
562
|
+
<MenuButton.Root iconName="open-menu-symbolic" />
|
|
563
|
+
</HeaderBar.End>
|
|
564
|
+
</HeaderBar.Root>
|
|
565
|
+
\`\`\`
|
|
566
|
+
|
|
567
|
+
### ActionBar
|
|
568
|
+
Bottom action bar with start/end packing.
|
|
569
|
+
|
|
570
|
+
\`\`\`tsx
|
|
571
|
+
<ActionBar.Root>
|
|
572
|
+
<ActionBar.Start>
|
|
573
|
+
<Button label="Cancel" />
|
|
574
|
+
</ActionBar.Start>
|
|
575
|
+
<ActionBar.End>
|
|
576
|
+
<Button label="Save" cssClasses={["suggested-action"]} />
|
|
577
|
+
</ActionBar.End>
|
|
578
|
+
</ActionBar.Root>
|
|
579
|
+
\`\`\`
|
|
580
|
+
|
|
466
581
|
## Input Widgets
|
|
467
582
|
|
|
468
583
|
### Entry
|
|
@@ -678,11 +793,12 @@ const TabContainer = () => (
|
|
|
678
793
|
|
|
679
794
|
## Virtual Scrolling Lists
|
|
680
795
|
|
|
681
|
-
### ListView with
|
|
796
|
+
### ListView with Selection
|
|
682
797
|
|
|
683
798
|
\`\`\`tsx
|
|
684
799
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
685
800
|
import { Box, Label, ListView } from "@gtkx/react";
|
|
801
|
+
import { useState } from "react";
|
|
686
802
|
|
|
687
803
|
interface Task {
|
|
688
804
|
id: string;
|
|
@@ -695,27 +811,63 @@ const tasks: Task[] = [
|
|
|
695
811
|
{ id: "2", title: "Build React app", completed: false },
|
|
696
812
|
];
|
|
697
813
|
|
|
698
|
-
const TaskList = () =>
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
)
|
|
814
|
+
const TaskList = () => {
|
|
815
|
+
const [selectedId, setSelectedId] = useState<string | undefined>();
|
|
816
|
+
|
|
817
|
+
return (
|
|
818
|
+
<Box cssClasses={["card"]} heightRequest={250}>
|
|
819
|
+
<ListView.Root
|
|
820
|
+
vexpand
|
|
821
|
+
selected={selectedId ? [selectedId] : []}
|
|
822
|
+
onSelectionChanged={(ids) => setSelectedId(ids[0])}
|
|
823
|
+
renderItem={(task: Task | null) => (
|
|
824
|
+
<Label
|
|
825
|
+
label={task?.title ?? ""}
|
|
826
|
+
cssClasses={task?.completed ? ["dim-label"] : []}
|
|
827
|
+
halign={Gtk.Align.START}
|
|
828
|
+
marginStart={12}
|
|
829
|
+
marginTop={8}
|
|
830
|
+
marginBottom={8}
|
|
831
|
+
/>
|
|
832
|
+
)}
|
|
833
|
+
>
|
|
834
|
+
{tasks.map((task) => (
|
|
835
|
+
<ListView.Item key={task.id} id={task.id} item={task} />
|
|
836
|
+
))}
|
|
837
|
+
</ListView.Root>
|
|
838
|
+
</Box>
|
|
839
|
+
);
|
|
840
|
+
};
|
|
841
|
+
\`\`\`
|
|
842
|
+
|
|
843
|
+
### HeaderBar with Navigation
|
|
844
|
+
|
|
845
|
+
\`\`\`tsx
|
|
846
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
847
|
+
import { ApplicationWindow, Box, Button, HeaderBar, Label, quit } from "@gtkx/react";
|
|
848
|
+
import { useState } from "react";
|
|
849
|
+
|
|
850
|
+
const AppWithHeaderBar = () => {
|
|
851
|
+
const [page, setPage] = useState("home");
|
|
852
|
+
|
|
853
|
+
return (
|
|
854
|
+
<ApplicationWindow title="My App" defaultWidth={600} defaultHeight={400} onCloseRequest={quit}>
|
|
855
|
+
<Box orientation={Gtk.Orientation.VERTICAL}>
|
|
856
|
+
<HeaderBar.Root>
|
|
857
|
+
<HeaderBar.Start>
|
|
858
|
+
{page !== "home" && (
|
|
859
|
+
<Button iconName="go-previous-symbolic" onClicked={() => setPage("home")} />
|
|
860
|
+
)}
|
|
861
|
+
</HeaderBar.Start>
|
|
862
|
+
<HeaderBar.End>
|
|
863
|
+
<Button iconName="emblem-system-symbolic" onClicked={() => setPage("settings")} />
|
|
864
|
+
</HeaderBar.End>
|
|
865
|
+
</HeaderBar.Root>
|
|
866
|
+
<Label label={page === "home" ? "Home Page" : "Settings Page"} vexpand />
|
|
867
|
+
</Box>
|
|
868
|
+
</ApplicationWindow>
|
|
869
|
+
);
|
|
870
|
+
};
|
|
719
871
|
\`\`\`
|
|
720
872
|
|
|
721
873
|
## Menus
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "CLI for GTKX - create and develop GTK4 React applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtk",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@vitejs/plugin-react": "^5.1.2",
|
|
48
48
|
"citty": "^0.1.6",
|
|
49
49
|
"vite": "^7.3.0",
|
|
50
|
-
"@gtkx/ffi": "0.9.
|
|
51
|
-
"@gtkx/react": "0.9.
|
|
50
|
+
"@gtkx/ffi": "0.9.4",
|
|
51
|
+
"@gtkx/react": "0.9.4"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"memfs": "^4.51.1"
|