@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.
Files changed (2) hide show
  1. package/dist/create.js +194 -42
  2. 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
- **ColumnView** - Table with columns:
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** - Selection widget:
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} item={opt} />
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
- - Standard scrollable props
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
- Selection dropdown with custom rendering.
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} item={opt} />
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 Custom Rendering
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
- <Box cssClasses={["card"]} heightRequest={250}>
700
- <ListView.Root
701
- vexpand
702
- renderItem={(task: Task | null) => (
703
- <Label
704
- label={task?.title ?? ""}
705
- cssClasses={task?.completed ? ["dim-label"] : []}
706
- halign={Gtk.Align.START}
707
- marginStart={12}
708
- marginTop={8}
709
- marginBottom={8}
710
- />
711
- )}
712
- >
713
- {tasks.map((task) => (
714
- <ListView.Item key={task.id} item={task} />
715
- ))}
716
- </ListView.Root>
717
- </Box>
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.2",
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.2",
51
- "@gtkx/react": "0.9.2"
50
+ "@gtkx/ffi": "0.9.4",
51
+ "@gtkx/react": "0.9.4"
52
52
  },
53
53
  "devDependencies": {
54
54
  "memfs": "^4.51.1"