@fgv/ts-app-shell 5.1.0-12 → 5.1.0-14
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.
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
31
31
|
import { StarIcon as StarIconOutline } from '@heroicons/react/24/outline';
|
|
32
|
-
import { StarIcon as StarIconSolid, ExclamationTriangleIcon, BuildingLibraryIcon, ShieldCheckIcon, ShieldExclamationIcon, ArrowDownTrayIcon, PencilSquareIcon, ArrowsPointingInIcon, TrashIcon, FolderPlusIcon, ArchiveBoxArrowDownIcon, FolderOpenIcon, ArrowUpTrayIcon, PlusIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
|
|
32
|
+
import { StarIcon as StarIconSolid, ExclamationTriangleIcon, BuildingLibraryIcon, BuildingStorefrontIcon, ShieldCheckIcon, ShieldExclamationIcon, ArrowDownTrayIcon, PencilSquareIcon, ArrowsPointingInIcon, TrashIcon, FolderPlusIcon, ArchiveBoxArrowDownIcon, FolderOpenIcon, ArrowUpTrayIcon, PlusIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
|
|
33
33
|
import { renderStatusBadge } from '../badge';
|
|
34
34
|
// ============================================================================
|
|
35
35
|
// Context Menu (internal)
|
|
@@ -82,7 +82,7 @@ function useLongPress(onLongPress) {
|
|
|
82
82
|
// CollectionRow (internal)
|
|
83
83
|
// ============================================================================
|
|
84
84
|
function CollectionRow(props) {
|
|
85
|
-
var _a;
|
|
85
|
+
var _a, _b, _c;
|
|
86
86
|
const { collection, onToggleVisibility, onSetDefault, onDelete, onExport, onUnlock, onRename, onMerge, borderColorClass, onContextMenu, isHiddenRow } = props;
|
|
87
87
|
const displayName = (_a = collection.name) !== null && _a !== void 0 ? _a : collection.id;
|
|
88
88
|
const handleContextMenu = useCallback((e) => {
|
|
@@ -113,8 +113,7 @@ function CollectionRow(props) {
|
|
|
113
113
|
: 'Set as default collection for new items', "aria-label": collection.isDefault ? `${displayName} is default` : `Set ${displayName} as default`, "aria-pressed": collection.isDefault }, collection.isDefault ? (React.createElement(StarIconSolid, { className: "w-4 h-4" })) : (React.createElement(StarIconOutline, { className: "w-4 h-4" })))),
|
|
114
114
|
collection.hasConflict && (React.createElement("span", { className: "shrink-0 text-status-warning-strong cursor-default", title: "An encrypted copy of this collection from another storage root has the same ID. Go to Settings \u2192 Storage to resolve the conflict.", "aria-label": `Conflict: encrypted shadow for ${displayName}` },
|
|
115
115
|
React.createElement(ExclamationTriangleIcon, { className: "w-4 h-4" }))),
|
|
116
|
-
!collection.isMutable && (React.createElement("span", { className: "shrink-0 text-muted", title:
|
|
117
|
-
React.createElement(BuildingLibraryIcon, { className: "w-4 h-4" }))),
|
|
116
|
+
!collection.isMutable && (React.createElement("span", { className: "shrink-0 text-muted", title: (_b = collection.readOnlyLabel) !== null && _b !== void 0 ? _b : 'Built-in collection (read-only)' }, collection.isDeletable ? (React.createElement(BuildingStorefrontIcon, { className: "w-4 h-4" })) : (React.createElement(BuildingLibraryIcon, { className: "w-4 h-4" })))),
|
|
118
117
|
collection.isProtected &&
|
|
119
118
|
(collection.isUnlocked || !onUnlock ? (React.createElement("span", { className: `shrink-0 ${collection.isUnlocked ? 'text-status-success-icon' : 'text-muted'}`, title: collection.isUnlocked ? 'Protected (unlocked)' : 'Protected (locked)' }, collection.isUnlocked ? (React.createElement(ShieldCheckIcon, { className: "w-4 h-4" })) : (React.createElement(ShieldExclamationIcon, { className: "w-4 h-4" })))) : (React.createElement("button", { onClick: (e) => {
|
|
120
119
|
e.stopPropagation();
|
|
@@ -140,12 +139,12 @@ function CollectionRow(props) {
|
|
|
140
139
|
onMerge(collection.id);
|
|
141
140
|
}, className: "shrink-0 w-5 h-5 flex items-center justify-center text-faint hover:text-brand-accent transition-colors", title: `Merge ${displayName} into another collection`, "aria-label": `Merge ${displayName}` },
|
|
142
141
|
React.createElement(ArrowsPointingInIcon, { className: "w-4 h-4" }))),
|
|
143
|
-
collection.isMutable && onDelete && (React.createElement("button", { onClick: (e) => {
|
|
142
|
+
(collection.isMutable || collection.isDeletable) && onDelete && (React.createElement("button", { onClick: (e) => {
|
|
144
143
|
e.stopPropagation();
|
|
145
144
|
onDelete(collection.id);
|
|
146
145
|
}, className: "shrink-0 w-5 h-5 flex items-center justify-center text-faint hover:text-status-error-icon transition-colors", title: `Remove ${displayName}`, "aria-label": `Remove ${displayName}` },
|
|
147
146
|
React.createElement(TrashIcon, { className: "w-4 h-4" }))),
|
|
148
|
-
!collection.isMutable && React.createElement("span", { className: "text-xs text-muted" },
|
|
147
|
+
!collection.isMutable && (React.createElement("span", { className: "text-xs text-muted" }, (_c = collection.readOnlyLabel) !== null && _c !== void 0 ? _c : '(built-in)')))));
|
|
149
148
|
}
|
|
150
149
|
// ============================================================================
|
|
151
150
|
// CollectionSection
|
|
@@ -49,6 +49,17 @@ export interface ICollectionRowItem {
|
|
|
49
49
|
readonly sourceName?: string;
|
|
50
50
|
/** Optional badge rendered alongside the collection name */
|
|
51
51
|
readonly badge?: ICollectionBadge;
|
|
52
|
+
/**
|
|
53
|
+
* Label shown for immutable collections. Defaults to `"(built-in)"` when
|
|
54
|
+
* omitted. Set to e.g. `"(trading post)"` for imported read-only content.
|
|
55
|
+
*/
|
|
56
|
+
readonly readOnlyLabel?: string;
|
|
57
|
+
/**
|
|
58
|
+
* When true, the collection can be deleted even though it is not mutable.
|
|
59
|
+
* Use for user-imported read-only content (e.g., Trading Post collections)
|
|
60
|
+
* that the user should be able to remove but not edit.
|
|
61
|
+
*/
|
|
62
|
+
readonly isDeletable?: boolean;
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
65
|
* Props for the CollectionSection component.
|
|
@@ -118,7 +118,7 @@ function useLongPress(onLongPress) {
|
|
|
118
118
|
// CollectionRow (internal)
|
|
119
119
|
// ============================================================================
|
|
120
120
|
function CollectionRow(props) {
|
|
121
|
-
var _a;
|
|
121
|
+
var _a, _b, _c;
|
|
122
122
|
const { collection, onToggleVisibility, onSetDefault, onDelete, onExport, onUnlock, onRename, onMerge, borderColorClass, onContextMenu, isHiddenRow } = props;
|
|
123
123
|
const displayName = (_a = collection.name) !== null && _a !== void 0 ? _a : collection.id;
|
|
124
124
|
const handleContextMenu = (0, react_1.useCallback)((e) => {
|
|
@@ -149,8 +149,7 @@ function CollectionRow(props) {
|
|
|
149
149
|
: 'Set as default collection for new items', "aria-label": collection.isDefault ? `${displayName} is default` : `Set ${displayName} as default`, "aria-pressed": collection.isDefault }, collection.isDefault ? (react_1.default.createElement(solid_1.StarIcon, { className: "w-4 h-4" })) : (react_1.default.createElement(outline_1.StarIcon, { className: "w-4 h-4" })))),
|
|
150
150
|
collection.hasConflict && (react_1.default.createElement("span", { className: "shrink-0 text-status-warning-strong cursor-default", title: "An encrypted copy of this collection from another storage root has the same ID. Go to Settings \u2192 Storage to resolve the conflict.", "aria-label": `Conflict: encrypted shadow for ${displayName}` },
|
|
151
151
|
react_1.default.createElement(solid_1.ExclamationTriangleIcon, { className: "w-4 h-4" }))),
|
|
152
|
-
!collection.isMutable && (react_1.default.createElement("span", { className: "shrink-0 text-muted", title:
|
|
153
|
-
react_1.default.createElement(solid_1.BuildingLibraryIcon, { className: "w-4 h-4" }))),
|
|
152
|
+
!collection.isMutable && (react_1.default.createElement("span", { className: "shrink-0 text-muted", title: (_b = collection.readOnlyLabel) !== null && _b !== void 0 ? _b : 'Built-in collection (read-only)' }, collection.isDeletable ? (react_1.default.createElement(solid_1.BuildingStorefrontIcon, { className: "w-4 h-4" })) : (react_1.default.createElement(solid_1.BuildingLibraryIcon, { className: "w-4 h-4" })))),
|
|
154
153
|
collection.isProtected &&
|
|
155
154
|
(collection.isUnlocked || !onUnlock ? (react_1.default.createElement("span", { className: `shrink-0 ${collection.isUnlocked ? 'text-status-success-icon' : 'text-muted'}`, title: collection.isUnlocked ? 'Protected (unlocked)' : 'Protected (locked)' }, collection.isUnlocked ? (react_1.default.createElement(solid_1.ShieldCheckIcon, { className: "w-4 h-4" })) : (react_1.default.createElement(solid_1.ShieldExclamationIcon, { className: "w-4 h-4" })))) : (react_1.default.createElement("button", { onClick: (e) => {
|
|
156
155
|
e.stopPropagation();
|
|
@@ -176,12 +175,12 @@ function CollectionRow(props) {
|
|
|
176
175
|
onMerge(collection.id);
|
|
177
176
|
}, className: "shrink-0 w-5 h-5 flex items-center justify-center text-faint hover:text-brand-accent transition-colors", title: `Merge ${displayName} into another collection`, "aria-label": `Merge ${displayName}` },
|
|
178
177
|
react_1.default.createElement(solid_1.ArrowsPointingInIcon, { className: "w-4 h-4" }))),
|
|
179
|
-
collection.isMutable && onDelete && (react_1.default.createElement("button", { onClick: (e) => {
|
|
178
|
+
(collection.isMutable || collection.isDeletable) && onDelete && (react_1.default.createElement("button", { onClick: (e) => {
|
|
180
179
|
e.stopPropagation();
|
|
181
180
|
onDelete(collection.id);
|
|
182
181
|
}, className: "shrink-0 w-5 h-5 flex items-center justify-center text-faint hover:text-status-error-icon transition-colors", title: `Remove ${displayName}`, "aria-label": `Remove ${displayName}` },
|
|
183
182
|
react_1.default.createElement(solid_1.TrashIcon, { className: "w-4 h-4" }))),
|
|
184
|
-
!collection.isMutable && react_1.default.createElement("span", { className: "text-xs text-muted" },
|
|
183
|
+
!collection.isMutable && (react_1.default.createElement("span", { className: "text-xs text-muted" }, (_c = collection.readOnlyLabel) !== null && _c !== void 0 ? _c : '(built-in)')))));
|
|
185
184
|
}
|
|
186
185
|
// ============================================================================
|
|
187
186
|
// CollectionSection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-app-shell",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-14",
|
|
4
4
|
"description": "Shared React UI primitives for application shells: column cascade, sidebar, toast/log messages, command palette, keybinding registry",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@heroicons/react": "~2.2.0",
|
|
19
19
|
"tslib": "^2.8.1",
|
|
20
|
-
"@fgv/ts-utils": "5.1.0-
|
|
21
|
-
"@fgv/ts-extras": "5.1.0-
|
|
20
|
+
"@fgv/ts-utils": "5.1.0-14",
|
|
21
|
+
"@fgv/ts-extras": "5.1.0-14"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"react": ">=18.0.0",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"@rushstack/heft-jest-plugin": "1.2.6",
|
|
52
52
|
"@testing-library/dom": "^10.4.0",
|
|
53
53
|
"@rushstack/heft-node-rig": "2.11.27",
|
|
54
|
-
"@fgv/
|
|
55
|
-
"@fgv/
|
|
54
|
+
"@fgv/heft-dual-rig": "5.1.0-14",
|
|
55
|
+
"@fgv/ts-utils-jest": "5.1.0-14"
|
|
56
56
|
},
|
|
57
57
|
"exports": {
|
|
58
58
|
".": {
|