@fgv/ts-app-shell 5.1.0-10 → 5.1.0-11

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.
@@ -30,6 +30,21 @@
30
30
  import React, { useCallback, useEffect, useRef, useState } from 'react';
31
31
  import { StarIcon as StarIconOutline } from '@heroicons/react/24/outline';
32
32
  import { StarIcon as StarIconSolid, ExclamationTriangleIcon, BuildingLibraryIcon, ShieldCheckIcon, ShieldExclamationIcon, ArrowDownTrayIcon, PencilSquareIcon, ArrowsPointingInIcon, TrashIcon, FolderPlusIcon, ArchiveBoxArrowDownIcon, FolderOpenIcon, ArrowUpTrayIcon, PlusIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
33
+ const BADGE_BASE_CLASSES = 'inline-flex shrink-0 items-center justify-center rounded-full font-medium leading-none';
34
+ const BADGE_TONE_CLASSES = {
35
+ info: 'bg-status-info-bg text-status-info-text',
36
+ warning: 'bg-status-warning-bg text-status-warning-text',
37
+ danger: 'bg-status-error-bg text-status-error-text'
38
+ };
39
+ function renderBadge(badge) {
40
+ var _a, _b;
41
+ const tone = (_a = badge.tone) !== null && _a !== void 0 ? _a : 'info';
42
+ const ariaLabel = badge.ariaLabel;
43
+ if (badge.kind === 'dot') {
44
+ return (React.createElement("span", { className: `ml-1.5 h-2 w-2 ${BADGE_BASE_CLASSES} ${BADGE_TONE_CLASSES[tone]}`, "aria-label": ariaLabel }));
45
+ }
46
+ return (React.createElement("span", { className: `ml-1.5 min-w-4 px-1.5 py-0.5 text-[0.6875rem] ${BADGE_BASE_CLASSES} ${BADGE_TONE_CLASSES[tone]}`, "aria-label": ariaLabel }, (_b = badge.count) !== null && _b !== void 0 ? _b : 0));
47
+ }
33
48
  // ============================================================================
34
49
  // Context Menu (internal)
35
50
  // ============================================================================
@@ -121,6 +136,7 @@ function CollectionRow(props) {
121
136
  }, className: "shrink-0 text-muted hover:text-star transition-colors", title: "Click to unlock", "aria-label": `Unlock ${displayName}` },
122
137
  React.createElement(ShieldExclamationIcon, { className: "w-4 h-4" })))),
123
138
  React.createElement("span", { className: "flex-1 truncate", title: displayName }, displayName),
139
+ collection.badge && renderBadge(collection.badge),
124
140
  React.createElement("span", { className: "shrink-0 text-xs text-muted" }, collection.itemCount)),
125
141
  React.createElement("div", { className: "flex items-center gap-1 mt-1 ml-[24px]" },
126
142
  collection.isMutable && onExport && (React.createElement("button", { onClick: (e) => {
@@ -7,6 +7,16 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
  import React from 'react';
10
+ /**
11
+ * Describes a single collection for rendering in the sidebar.
12
+ * @public
13
+ */
14
+ export interface ICollectionBadge {
15
+ readonly kind: 'dot' | 'count';
16
+ readonly tone?: 'info' | 'warning' | 'danger';
17
+ readonly count?: number;
18
+ readonly ariaLabel?: string;
19
+ }
10
20
  /**
11
21
  * Describes a single collection for rendering in the sidebar.
12
22
  * @public
@@ -37,6 +47,8 @@ export interface ICollectionRowItem {
37
47
  readonly isHidden?: boolean;
38
48
  /** The name of the storage source this collection was loaded from */
39
49
  readonly sourceName?: string;
50
+ /** Optional badge rendered alongside the collection name */
51
+ readonly badge?: ICollectionBadge;
40
52
  }
41
53
  /**
42
54
  * Props for the CollectionSection component.
@@ -66,6 +66,21 @@ exports.CollectionSection = CollectionSection;
66
66
  const react_1 = __importStar(require("react"));
67
67
  const outline_1 = require("@heroicons/react/24/outline");
68
68
  const solid_1 = require("@heroicons/react/20/solid");
69
+ const BADGE_BASE_CLASSES = 'inline-flex shrink-0 items-center justify-center rounded-full font-medium leading-none';
70
+ const BADGE_TONE_CLASSES = {
71
+ info: 'bg-status-info-bg text-status-info-text',
72
+ warning: 'bg-status-warning-bg text-status-warning-text',
73
+ danger: 'bg-status-error-bg text-status-error-text'
74
+ };
75
+ function renderBadge(badge) {
76
+ var _a, _b;
77
+ const tone = (_a = badge.tone) !== null && _a !== void 0 ? _a : 'info';
78
+ const ariaLabel = badge.ariaLabel;
79
+ if (badge.kind === 'dot') {
80
+ return (react_1.default.createElement("span", { className: `ml-1.5 h-2 w-2 ${BADGE_BASE_CLASSES} ${BADGE_TONE_CLASSES[tone]}`, "aria-label": ariaLabel }));
81
+ }
82
+ return (react_1.default.createElement("span", { className: `ml-1.5 min-w-4 px-1.5 py-0.5 text-[0.6875rem] ${BADGE_BASE_CLASSES} ${BADGE_TONE_CLASSES[tone]}`, "aria-label": ariaLabel }, (_b = badge.count) !== null && _b !== void 0 ? _b : 0));
83
+ }
69
84
  // ============================================================================
70
85
  // Context Menu (internal)
71
86
  // ============================================================================
@@ -157,6 +172,7 @@ function CollectionRow(props) {
157
172
  }, className: "shrink-0 text-muted hover:text-star transition-colors", title: "Click to unlock", "aria-label": `Unlock ${displayName}` },
158
173
  react_1.default.createElement(solid_1.ShieldExclamationIcon, { className: "w-4 h-4" })))),
159
174
  react_1.default.createElement("span", { className: "flex-1 truncate", title: displayName }, displayName),
175
+ collection.badge && renderBadge(collection.badge),
160
176
  react_1.default.createElement("span", { className: "shrink-0 text-xs text-muted" }, collection.itemCount)),
161
177
  react_1.default.createElement("div", { className: "flex items-center gap-1 mt-1 ml-[24px]" },
162
178
  collection.isMutable && onExport && (react_1.default.createElement("button", { onClick: (e) => {
@@ -8,5 +8,5 @@ export { FilterRow, type IFilterRowProps, type IFilterOption } from './FilterRow
8
8
  export { FilterBar, type IFilterBarProps } from './FilterBar';
9
9
  export { EntityList, type IEntityListProps, type IEntityDescriptor, type IEntityStatus, type IEmptyStateConfig, type IEmptyStateAction } from './EntityList';
10
10
  export { GroupedEntityList, type IGroupedEntityListProps, type IEntityGroupDescriptor } from './GroupedEntityList';
11
- export { CollectionSection, type ICollectionSectionProps, type ICollectionRowItem, type SourceColorMap } from './CollectionSection';
11
+ export { CollectionSection, type ICollectionBadge, type ICollectionSectionProps, type ICollectionRowItem, type SourceColorMap } from './CollectionSection';
12
12
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fgv/ts-app-shell",
3
- "version": "5.1.0-10",
3
+ "version": "5.1.0-11",
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-10",
21
- "@fgv/ts-extras": "5.1.0-10"
20
+ "@fgv/ts-utils": "5.1.0-11",
21
+ "@fgv/ts-extras": "5.1.0-11"
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/heft-dual-rig": "5.1.0-10",
55
- "@fgv/ts-utils-jest": "5.1.0-10"
54
+ "@fgv/heft-dual-rig": "5.1.0-11",
55
+ "@fgv/ts-utils-jest": "5.1.0-11"
56
56
  },
57
57
  "exports": {
58
58
  ".": {