@ssebastien/tcmd 0.1.3 → 0.1.7
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/README.md +256 -62
- package/bin/tcmd +10 -2
- package/bin/tcmd.js +13 -2
- package/desktop/dist/index.html +13 -0
- package/desktop/dist/main.js +20298 -0
- package/desktop/dist/style.css +1515 -0
- package/desktop/frontend/index.html +13 -0
- package/package.json +19 -6
- package/public/fonts/OFL.txt +93 -0
- package/public/index.html +14 -0
- package/public/licenses/LUCIDE.txt +43 -0
- package/public/main.js +20679 -0
- package/public/style.css +1515 -0
- package/scripts/build-desktop.js +31 -0
- package/scripts/serve-web.js +61 -0
- package/src/js/tcmd/components/App.html +80 -14
- package/src/js/tcmd/components/App.js +339 -114
- package/src/js/tcmd/components/App.xml +76 -22
- package/src/js/tcmd/components/BookmarkList.html +5 -5
- package/src/js/tcmd/components/BookmarkList.js +15 -41
- package/src/js/tcmd/components/BookmarkList.xml +1 -2
- package/src/js/tcmd/components/BookmarkRow.html +2 -1
- package/src/js/tcmd/components/BookmarkRow.js +14 -9
- package/src/js/tcmd/components/BookmarkRow.xml +1 -1
- package/src/js/tcmd/components/Breadcrumbs.js +1 -1
- package/src/js/tcmd/components/CommandArgRow.html +28 -0
- package/src/js/tcmd/components/CommandArgRow.js +146 -30
- package/src/js/tcmd/components/CommandArgRow.xml +55 -4
- package/src/js/tcmd/components/CommandBar.html +2 -2
- package/src/js/tcmd/components/CommandBar.js +33 -27
- package/src/js/tcmd/components/CommandBar.xml +2 -2
- package/src/js/tcmd/components/CommandItem.html +1 -1
- package/src/js/tcmd/components/CommandItem.js +25 -25
- package/src/js/tcmd/components/CommandItem.xml +2 -2
- package/src/js/tcmd/components/CommandPanel.html +29 -0
- package/src/js/tcmd/components/CommandPanel.js +78 -52
- package/src/js/tcmd/components/CommandPanel.xml +49 -25
- package/src/js/tcmd/components/Confirm.html +2 -2
- package/src/js/tcmd/components/EntryDetail.html +7 -7
- package/src/js/tcmd/components/EntryDetail.js +22 -8
- package/src/js/tcmd/components/FileList.html +5 -1
- package/src/js/tcmd/components/FileList.js +2 -1
- package/src/js/tcmd/components/FilePicker.html +10 -0
- package/src/js/tcmd/components/FilePicker.js +43 -0
- package/src/js/tcmd/components/FilePicker.xml +13 -0
- package/src/js/tcmd/components/FilePickerRow.html +6 -0
- package/src/js/tcmd/components/FilePickerRow.js +27 -0
- package/src/js/tcmd/components/FilePickerRow.xml +10 -0
- package/src/js/tcmd/components/FilePreview.html +14 -4
- package/src/js/tcmd/components/FilePreview.js +111 -12
- package/src/js/tcmd/components/FilePreview.xml +28 -8
- package/src/js/tcmd/components/FileRow.html +2 -1
- package/src/js/tcmd/components/FileRow.js +70 -12
- package/src/js/tcmd/components/FilterBar.html +1 -1
- package/src/js/tcmd/components/FilterBar.js +14 -4
- package/src/js/tcmd/components/FilterBar.xml +1 -1
- package/src/js/tcmd/components/Frame.js +324 -0
- package/src/js/tcmd/components/Help.html +15 -0
- package/src/js/tcmd/components/Help.js +260 -0
- package/src/js/tcmd/components/Help.xml +13 -4
- package/src/js/tcmd/components/HelpRow.html +8 -0
- package/src/js/tcmd/components/HelpRow.xml +7 -0
- package/src/js/tcmd/components/OverlayList.html +8 -0
- package/src/js/tcmd/components/OverlayList.js +69 -0
- package/src/js/tcmd/components/{CommandPalette.xml → OverlayList.xml} +2 -5
- package/src/js/tcmd/components/OverlayRow.html +5 -0
- package/src/js/tcmd/components/OverlayRow.js +47 -0
- package/src/js/tcmd/components/OverlayRow.xml +9 -0
- package/src/js/tcmd/components/Summary.html +1 -1
- package/src/js/tcmd/components/Summary.js +1 -6
- package/src/js/tcmd/components/format.js +4 -23
- package/src/js/tcmd/components/icons.js +176 -5
- package/src/js/tcmd/components/index.js +9 -5
- package/src/js/tcmd/components/rows.js +176 -48
- package/src/js/tcmd/core/base64.js +64 -0
- package/src/js/tcmd/core/bookmarks.js +45 -8
- package/src/js/tcmd/core/commands.js +978 -260
- package/src/js/tcmd/core/concurrency.js +59 -0
- package/src/js/tcmd/core/decompress.js +117 -0
- package/src/js/tcmd/core/directory.js +219 -93
- package/src/js/tcmd/core/format.js +36 -0
- package/src/js/tcmd/core/fs.js +438 -54
- package/src/js/tcmd/core/history.js +58 -0
- package/src/js/tcmd/core/index.js +3 -9
- package/src/js/tcmd/core/journal.js +93 -0
- package/src/js/tcmd/core/keymap.js +42 -6
- package/src/js/tcmd/core/operations.js +813 -48
- package/src/js/tcmd/core/os.js +29 -3
- package/src/js/tcmd/core/pane.js +33 -8
- package/src/js/tcmd/core/panel.js +280 -104
- package/src/js/tcmd/core/path.js +30 -3
- package/src/js/tcmd/core/permissions.js +107 -0
- package/src/js/tcmd/core/picker.js +156 -0
- package/src/js/tcmd/core/preview.js +102 -0
- package/src/js/tcmd/core/script.js +7 -95
- package/src/js/tcmd/core/selection.js +9 -1
- package/src/js/tcmd/core/session.js +498 -200
- package/src/js/tcmd/core/watch.js +153 -0
- package/src/js/tcmd/desktop/backend/api.js +165 -0
- package/src/js/tcmd/desktop/backend/fs.js +626 -0
- package/src/js/tcmd/desktop/backend/main.ts +9 -0
- package/src/js/tcmd/desktop/bookmarks.js +23 -0
- package/src/js/tcmd/desktop/fs.js +91 -0
- package/src/js/tcmd/desktop/main.js +194 -0
- package/src/js/tcmd/desktop/os.js +33 -0
- package/src/js/tcmd/index.js +0 -1
- package/src/js/tcmd/tui/app.js +118 -60
- package/src/js/tcmd/tui/catalogue.js +238 -42
- package/src/js/tcmd/tui/index.js +18 -19
- package/src/js/tcmd/tui/opentui.js +33 -0
- package/src/js/tcmd/tui/syntax.js +91 -0
- package/src/js/tcmd/tui/theme.js +32 -2
- package/src/js/tcmd/vendor/bzip2.js +276 -0
- package/src/js/tcmd/web/app.js +225 -41
- package/src/js/tcmd/web/bookmarks.js +36 -0
- package/src/js/tcmd/web/catalogue.js +81 -38
- package/src/js/tcmd/web/effects.js +223 -0
- package/src/js/tcmd/web/header.html +1 -1
- package/src/js/tcmd/web/header.js +15 -11
- package/src/js/tcmd/web/http.js +13 -0
- package/src/js/tcmd/web/index.js +2 -2
- package/src/js/tcmd/web/main.js +6 -66
- package/src/js/tcmd/web/opfs.js +297 -30
- package/src/js/tcmd/web/seed.js +4 -4
- package/src/js/tcmd/web/server.js +124 -21
- package/src/js/tcmd/web/theme.js +4 -0
- package/tinyjs.json +16 -0
- package/src/js/tcmd/components/CommandPalette.html +0 -7
- package/src/js/tcmd/components/CommandPalette.js +0 -58
- package/src/js/tcmd/components/PaletteRow.html +0 -3
- package/src/js/tcmd/components/PaletteRow.js +0 -43
- package/src/js/tcmd/components/PaletteRow.xml +0 -4
- package/src/js/tcmd/tui/frame.js +0 -269
- package/src/js/tcmd/tui/help.js +0 -32
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<!-- Identity bar: the one visible trace of TinyCmd itself (the host
|
|
11
11
|
aside, everything else on screen is the user's files). "Tiny"
|
|
12
12
|
shimmers blue letter by letter, "Cmd" shimmers orange. -->
|
|
13
|
-
<box flexDirection="row" height="1" paddingLeft="1" overflow="hidden">
|
|
13
|
+
<box flexDirection="row" height="1" paddingLeft="1" paddingRight="1" overflow="hidden">
|
|
14
14
|
<text out="brandT" out:fg="brandTFg" wrapMode="none"></text>
|
|
15
15
|
<text out="brandI" out:fg="brandIFg" wrapMode="none"></text>
|
|
16
16
|
<text out="brandN" out:fg="brandNFg" wrapMode="none"></text>
|
|
@@ -19,6 +19,26 @@
|
|
|
19
19
|
<text out="brandM" out:fg="brandMFg" wrapMode="none"></text>
|
|
20
20
|
<text out="brandD" out:fg="brandDFg" wrapMode="none"></text>
|
|
21
21
|
<text out="topBar" out:fg="topBarFg" wrapMode="none"></text>
|
|
22
|
+
<box flexGrow="1" flexShrink="1" minWidth="0" overflow="hidden"></box>
|
|
23
|
+
<!-- The view mode, letter by letter so each carries its gradient:
|
|
24
|
+
explorer shimmers along the Tiny blues, commander along the
|
|
25
|
+
Cmd oranges (see `modeGradient` in Frame.js). The trailing
|
|
26
|
+
slots of the shorter word are empty and take no column. -->
|
|
27
|
+
<box flexDirection="row" flexShrink="0" overflow="hidden">
|
|
28
|
+
<!-- Clicking the mode word flips explorer ⇄ commander. -->
|
|
29
|
+
<box flexDirection="row" overflow="hidden" on:click="!view:toggleMode">
|
|
30
|
+
<text when="modeHas0" out="modeL0" out:fg="modeFg0" wrapMode="none"></text>
|
|
31
|
+
<text when="modeHas1" out="modeL1" out:fg="modeFg1" wrapMode="none"></text>
|
|
32
|
+
<text when="modeHas2" out="modeL2" out:fg="modeFg2" wrapMode="none"></text>
|
|
33
|
+
<text when="modeHas3" out="modeL3" out:fg="modeFg3" wrapMode="none"></text>
|
|
34
|
+
<text when="modeHas4" out="modeL4" out:fg="modeFg4" wrapMode="none"></text>
|
|
35
|
+
<text when="modeHas5" out="modeL5" out:fg="modeFg5" wrapMode="none"></text>
|
|
36
|
+
<text when="modeHas6" out="modeL6" out:fg="modeFg6" wrapMode="none"></text>
|
|
37
|
+
<text when="modeHas7" out="modeL7" out:fg="modeFg7" wrapMode="none"></text>
|
|
38
|
+
<text when="modeHas8" out="modeL8" out:fg="modeFg8" wrapMode="none"></text>
|
|
39
|
+
</box>
|
|
40
|
+
<text out="topBarStatus" out:fg="topBarStatusFg" wrapMode="none"></text>
|
|
41
|
+
</box>
|
|
22
42
|
</box>
|
|
23
43
|
|
|
24
44
|
<!-- Minimum-size gate: below the breakpoint the workspace is unusable. -->
|
|
@@ -27,72 +47,106 @@
|
|
|
27
47
|
<text out="minSizeHint" out:fg="dimFg"></text>
|
|
28
48
|
</box>
|
|
29
49
|
|
|
30
|
-
<!--
|
|
50
|
+
<!-- Columns: commander tiles source and destination; explorer leads
|
|
51
|
+
with the parent mirror so the current pane sits in the middle,
|
|
52
|
+
slightly wider than its neighbours. The inspector completes the
|
|
53
|
+
three columns in either mode. -->
|
|
31
54
|
<box when="!tooSmall" flexDirection="column" flexGrow="1" overflow="hidden">
|
|
32
|
-
<box flexDirection="row" flexGrow="1" overflow="hidden">
|
|
33
|
-
<box flexDirection="column" flexGrow="1" border borderStyle="single"
|
|
55
|
+
<box when="!showPreviewFull" flexDirection="row" flexGrow="1" overflow="hidden">
|
|
56
|
+
<box when="showParentPane" flexDirection="column" flexGrow="1" flexBasis="0" border borderStyle="single"
|
|
57
|
+
out:border="leftBorder" out:borderColor="parentBorderFg"
|
|
58
|
+
on:click="parentId!pane:activate">
|
|
59
|
+
<box flexDirection="row" height="1" paddingLeft="1" overflow="hidden">
|
|
60
|
+
<box when="!parentFilterOn" flexGrow="1" flexShrink="1" minWidth="0" overflow="hidden">
|
|
61
|
+
<breadcrumbs in:segments="parentSegments" in:paneId="parentId" height="1"></breadcrumbs>
|
|
62
|
+
</box>
|
|
63
|
+
<filterbar in:query="parentFilter" in:paneId="parentId" in:filtering="filtering" in:entries="parentEntries" in:setFilter="parentSetFilter"></filterbar>
|
|
64
|
+
</box>
|
|
65
|
+
<box height="1" out:border="headRule" out:borderColor="parentHeadRuleFg"></box>
|
|
66
|
+
<filelist in:entries="parentEntries" in:cursor="parentCursor" in:marked="parentMarked"
|
|
67
|
+
in:active="parentActive" in:paneId="parentId" in:loading="parentLoading"
|
|
68
|
+
in:viewport="listViewport"></filelist>
|
|
69
|
+
<entrydetail in:entry="parentEntry" in:marked="parentMarked" height="2"></entrydetail>
|
|
70
|
+
</box>
|
|
71
|
+
<box when="showLeftPane" flexDirection="column" flexBasis="0" out:flexGrow="leftGrow" border borderStyle="single"
|
|
34
72
|
out:border="leftBorder" out:borderColor="leftBorderFg"
|
|
35
73
|
on:click="leftId!pane:activate">
|
|
36
74
|
<box flexDirection="row" height="1" paddingLeft="1" overflow="hidden">
|
|
37
75
|
<box when="!leftFilterOn" flexGrow="1" flexShrink="1" minWidth="0" overflow="hidden">
|
|
38
76
|
<breadcrumbs in:segments="leftSegments" in:paneId="leftId" height="1"></breadcrumbs>
|
|
39
77
|
</box>
|
|
40
|
-
<filterbar in:query="leftFilter" in:paneId="leftId" in:filtering="filtering" in:entries="leftEntries"></filterbar>
|
|
78
|
+
<filterbar in:query="leftFilter" in:paneId="leftId" in:filtering="filtering" in:entries="leftEntries" in:setFilter="leftSetFilter"></filterbar>
|
|
41
79
|
</box>
|
|
42
80
|
<box height="1" out:border="headRule" out:borderColor="leftHeadRuleFg"></box>
|
|
43
81
|
<filelist in:entries="leftEntries" in:cursor="leftCursor" in:marked="leftMarked"
|
|
44
82
|
in:active="leftActive" in:paneId="leftId" in:loading="leftLoading"
|
|
45
83
|
in:viewport="listViewport"></filelist>
|
|
46
84
|
<entrydetail in:entry="leftEntry" in:marked="leftMarked" height="2"></entrydetail>
|
|
47
|
-
<summary in:entries="leftEntries" in:disk="leftDisk" height="1"></summary>
|
|
48
85
|
</box>
|
|
49
|
-
<box flexDirection="column" flexGrow="
|
|
86
|
+
<box when="showRightPane" flexDirection="column" flexBasis="0" out:flexGrow="rightGrow" border borderStyle="single"
|
|
50
87
|
out:border="rightBorder" out:borderColor="rightBorderFg"
|
|
51
88
|
on:click="rightId!pane:activate">
|
|
52
89
|
<box flexDirection="row" height="1" paddingLeft="1" overflow="hidden">
|
|
53
90
|
<box when="!rightFilterOn" flexGrow="1" flexShrink="1" minWidth="0" overflow="hidden">
|
|
54
91
|
<breadcrumbs in:segments="rightSegments" in:paneId="rightId" height="1"></breadcrumbs>
|
|
55
92
|
</box>
|
|
56
|
-
<filterbar in:query="rightFilter" in:paneId="rightId" in:filtering="filtering" in:entries="rightEntries"></filterbar>
|
|
93
|
+
<filterbar in:query="rightFilter" in:paneId="rightId" in:filtering="filtering" in:entries="rightEntries" in:setFilter="rightSetFilter"></filterbar>
|
|
57
94
|
</box>
|
|
58
95
|
<box height="1" out:border="headRule" out:borderColor="rightHeadRuleFg"></box>
|
|
59
96
|
<filelist in:entries="rightEntries" in:cursor="rightCursor" in:marked="rightMarked"
|
|
60
97
|
in:active="rightActive" in:paneId="rightId" in:loading="rightLoading"
|
|
61
98
|
in:viewport="listViewport"></filelist>
|
|
62
99
|
<entrydetail in:entry="rightEntry" in:marked="rightMarked" height="2"></entrydetail>
|
|
63
|
-
<summary in:entries="rightEntries" in:disk="rightDisk" height="1"></summary>
|
|
64
100
|
</box>
|
|
65
101
|
<filepreview when="showInspectorInline" in:preview="preview" in:show="showInspectorInline"
|
|
66
|
-
in:entry="appEntry"
|
|
102
|
+
in:entry="appEntry" in:paneId="previewId" in:scroll="previewScroll"
|
|
103
|
+
in:dirSegments="previewSegments" in:dirEntries="previewEntries"
|
|
104
|
+
in:dirCursor="previewCursor" in:dirMarked="previewMarked"
|
|
105
|
+
in:dirActive="previewActive" in:dirLoading="previewLoading"
|
|
106
|
+
flexGrow="1" flexBasis="0"></filepreview>
|
|
67
107
|
</box>
|
|
108
|
+
<!-- Maximized inspector (`⇧V`): the preview takes the whole pane
|
|
109
|
+
row, the identity and command bars staying in place. -->
|
|
110
|
+
<filepreview when="showPreviewFull" in:preview="preview" in:show="showPreviewFull"
|
|
111
|
+
in:entry="appEntry" in:paneId="previewId" in:scroll="previewScroll"
|
|
112
|
+
in:dirSegments="previewSegments" in:dirEntries="previewEntries"
|
|
113
|
+
in:dirCursor="previewCursor" in:dirMarked="previewMarked"
|
|
114
|
+
in:dirActive="previewActive" in:dirLoading="previewLoading"
|
|
115
|
+
flexGrow="1"></filepreview>
|
|
68
116
|
<commandbar in:items="commandBarItems" in:notice="notice" in:leftError="leftError"
|
|
69
|
-
in:rightError="rightError" in:active="active"
|
|
117
|
+
in:rightError="rightError" in:active="active" in:uiSize="uiSize"
|
|
70
118
|
in:leftMarked="leftMarked" in:rightMarked="rightMarked" out:height="barHeight"></commandbar>
|
|
71
119
|
</box>
|
|
72
120
|
</box>
|
|
73
121
|
|
|
74
|
-
<!-- Fullscreen inspector
|
|
122
|
+
<!-- Fullscreen inspector overlay: `v` below the inline breakpoint, or
|
|
123
|
+
Enter on a file the host cannot edit (any width). -->
|
|
75
124
|
<box when="showViewer" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="10"
|
|
76
125
|
alignItems="center" justifyContent="center">
|
|
77
126
|
<box width="80%" height="90%">
|
|
78
|
-
<filepreview in:preview="preview" in:show="showViewer" in:entry="appEntry"
|
|
127
|
+
<filepreview in:preview="preview" in:show="showViewer" in:entry="appEntry" in:paneId="previewId"
|
|
128
|
+
in:scroll="previewScroll"
|
|
129
|
+
in:dirSegments="previewSegments" in:dirEntries="previewEntries"
|
|
130
|
+
in:dirCursor="previewCursor" in:dirMarked="previewMarked"
|
|
131
|
+
in:dirActive="previewActive" in:dirLoading="previewLoading"></filepreview>
|
|
79
132
|
</box>
|
|
80
133
|
</box>
|
|
81
134
|
|
|
82
|
-
<commandpalette when="paletteOpen" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="20"
|
|
83
|
-
in:open="paletteOpen" in:mode="paletteMode" in:query="paletteQuery"
|
|
84
|
-
in:items="paletteItems" in:selected="paletteIndex"></commandpalette>
|
|
85
135
|
<commandpanel when="panelOpen" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="22"
|
|
86
|
-
in:open="panelOpen" in:
|
|
136
|
+
in:open="panelOpen" in:entry="panelEntry" in:items="panelItems"
|
|
87
137
|
in:opCursor="panelOpIndex" in:rows="panelRows" in:argCursor="panelRowIndex"
|
|
88
|
-
in:
|
|
89
|
-
in:
|
|
138
|
+
in:permBit="panelPermBit" in:focus="panelFocus"
|
|
139
|
+
in:preview="panelPreview"
|
|
140
|
+
in:picking="pickerOpen"
|
|
141
|
+
in:pickerPathText="pickerPathText" in:pickerFocus="pickerFocus" in:pickerRows="pickerRows"
|
|
90
142
|
in:query="panelQuery" in:value="panelValue"></commandpanel>
|
|
91
143
|
<bookmarklist when="bookmarkOpen" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="25"
|
|
92
|
-
in:open="bookmarkOpen" in:
|
|
93
|
-
in:
|
|
144
|
+
in:open="bookmarkOpen" in:query="bookmarkQuery"
|
|
145
|
+
in:items="bookmarkItems" in:selected="bookmarkIndex"></bookmarklist>
|
|
146
|
+
<overlaylist when="overlayOpen" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="27"
|
|
147
|
+
in:open="overlay" in:mode="overlay" in:items="overlayItems" in:cursor="overlayIndex"></overlaylist>
|
|
94
148
|
<confirm when="confirm" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="30"
|
|
95
149
|
in:confirm="confirm"></confirm>
|
|
96
150
|
<help when="helpOpen" position="absolute" top="0" left="0" width="100%" height="100%" zIndex="40"
|
|
97
|
-
in:open="helpOpen"></help>
|
|
151
|
+
in:open="helpOpen" in:size="uiSize"></help>
|
|
98
152
|
</box>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<div class="bookmark-list" when="open">
|
|
2
|
-
<div class="bookmark-dialog">
|
|
1
|
+
<div class="bookmark-list" when="open" role="dialog" aria-modal="true" aria-label="Bookmarks" on:click="!dialog:bookmark-cancel">
|
|
2
|
+
<div class="bookmark-dialog" on:click="dialogStop">
|
|
3
|
+
<h2 out="title"></h2>
|
|
3
4
|
<header>
|
|
4
5
|
<span class="bookmark-sign" out="sign"></span>
|
|
5
|
-
<input class="bookmark-query" type="text" inout="query" on:enter="confirm">
|
|
6
|
+
<input class="bookmark-query" type="text" inout="query" aria-label="Filter bookmarks" on:enter="confirm">
|
|
6
7
|
</header>
|
|
7
|
-
<p class="bookmark-target" when="inputVisible" out="target"></p>
|
|
8
8
|
<p class="bookmark-empty" when="emptyList" out="empty"></p>
|
|
9
|
-
<ul class="bookmark-rows"
|
|
9
|
+
<ul class="bookmark-rows" out="rows"></ul>
|
|
10
10
|
<footer out="footer"></footer>
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
@@ -4,65 +4,39 @@
|
|
|
4
4
|
// Created: 2026-10-09
|
|
5
5
|
|
|
6
6
|
// Module: tcmd/components/BookmarkList
|
|
7
|
-
// BookmarkList: the
|
|
8
|
-
// the
|
|
9
|
-
//
|
|
7
|
+
// BookmarkList: the single bookmarks panel opened with `b`. The input filters
|
|
8
|
+
// the stored bookmarks (matched by name or path); the first row offers to add
|
|
9
|
+
// the current path when it is not bookmarked yet. The row logic lives in
|
|
10
10
|
// `BookmarkRow.js`; this parent maps its `items` to rows.
|
|
11
11
|
//
|
|
12
12
|
// Environment: `overlayBg`, `borderPrimaryActiveFg`, `textSecondaryFg`
|
|
13
|
-
// (footer
|
|
14
|
-
//
|
|
13
|
+
// (footer), `textHeadingFg` (title), `rows(data)` returning the keyed rows and
|
|
14
|
+
// `scrollTop(self, data)` (TUI viewport tracking).
|
|
15
15
|
|
|
16
16
|
import { unwrap } from "select/state/cells"
|
|
17
17
|
|
|
18
|
-
// Function: title
|
|
19
|
-
// The overlay title: "bookmark" while naming, "bookmarks" while picking.
|
|
20
|
-
function bookmarkTitle(mode) {
|
|
21
|
-
return unwrap(mode) === "name" ? "bookmark" : "bookmarks"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Function: footer
|
|
25
|
-
function bookmarkFooter(mode) {
|
|
26
|
-
return unwrap(mode) === "name"
|
|
27
|
-
? "name the bookmark ↵ save Esc cancel"
|
|
28
|
-
: "↑↓ move ↵ jump Esc close"
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Function: targetLine
|
|
32
|
-
// The path being recorded (name mode). `target` is `{ path, isDir }` or null.
|
|
33
|
-
function targetLine(target) {
|
|
34
|
-
const value = unwrap(target)
|
|
35
|
-
if (!value) return ""
|
|
36
|
-
if (typeof value === "string") return value
|
|
37
|
-
return `${value.path ?? ""}${value.isDir === true ? "/" : ""}`
|
|
38
|
-
}
|
|
39
|
-
|
|
40
18
|
// Function: createBehaviors
|
|
41
19
|
// Builds the BookmarkList behavior map for the given renderer environment.
|
|
42
20
|
function createBehaviors(env) {
|
|
43
21
|
const behaviors = {
|
|
44
22
|
bg: () => env.overlayBg,
|
|
45
23
|
borderFg: () => env.borderPrimaryActiveFg,
|
|
46
|
-
confirm: (self
|
|
47
|
-
footer: (
|
|
24
|
+
confirm: (self) => self.pub("bookmark:confirm"),
|
|
25
|
+
footer: () => "↑↓ move ⌫/Del remove ↵ open Esc close",
|
|
48
26
|
footerFg: () => env.textSecondaryFg,
|
|
49
|
-
// The input
|
|
27
|
+
// The filter input owns typing; the list navigates with the arrows.
|
|
50
28
|
focused: (_self, data) => Boolean(unwrap(data.open)),
|
|
51
|
-
inputVisible: (_self, data) => unwrap(data.mode) === "name",
|
|
52
|
-
listVisible: (_self, data) => unwrap(data.mode) === "list",
|
|
53
29
|
open: (_self, data) => Boolean(unwrap(data.open)),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
target: (_self, data) => targetLine(data.target),
|
|
57
|
-
title: (_self, data) => bookmarkTitle(data.mode),
|
|
30
|
+
sign: () => "›",
|
|
31
|
+
title: () => "bookmarks",
|
|
58
32
|
titleColor: () => env.textHeadingFg,
|
|
59
|
-
emptyList: (_self, data) =>
|
|
60
|
-
|
|
61
|
-
|
|
33
|
+
emptyList: (_self, data) => (unwrap(data.items)?.length ?? 0) === 0,
|
|
34
|
+
empty: (_self, data) =>
|
|
35
|
+
`${unwrap(data.query) ?? ""}`.trim() ? " no matching bookmarks" : " no bookmarks",
|
|
62
36
|
emptyFg: () => env.textSecondaryFg,
|
|
63
37
|
}
|
|
64
38
|
if (env?.rows) {
|
|
65
|
-
behaviors.rows = (
|
|
39
|
+
behaviors.rows = (self, data) => env.rows(self, data)
|
|
66
40
|
}
|
|
67
41
|
if (env?.scrollTop) {
|
|
68
42
|
behaviors.scrollTop = (self, data) => env.scrollTop(self, data)
|
|
@@ -70,4 +44,4 @@ function createBehaviors(env) {
|
|
|
70
44
|
return behaviors
|
|
71
45
|
}
|
|
72
46
|
|
|
73
|
-
export {
|
|
47
|
+
export { createBehaviors }
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
<text out="sign" out:fg="titleColor"></text>
|
|
7
7
|
<input ref="query" inout="query" flexGrow="1" height="1" out:focused="focused" on:enter="confirm"></input>
|
|
8
8
|
</box>
|
|
9
|
-
<text when="inputVisible" out="target" out:fg="pathFg" paddingLeft="1" wrapMode="none" truncate="true"></text>
|
|
10
9
|
<text when="emptyList" out="empty" out:fg="emptyFg" paddingLeft="1" wrapMode="none"></text>
|
|
11
|
-
<scrollbox
|
|
10
|
+
<scrollbox ref="list" flexGrow="1">
|
|
12
11
|
<box out="rows" flexDirection="column"></box>
|
|
13
12
|
</scrollbox>
|
|
14
13
|
<box flexDirection="row" height="1" paddingLeft="1">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
<li class="bookmark-row" out:class="rowClass" on:click="item.
|
|
1
|
+
<li class="bookmark-row" out:class="rowClass" on:click="item.key!bookmark:select">
|
|
2
2
|
<span class="bookmark-marker" out="rowMarker"></span>
|
|
3
|
+
<svg class="bookmark-icon ui-icon" when="hasIcon" aria-hidden="true" focusable="false" viewBox="0 0 24 24"><use out:href="rowIconHref"></use></svg>
|
|
3
4
|
<span class="bookmark-name" out="rowName"></span>
|
|
4
5
|
<span class="bookmark-path" out="rowPath"></span>
|
|
5
6
|
</li>
|
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
// Created: 2026-10-09
|
|
5
5
|
|
|
6
6
|
// Module: tcmd/components/BookmarkRow
|
|
7
|
-
// One row of the
|
|
8
|
-
// selected }`, the same bag shape in both engines.
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
7
|
+
// One row of the bookmarks panel. Reads `{ item: { name, path, add? }, index,
|
|
8
|
+
// selected }`, the same bag shape in both engines. The synthetic add row reads
|
|
9
|
+
// as an action; stored rows read as `name/` for directories. Selection is
|
|
10
|
+
// snapshotted by the row builder into a plain `selectedRow` boolean and read
|
|
11
|
+
// through the shared `isSelected` predicate, with the `selected` cell as
|
|
12
|
+
// fallback for hand-built bags.
|
|
12
13
|
//
|
|
13
14
|
// Environment: `accentFg`, `textFg`, `textSecondaryFg`, `selectionBg` (TUI row
|
|
14
15
|
// background), `selectedClass` (web), `icons` (show Nerd Font icons).
|
|
15
16
|
|
|
16
17
|
import { isSelected } from "./rows.js"
|
|
17
|
-
import { iconFor } from "./icons.js"
|
|
18
|
+
import { iconFor, lucideIconFor } from "./icons.js"
|
|
18
19
|
|
|
19
20
|
// Function: createBehaviors
|
|
20
21
|
// Builds the BookmarkRow behavior map for the given renderer environment.
|
|
@@ -25,13 +26,17 @@ function createBehaviors(env) {
|
|
|
25
26
|
rowFg: (_self, data) => (isSelected(data) ? env.accentFg : env.textFg),
|
|
26
27
|
// The icon is its own slot, dimmer than the name; it collapses when
|
|
27
28
|
// the environment keeps rows icon-free.
|
|
28
|
-
hasIcon: () => Boolean(env.icons),
|
|
29
|
+
hasIcon: () => Boolean(env.icons || env.lucideIcons),
|
|
29
30
|
rowIcon: (_self, data) => (env.icons ? iconFor(data.item) : ""),
|
|
31
|
+
rowIconHref: (_self, data) => (env.lucideIcons ? `#lucide-${lucideIconFor(data.item)}` : ""),
|
|
30
32
|
rowIconFg: () => env.textSecondaryFg,
|
|
31
33
|
rowMarker: (_self, data) => (isSelected(data) ? ">" : " "),
|
|
32
|
-
//
|
|
34
|
+
// The add row names its action; a directory bookmark reads as
|
|
35
|
+
// `name/`, mirroring the listing.
|
|
33
36
|
rowName: (_self, data) =>
|
|
34
|
-
|
|
37
|
+
data.item?.add
|
|
38
|
+
? data.item.name ?? ""
|
|
39
|
+
: `${data.item?.name ?? ""}${data.item?.isDir === true ? "/" : ""}`,
|
|
35
40
|
rowPath: (_self, data) => `${data.item?.path ?? ""}`,
|
|
36
41
|
rowPathFg: () => env.textSecondaryFg,
|
|
37
42
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<box flexDirection="row" height="1" columnGap="1" out:backgroundColor="rowBg" on:click="item.
|
|
1
|
+
<box flexDirection="row" height="1" columnGap="1" out:backgroundColor="rowBg" on:click="item.key!bookmark:select">
|
|
2
2
|
<text out="rowMarker" width="2" out:fg="rowFg"></text>
|
|
3
3
|
<text out="rowIcon" out:fg="rowIconFg" wrapMode="none" when="hasIcon"></text>
|
|
4
4
|
<box minWidth="12" flexShrink="0">
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<li class="panel-row" out:class="rowClass" out:data-risk="row.risk" out:data-group="row.group" out:data-type="row.type" out:data-selected="rowSelected" on:click="row.key!panel:select">
|
|
2
|
+
<span class="panel-list-indent" when="isList" out="listSpacer"></span>
|
|
3
|
+
<span class="panel-list-box" when="isList">
|
|
4
|
+
<span class="panel-marker" when="isItem" out="marker"></span>
|
|
5
|
+
<span class="panel-name" when="isItem" out="name"></span>
|
|
6
|
+
<span class="panel-summary" when="isItem" out="summary"></span>
|
|
7
|
+
</span>
|
|
8
|
+
<span class="panel-name panel-group-name" when="isGroup" out="name"></span>
|
|
9
|
+
<span class="panel-marker" when="showPlain" out="marker"></span>
|
|
10
|
+
<span class="panel-name" when="showPlain" out="name"></span>
|
|
11
|
+
<span class="panel-marker" when="isArg" out="marker"></span>
|
|
12
|
+
<span class="panel-name panel-arg-name" when="isArg" out="name"></span>
|
|
13
|
+
<span class="panel-perm" when="isPerm">
|
|
14
|
+
<span class="panel-perm-class" out="permClass"></span>
|
|
15
|
+
<button class="panel-perm-bit" type="button" tabindex="-1" out:class="permRClass" out:aria-pressed="permROn" on:click="row.keyR!panel:perm." out="permR"></button>
|
|
16
|
+
<button class="panel-perm-bit" type="button" tabindex="-1" out:class="permWClass" out:aria-pressed="permWOn" on:click="row.keyW!panel:perm." out="permW"></button>
|
|
17
|
+
<button class="panel-perm-bit" type="button" tabindex="-1" out:class="permXClass" out:aria-pressed="permXOn" on:click="row.keyX!panel:perm." out="permX"></button>
|
|
18
|
+
</span>
|
|
19
|
+
<button class="panel-run-button" when="isRun" type="button" tabindex="-1" out:aria-label="runAriaLabel" out="runLabel"></button>
|
|
20
|
+
<span class="panel-field" when="isArg" out:data-editable="editable">
|
|
21
|
+
<span class="panel-field-bracket" out="fieldOpen"></span>
|
|
22
|
+
<input class="panel-value" when="editing" type="text" inout="value" aria-label="Argument value" />
|
|
23
|
+
<span class="panel-field-value" when="!editing" out="summary"></span>
|
|
24
|
+
<span class="panel-field-bracket" out="fieldClose"></span>
|
|
25
|
+
</span>
|
|
26
|
+
<span class="panel-summary" when="isPlain" out="summary"></span>
|
|
27
|
+
<svg class="panel-op-chevron ui-icon" when="isOp" aria-hidden="true" focusable="false" viewBox="0 0 24 24"><use href="#lucide-chevron-right"></use></svg>
|
|
28
|
+
</li>
|