@fgv/ts-app-shell 5.1.0-1
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 +26 -0
- package/dist/index.browser.js +3 -0
- package/dist/index.js +43 -0
- package/dist/packlets/ai-assist/index.js +6 -0
- package/dist/packlets/ai-assist/useAiAssist.js +219 -0
- package/dist/packlets/cascade/CascadeContainer.js +83 -0
- package/dist/packlets/cascade/ComparisonView.js +48 -0
- package/dist/packlets/cascade/EntityTabLayout.js +104 -0
- package/dist/packlets/cascade/MobileCascadeStack.js +63 -0
- package/dist/packlets/cascade/index.js +37 -0
- package/dist/packlets/cascade/model.js +30 -0
- package/dist/packlets/cascade/useCascadeOps.js +206 -0
- package/dist/packlets/cascade/useCascadeTransitions.js +58 -0
- package/dist/packlets/detail/DetailHelpers.js +103 -0
- package/dist/packlets/detail/index.js +6 -0
- package/dist/packlets/drop-zone/JsonDropZone.js +112 -0
- package/dist/packlets/drop-zone/index.js +6 -0
- package/dist/packlets/editing/EditFieldHelpers.js +130 -0
- package/dist/packlets/editing/MultiActionButton.js +73 -0
- package/dist/packlets/editing/NumericInput.js +119 -0
- package/dist/packlets/editing/TypeaheadInput.js +207 -0
- package/dist/packlets/editing/index.js +10 -0
- package/dist/packlets/editing/useTypeaheadMatch.js +102 -0
- package/dist/packlets/keyboard/index.js +7 -0
- package/dist/packlets/keyboard/registry.js +133 -0
- package/dist/packlets/keyboard/useKeyboardShortcuts.js +117 -0
- package/dist/packlets/messages/MessagesContext.js +76 -0
- package/dist/packlets/messages/MessagesLogger.js +103 -0
- package/dist/packlets/messages/StatusBar.js +154 -0
- package/dist/packlets/messages/Toast.js +68 -0
- package/dist/packlets/messages/index.js +11 -0
- package/dist/packlets/messages/model.js +56 -0
- package/dist/packlets/messages/useLogReporter.js +66 -0
- package/dist/packlets/modal/ConfirmDialog.js +78 -0
- package/dist/packlets/modal/Modal.js +55 -0
- package/dist/packlets/modal/index.js +7 -0
- package/dist/packlets/print/PrintEnclosure.js +60 -0
- package/dist/packlets/print/index.js +7 -0
- package/dist/packlets/print/openPrintWindow.js +112 -0
- package/dist/packlets/responsive/ResponsiveProvider.js +56 -0
- package/dist/packlets/responsive/index.js +7 -0
- package/dist/packlets/responsive/useResponsiveLayout.js +118 -0
- package/dist/packlets/selectors/EntityRow.js +276 -0
- package/dist/packlets/selectors/PreferredSelector.js +251 -0
- package/dist/packlets/selectors/index.js +24 -0
- package/dist/packlets/sidebar/CollectionSection.js +107 -0
- package/dist/packlets/sidebar/EntityList.js +164 -0
- package/dist/packlets/sidebar/FilterBar.js +42 -0
- package/dist/packlets/sidebar/FilterRow.js +182 -0
- package/dist/packlets/sidebar/GroupedEntityList.js +183 -0
- package/dist/packlets/sidebar/SearchBar.js +34 -0
- package/dist/packlets/sidebar/SidebarLayout.js +62 -0
- package/dist/packlets/sidebar/index.js +12 -0
- package/dist/packlets/theme/ThemeProvider.js +141 -0
- package/dist/packlets/theme/index.js +6 -0
- package/dist/packlets/top-bar/ModeSelector.js +46 -0
- package/dist/packlets/top-bar/TabBar.js +37 -0
- package/dist/packlets/top-bar/index.js +7 -0
- package/dist/packlets/url-sync/index.js +6 -0
- package/dist/packlets/url-sync/useUrlSync.js +157 -0
- package/eslint.config.js +22 -0
- package/lib/index.browser.d.ts +2 -0
- package/lib/index.browser.js +19 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.js +59 -0
- package/lib/packlets/ai-assist/index.d.ts +6 -0
- package/lib/packlets/ai-assist/index.js +11 -0
- package/lib/packlets/ai-assist/useAiAssist.d.ts +77 -0
- package/lib/packlets/ai-assist/useAiAssist.js +223 -0
- package/lib/packlets/cascade/CascadeContainer.d.ts +44 -0
- package/lib/packlets/cascade/CascadeContainer.js +119 -0
- package/lib/packlets/cascade/ComparisonView.d.ts +35 -0
- package/lib/packlets/cascade/ComparisonView.js +54 -0
- package/lib/packlets/cascade/EntityTabLayout.d.ts +47 -0
- package/lib/packlets/cascade/EntityTabLayout.js +110 -0
- package/lib/packlets/cascade/MobileCascadeStack.d.ts +20 -0
- package/lib/packlets/cascade/MobileCascadeStack.js +99 -0
- package/lib/packlets/cascade/index.d.ts +12 -0
- package/lib/packlets/cascade/index.js +48 -0
- package/lib/packlets/cascade/model.d.ts +57 -0
- package/lib/packlets/cascade/model.js +33 -0
- package/lib/packlets/cascade/useCascadeOps.d.ts +111 -0
- package/lib/packlets/cascade/useCascadeOps.js +209 -0
- package/lib/packlets/cascade/useCascadeTransitions.d.ts +19 -0
- package/lib/packlets/cascade/useCascadeTransitions.js +62 -0
- package/lib/packlets/detail/DetailHelpers.d.ts +83 -0
- package/lib/packlets/detail/DetailHelpers.js +113 -0
- package/lib/packlets/detail/index.d.ts +6 -0
- package/lib/packlets/detail/index.js +14 -0
- package/lib/packlets/drop-zone/JsonDropZone.d.ts +40 -0
- package/lib/packlets/drop-zone/JsonDropZone.js +149 -0
- package/lib/packlets/drop-zone/index.d.ts +6 -0
- package/lib/packlets/drop-zone/index.js +10 -0
- package/lib/packlets/editing/EditFieldHelpers.d.ts +171 -0
- package/lib/packlets/editing/EditFieldHelpers.js +144 -0
- package/lib/packlets/editing/MultiActionButton.d.ts +45 -0
- package/lib/packlets/editing/MultiActionButton.js +109 -0
- package/lib/packlets/editing/NumericInput.d.ts +47 -0
- package/lib/packlets/editing/NumericInput.js +155 -0
- package/lib/packlets/editing/TypeaheadInput.d.ts +46 -0
- package/lib/packlets/editing/TypeaheadInput.js +243 -0
- package/lib/packlets/editing/index.d.ts +10 -0
- package/lib/packlets/editing/index.js +26 -0
- package/lib/packlets/editing/useTypeaheadMatch.d.ts +42 -0
- package/lib/packlets/editing/useTypeaheadMatch.js +105 -0
- package/lib/packlets/keyboard/index.d.ts +7 -0
- package/lib/packlets/keyboard/index.js +15 -0
- package/lib/packlets/keyboard/registry.d.ts +92 -0
- package/lib/packlets/keyboard/registry.js +138 -0
- package/lib/packlets/keyboard/useKeyboardShortcuts.d.ts +50 -0
- package/lib/packlets/keyboard/useKeyboardShortcuts.js +155 -0
- package/lib/packlets/messages/MessagesContext.d.ts +40 -0
- package/lib/packlets/messages/MessagesContext.js +113 -0
- package/lib/packlets/messages/MessagesLogger.d.ts +50 -0
- package/lib/packlets/messages/MessagesLogger.js +107 -0
- package/lib/packlets/messages/StatusBar.d.ts +22 -0
- package/lib/packlets/messages/StatusBar.js +190 -0
- package/lib/packlets/messages/Toast.d.ts +31 -0
- package/lib/packlets/messages/Toast.js +105 -0
- package/lib/packlets/messages/index.d.ts +11 -0
- package/lib/packlets/messages/index.js +24 -0
- package/lib/packlets/messages/model.d.ts +59 -0
- package/lib/packlets/messages/model.js +61 -0
- package/lib/packlets/messages/useLogReporter.d.ts +22 -0
- package/lib/packlets/messages/useLogReporter.js +69 -0
- package/lib/packlets/modal/ConfirmDialog.d.ts +39 -0
- package/lib/packlets/modal/ConfirmDialog.js +114 -0
- package/lib/packlets/modal/Modal.d.ts +22 -0
- package/lib/packlets/modal/Modal.js +91 -0
- package/lib/packlets/modal/index.d.ts +7 -0
- package/lib/packlets/modal/index.js +12 -0
- package/lib/packlets/print/PrintEnclosure.d.ts +33 -0
- package/lib/packlets/print/PrintEnclosure.js +96 -0
- package/lib/packlets/print/index.d.ts +7 -0
- package/lib/packlets/print/index.js +12 -0
- package/lib/packlets/print/openPrintWindow.d.ts +35 -0
- package/lib/packlets/print/openPrintWindow.js +118 -0
- package/lib/packlets/responsive/ResponsiveProvider.d.ts +35 -0
- package/lib/packlets/responsive/ResponsiveProvider.js +93 -0
- package/lib/packlets/responsive/index.d.ts +7 -0
- package/lib/packlets/responsive/index.js +13 -0
- package/lib/packlets/responsive/useResponsiveLayout.d.ts +48 -0
- package/lib/packlets/responsive/useResponsiveLayout.js +121 -0
- package/lib/packlets/selectors/EntityRow.d.ts +45 -0
- package/lib/packlets/selectors/EntityRow.js +315 -0
- package/lib/packlets/selectors/PreferredSelector.d.ts +50 -0
- package/lib/packlets/selectors/PreferredSelector.js +287 -0
- package/lib/packlets/selectors/index.d.ts +5 -0
- package/lib/packlets/selectors/index.js +29 -0
- package/lib/packlets/sidebar/CollectionSection.d.ts +82 -0
- package/lib/packlets/sidebar/CollectionSection.js +143 -0
- package/lib/packlets/sidebar/EntityList.d.ts +105 -0
- package/lib/packlets/sidebar/EntityList.js +200 -0
- package/lib/packlets/sidebar/FilterBar.d.ts +26 -0
- package/lib/packlets/sidebar/FilterBar.js +48 -0
- package/lib/packlets/sidebar/FilterRow.d.ts +42 -0
- package/lib/packlets/sidebar/FilterRow.js +218 -0
- package/lib/packlets/sidebar/GroupedEntityList.d.ts +59 -0
- package/lib/packlets/sidebar/GroupedEntityList.js +219 -0
- package/lib/packlets/sidebar/SearchBar.d.ts +19 -0
- package/lib/packlets/sidebar/SearchBar.js +40 -0
- package/lib/packlets/sidebar/SidebarLayout.d.ts +28 -0
- package/lib/packlets/sidebar/SidebarLayout.js +98 -0
- package/lib/packlets/sidebar/index.d.ts +12 -0
- package/lib/packlets/sidebar/index.js +22 -0
- package/lib/packlets/theme/ThemeProvider.d.ts +68 -0
- package/lib/packlets/theme/ThemeProvider.js +178 -0
- package/lib/packlets/theme/index.d.ts +6 -0
- package/lib/packlets/theme/index.js +11 -0
- package/lib/packlets/top-bar/ModeSelector.d.ts +38 -0
- package/lib/packlets/top-bar/ModeSelector.js +52 -0
- package/lib/packlets/top-bar/TabBar.d.ts +31 -0
- package/lib/packlets/top-bar/TabBar.js +43 -0
- package/lib/packlets/top-bar/index.d.ts +7 -0
- package/lib/packlets/top-bar/index.js +12 -0
- package/lib/packlets/url-sync/index.d.ts +6 -0
- package/lib/packlets/url-sync/index.js +12 -0
- package/lib/packlets/url-sync/useUrlSync.d.ts +75 -0
- package/lib/packlets/url-sync/useUrlSync.js +162 -0
- package/package.json +82 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
+
var ownKeys = function(o) {
|
|
41
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
+
var ar = [];
|
|
43
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
+
__setModuleDefault(result, mod);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
+
exports.CascadeContainer = CascadeContainer;
|
|
58
|
+
/**
|
|
59
|
+
* Column cascade container — horizontal scroll of detail columns.
|
|
60
|
+
* @packageDocumentation
|
|
61
|
+
*/
|
|
62
|
+
const react_1 = __importStar(require("react"));
|
|
63
|
+
const responsive_1 = require("../responsive");
|
|
64
|
+
const MobileCascadeStack_1 = require("./MobileCascadeStack");
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// CascadeContainer Component
|
|
67
|
+
// ============================================================================
|
|
68
|
+
/**
|
|
69
|
+
* Horizontal scroll container for the column cascade.
|
|
70
|
+
*
|
|
71
|
+
* Renders a breadcrumb trail at the top and horizontally-scrollable
|
|
72
|
+
* detail columns below. Auto-scrolls to the rightmost column when
|
|
73
|
+
* a new column is pushed.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
function CascadeContainer(props) {
|
|
78
|
+
const { columns, onPopTo, minColumnWidth = '400px', onFocus, rootLabel = 'List' } = props;
|
|
79
|
+
const { layoutMode } = (0, responsive_1.useResponsive)();
|
|
80
|
+
const scrollRef = (0, react_1.useRef)(null);
|
|
81
|
+
const handleMouseDown = (0, react_1.useCallback)(() => {
|
|
82
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
83
|
+
}, [onFocus]);
|
|
84
|
+
const handleKeyDown = (0, react_1.useCallback)((e) => {
|
|
85
|
+
if (e.key === 'Escape' || e.key === 'ArrowLeft') {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
e.stopPropagation();
|
|
88
|
+
if (columns.length > 1) {
|
|
89
|
+
onPopTo(columns.length - 1);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
onPopTo(0);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}, [columns.length, onPopTo]);
|
|
96
|
+
// Auto-scroll to rightmost column when columns change
|
|
97
|
+
(0, react_1.useEffect)(() => {
|
|
98
|
+
if (scrollRef.current) {
|
|
99
|
+
scrollRef.current.scrollTo({
|
|
100
|
+
left: scrollRef.current.scrollWidth,
|
|
101
|
+
behavior: 'smooth'
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}, [columns.length]);
|
|
105
|
+
if (layoutMode === 'mobile') {
|
|
106
|
+
return react_1.default.createElement(MobileCascadeStack_1.MobileCascadeStack, Object.assign({}, props));
|
|
107
|
+
}
|
|
108
|
+
if (columns.length === 0) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden outline-none", tabIndex: -1, onKeyDown: handleKeyDown },
|
|
112
|
+
react_1.default.createElement("div", { className: "flex items-center gap-1 px-3 py-1.5 bg-surface-alt border-b border-border text-xs shrink-0 overflow-x-auto" },
|
|
113
|
+
react_1.default.createElement("button", { onClick: () => onPopTo(0), className: "text-brand-accent hover:text-brand-primary hover:underline shrink-0" }, rootLabel),
|
|
114
|
+
columns.map((col, idx) => (react_1.default.createElement(react_1.default.Fragment, { key: col.key },
|
|
115
|
+
react_1.default.createElement("span", { className: "text-muted shrink-0" }, "/"),
|
|
116
|
+
idx < columns.length - 1 ? (react_1.default.createElement("button", { onClick: () => onPopTo(idx + 1), className: "text-brand-accent hover:text-brand-primary hover:underline truncate max-w-[200px] shrink-0" }, col.label)) : (react_1.default.createElement("span", { className: "text-secondary font-medium truncate max-w-[200px] shrink-0" }, col.label)))))),
|
|
117
|
+
react_1.default.createElement("div", { ref: scrollRef, className: "flex flex-1 overflow-x-auto overflow-y-hidden", onMouseDown: handleMouseDown }, columns.map((col) => (react_1.default.createElement("div", { key: col.key, className: "flex flex-col shrink-0 border-r border-border overflow-y-auto", style: { minWidth: minColumnWidth, width: minColumnWidth } }, col.content))))));
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=CascadeContainer.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ComparisonView — side-by-side read-only comparison of 2–4 entities.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* A single column in the comparison view.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export interface IComparisonColumn {
|
|
11
|
+
/** Unique key for React reconciliation */
|
|
12
|
+
readonly key: string;
|
|
13
|
+
/** Column header label */
|
|
14
|
+
readonly label: string;
|
|
15
|
+
/** Column content (typically a detail component) */
|
|
16
|
+
readonly content: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Props for the ComparisonView component.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export interface IComparisonViewProps {
|
|
23
|
+
/** Columns to compare (2–4) */
|
|
24
|
+
readonly columns: ReadonlyArray<IComparisonColumn>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Side-by-side comparison view for entities.
|
|
28
|
+
*
|
|
29
|
+
* Renders 2–4 entity detail views in equal-width columns with
|
|
30
|
+
* synchronized scrolling (future) and column headers.
|
|
31
|
+
*
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export declare function ComparisonView(props: IComparisonViewProps): React.ReactElement;
|
|
35
|
+
//# sourceMappingURL=ComparisonView.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
24
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.ComparisonView = ComparisonView;
|
|
28
|
+
/**
|
|
29
|
+
* ComparisonView — side-by-side read-only comparison of 2–4 entities.
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
const react_1 = __importDefault(require("react"));
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// ComparisonView Component
|
|
35
|
+
// ============================================================================
|
|
36
|
+
/**
|
|
37
|
+
* Side-by-side comparison view for entities.
|
|
38
|
+
*
|
|
39
|
+
* Renders 2–4 entity detail views in equal-width columns with
|
|
40
|
+
* synchronized scrolling (future) and column headers.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
function ComparisonView(props) {
|
|
45
|
+
const { columns } = props;
|
|
46
|
+
if (columns.length < 2) {
|
|
47
|
+
return (react_1.default.createElement("div", { className: "flex flex-1 items-center justify-center text-muted text-sm" }, "Select at least 2 items to compare."));
|
|
48
|
+
}
|
|
49
|
+
return (react_1.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, columns.map((col) => (react_1.default.createElement("div", { key: col.key, className: "flex flex-col flex-1 min-w-0 border-r border-border last:border-r-0 overflow-hidden" },
|
|
50
|
+
react_1.default.createElement("div", { className: "px-3 py-1.5 bg-surface-alt border-b border-border shrink-0" },
|
|
51
|
+
react_1.default.createElement("span", { className: "text-xs font-medium text-secondary truncate block" }, col.label)),
|
|
52
|
+
react_1.default.createElement("div", { className: "flex-1 overflow-y-auto" }, col.content))))));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ComparisonView.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EntityTabLayout — shared layout for entity tab content with list + cascade + collapse-on-focus.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { type ICascadeColumn } from './CascadeContainer';
|
|
7
|
+
import { type IComparisonColumn } from './ComparisonView';
|
|
8
|
+
/**
|
|
9
|
+
* Props for the EntityTabLayout component.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface IEntityTabLayoutProps {
|
|
13
|
+
/** The entity list content (rendered in the collapsible left panel) */
|
|
14
|
+
readonly list: React.ReactNode;
|
|
15
|
+
/** Cascade columns to display (empty array = no cascade) */
|
|
16
|
+
readonly cascadeColumns: ReadonlyArray<ICascadeColumn>;
|
|
17
|
+
/** Callback to pop the cascade back to a specific depth (0 = clear all) */
|
|
18
|
+
readonly onPopTo: (depth: number) => void;
|
|
19
|
+
/** Whether the entity list is currently collapsed */
|
|
20
|
+
readonly listCollapsed: boolean;
|
|
21
|
+
/** Callback to collapse the entity list (fired when user clicks inside cascade) */
|
|
22
|
+
readonly onListCollapse: () => void;
|
|
23
|
+
/** Whether compare mode is active */
|
|
24
|
+
readonly compareMode?: boolean;
|
|
25
|
+
/** Columns for the comparison view (when compare mode is active with 2+ selections) */
|
|
26
|
+
readonly comparisonColumns?: ReadonlyArray<IComparisonColumn>;
|
|
27
|
+
/** Whether the comparison view is actively showing (user explicitly triggered) */
|
|
28
|
+
readonly showingComparison?: boolean;
|
|
29
|
+
/** Callback to exit the comparison view (back to selection list) */
|
|
30
|
+
readonly onExitComparison?: () => void;
|
|
31
|
+
/** Columns for variation comparison (when comparing variations of a single recipe) */
|
|
32
|
+
readonly variationCompareColumns?: ReadonlyArray<IComparisonColumn>;
|
|
33
|
+
/** Callback to exit variation comparison mode */
|
|
34
|
+
readonly onExitVariationCompare?: () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Shared layout for entity tab content.
|
|
38
|
+
*
|
|
39
|
+
* Renders an entity list on the left and a cascade container on the right.
|
|
40
|
+
* The list stays expanded while browsing (selecting items in the list).
|
|
41
|
+
* It collapses when the user clicks inside the cascade detail pane,
|
|
42
|
+
* signaling they are focused on the detail rather than browsing.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare function EntityTabLayout(props: IEntityTabLayoutProps): React.ReactElement;
|
|
47
|
+
//# sourceMappingURL=EntityTabLayout.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
24
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.EntityTabLayout = EntityTabLayout;
|
|
28
|
+
/**
|
|
29
|
+
* EntityTabLayout — shared layout for entity tab content with list + cascade + collapse-on-focus.
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
const react_1 = __importDefault(require("react"));
|
|
33
|
+
const CascadeContainer_1 = require("./CascadeContainer");
|
|
34
|
+
const responsive_1 = require("../responsive");
|
|
35
|
+
const ComparisonView_1 = require("./ComparisonView");
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// EntityTabLayout Component
|
|
38
|
+
// ============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* Shared layout for entity tab content.
|
|
41
|
+
*
|
|
42
|
+
* Renders an entity list on the left and a cascade container on the right.
|
|
43
|
+
* The list stays expanded while browsing (selecting items in the list).
|
|
44
|
+
* It collapses when the user clicks inside the cascade detail pane,
|
|
45
|
+
* signaling they are focused on the detail rather than browsing.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
function EntityTabLayout(props) {
|
|
50
|
+
var _a;
|
|
51
|
+
const { list, cascadeColumns, onPopTo, listCollapsed, onListCollapse, compareMode, comparisonColumns } = props;
|
|
52
|
+
const variationCompareColumns = props.variationCompareColumns;
|
|
53
|
+
const onExitVariationCompare = props.onExitVariationCompare;
|
|
54
|
+
const showingComparison = (_a = props.showingComparison) !== null && _a !== void 0 ? _a : false;
|
|
55
|
+
const onExitComparison = props.onExitComparison;
|
|
56
|
+
const { layoutMode } = (0, responsive_1.useResponsive)();
|
|
57
|
+
const isVariationCompare = variationCompareColumns !== undefined && variationCompareColumns.length >= 2;
|
|
58
|
+
const showComparison = !isVariationCompare &&
|
|
59
|
+
showingComparison &&
|
|
60
|
+
comparisonColumns !== undefined &&
|
|
61
|
+
comparisonColumns.length >= 2;
|
|
62
|
+
const showCascade = !compareMode && !isVariationCompare && !showComparison && cascadeColumns.length > 0;
|
|
63
|
+
const hasCascadeOrCompare = cascadeColumns.length > 0 || showComparison;
|
|
64
|
+
// Variation compare banner — shared between mobile and desktop
|
|
65
|
+
const variationCompareBanner = isVariationCompare && onExitVariationCompare && (react_1.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-status-warning-bg border-b border-status-warning-border shrink-0" },
|
|
66
|
+
react_1.default.createElement("span", { className: "text-xs text-status-warning-text" },
|
|
67
|
+
"Comparing ",
|
|
68
|
+
variationCompareColumns.length,
|
|
69
|
+
" variations"),
|
|
70
|
+
react_1.default.createElement("button", { onClick: onExitVariationCompare, className: "px-2 py-0.5 text-xs rounded border border-status-warning-border text-status-warning-text hover:bg-status-warning-surface transition-colors" }, "Exit")));
|
|
71
|
+
// Mobile: show one pane at a time — list or cascade/comparison full-screen
|
|
72
|
+
if (layoutMode === 'mobile') {
|
|
73
|
+
const hasCascadeContent = showCascade || showComparison || isVariationCompare;
|
|
74
|
+
return (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" },
|
|
75
|
+
variationCompareBanner,
|
|
76
|
+
hasCascadeContent ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
77
|
+
showCascade && react_1.default.createElement(CascadeContainer_1.CascadeContainer, { columns: cascadeColumns, onPopTo: onPopTo }),
|
|
78
|
+
showComparison && (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" },
|
|
79
|
+
react_1.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-status-info-bg border-b border-status-info-border shrink-0" },
|
|
80
|
+
react_1.default.createElement("span", { className: "text-xs text-status-info-text" },
|
|
81
|
+
"Comparing ",
|
|
82
|
+
comparisonColumns.length,
|
|
83
|
+
" items"),
|
|
84
|
+
onExitComparison && (react_1.default.createElement("button", { onClick: onExitComparison, className: "px-2 py-0.5 text-xs rounded border border-status-info-border text-status-info-text hover:bg-status-info-surface transition-colors" }, "\u2190 Back to list"))),
|
|
85
|
+
react_1.default.createElement(ComparisonView_1.ComparisonView, { columns: comparisonColumns }))),
|
|
86
|
+
isVariationCompare && react_1.default.createElement(ComparisonView_1.ComparisonView, { columns: variationCompareColumns }))) : (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" }, list))));
|
|
87
|
+
}
|
|
88
|
+
// Desktop/compact: side-by-side list and cascade
|
|
89
|
+
return (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" },
|
|
90
|
+
variationCompareBanner,
|
|
91
|
+
react_1.default.createElement("div", { className: "flex flex-1 overflow-hidden" },
|
|
92
|
+
react_1.default.createElement("div", { className: `flex flex-col overflow-hidden transition-all ${isVariationCompare || showComparison
|
|
93
|
+
? 'w-0 min-w-0'
|
|
94
|
+
: listCollapsed
|
|
95
|
+
? 'w-0 min-w-0'
|
|
96
|
+
: hasCascadeOrCompare
|
|
97
|
+
? 'w-1/4 max-w-xs shrink-0 border-r border-border'
|
|
98
|
+
: 'w-full max-w-sm shrink-0 border-r border-border'}` }, list),
|
|
99
|
+
showCascade && (react_1.default.createElement(CascadeContainer_1.CascadeContainer, { columns: cascadeColumns, onPopTo: onPopTo, onFocus: onListCollapse })),
|
|
100
|
+
showComparison && (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" },
|
|
101
|
+
react_1.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-status-info-bg border-b border-status-info-border shrink-0" },
|
|
102
|
+
react_1.default.createElement("span", { className: "text-xs text-status-info-text" },
|
|
103
|
+
"Comparing ",
|
|
104
|
+
comparisonColumns.length,
|
|
105
|
+
" items"),
|
|
106
|
+
onExitComparison && (react_1.default.createElement("button", { onClick: onExitComparison, className: "px-2 py-0.5 text-xs rounded border border-status-info-border text-status-info-text hover:bg-status-info-surface transition-colors" }, "\u2190 Back to list"))),
|
|
107
|
+
react_1.default.createElement(ComparisonView_1.ComparisonView, { columns: comparisonColumns }))),
|
|
108
|
+
isVariationCompare && react_1.default.createElement(ComparisonView_1.ComparisonView, { columns: variationCompareColumns }))));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=EntityTabLayout.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mobile view-stack cascade — one full-screen column at a time with back navigation.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { type ICascadeContainerProps } from './CascadeContainer';
|
|
7
|
+
/**
|
|
8
|
+
* Mobile replacement for {@link CascadeContainer}.
|
|
9
|
+
*
|
|
10
|
+
* Shows the rightmost (deepest) cascade column full-screen with a back button
|
|
11
|
+
* that pops one level at a time. At the first column, back returns to the list
|
|
12
|
+
* by calling `onPopTo(0)`.
|
|
13
|
+
*
|
|
14
|
+
* Accepts the same props as {@link CascadeContainer} so `CascadeContainer` can
|
|
15
|
+
* delegate to it transparently on mobile.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export declare function MobileCascadeStack(props: ICascadeContainerProps): React.ReactElement | null;
|
|
20
|
+
//# sourceMappingURL=MobileCascadeStack.d.ts.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
+
var ownKeys = function(o) {
|
|
41
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
+
var ar = [];
|
|
43
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
+
__setModuleDefault(result, mod);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
+
exports.MobileCascadeStack = MobileCascadeStack;
|
|
58
|
+
/**
|
|
59
|
+
* Mobile view-stack cascade — one full-screen column at a time with back navigation.
|
|
60
|
+
* @packageDocumentation
|
|
61
|
+
*/
|
|
62
|
+
const react_1 = __importStar(require("react"));
|
|
63
|
+
/**
|
|
64
|
+
* Mobile replacement for {@link CascadeContainer}.
|
|
65
|
+
*
|
|
66
|
+
* Shows the rightmost (deepest) cascade column full-screen with a back button
|
|
67
|
+
* that pops one level at a time. At the first column, back returns to the list
|
|
68
|
+
* by calling `onPopTo(0)`.
|
|
69
|
+
*
|
|
70
|
+
* Accepts the same props as {@link CascadeContainer} so `CascadeContainer` can
|
|
71
|
+
* delegate to it transparently on mobile.
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
function MobileCascadeStack(props) {
|
|
76
|
+
const { columns, onPopTo, rootLabel = 'List' } = props;
|
|
77
|
+
const handleBack = (0, react_1.useCallback)(() => {
|
|
78
|
+
if (columns.length > 1) {
|
|
79
|
+
onPopTo(columns.length - 1);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
onPopTo(0);
|
|
83
|
+
}
|
|
84
|
+
}, [columns.length, onPopTo]);
|
|
85
|
+
if (columns.length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const currentColumn = columns[columns.length - 1];
|
|
89
|
+
const backLabel = columns.length > 1 ? columns[columns.length - 2].label : rootLabel;
|
|
90
|
+
return (react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-hidden" },
|
|
91
|
+
react_1.default.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-surface-alt border-b border-border shrink-0" },
|
|
92
|
+
react_1.default.createElement("button", { onClick: handleBack, className: "flex items-center gap-1 text-sm text-brand-accent hover:text-brand-primary", "aria-label": `Back to ${backLabel}` },
|
|
93
|
+
react_1.default.createElement("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor" },
|
|
94
|
+
react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5L8.25 12l7.5-7.5" })),
|
|
95
|
+
backLabel),
|
|
96
|
+
columns.length > 1 && (react_1.default.createElement("span", { className: "ml-auto text-xs text-muted truncate" }, currentColumn.label))),
|
|
97
|
+
react_1.default.createElement("div", { className: "flex flex-col flex-1 overflow-y-auto" }, currentColumn.content)));
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=MobileCascadeStack.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade packlet - column cascade container, layout, and semantic operations.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { CascadeContainer, type ICascadeContainerProps, type ICascadeColumn } from './CascadeContainer';
|
|
6
|
+
export { MobileCascadeStack } from './MobileCascadeStack';
|
|
7
|
+
export { EntityTabLayout, type IEntityTabLayoutProps } from './EntityTabLayout';
|
|
8
|
+
export { ComparisonView, type IComparisonViewProps, type IComparisonColumn } from './ComparisonView';
|
|
9
|
+
export { type CascadeColumnMode, type CascadeEntryOrigin, type ICascadeEntryBase, CASCADE_NEW_ENTITY_ID } from './model';
|
|
10
|
+
export { useSquashAt, useCascadeDrillDown } from './useCascadeTransitions';
|
|
11
|
+
export { type ICascadeConflict, type ICascadeFind, type CascadeEntrySpec, type ICascadeOps, useCascadeOps } from './useCascadeOps';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.useCascadeOps = exports.useCascadeDrillDown = exports.useSquashAt = exports.CASCADE_NEW_ENTITY_ID = exports.ComparisonView = exports.EntityTabLayout = exports.MobileCascadeStack = exports.CascadeContainer = void 0;
|
|
25
|
+
/**
|
|
26
|
+
* Cascade packlet - column cascade container, layout, and semantic operations.
|
|
27
|
+
* @packageDocumentation
|
|
28
|
+
*/
|
|
29
|
+
// UI components
|
|
30
|
+
var CascadeContainer_1 = require("./CascadeContainer");
|
|
31
|
+
Object.defineProperty(exports, "CascadeContainer", { enumerable: true, get: function () { return CascadeContainer_1.CascadeContainer; } });
|
|
32
|
+
var MobileCascadeStack_1 = require("./MobileCascadeStack");
|
|
33
|
+
Object.defineProperty(exports, "MobileCascadeStack", { enumerable: true, get: function () { return MobileCascadeStack_1.MobileCascadeStack; } });
|
|
34
|
+
var EntityTabLayout_1 = require("./EntityTabLayout");
|
|
35
|
+
Object.defineProperty(exports, "EntityTabLayout", { enumerable: true, get: function () { return EntityTabLayout_1.EntityTabLayout; } });
|
|
36
|
+
var ComparisonView_1 = require("./ComparisonView");
|
|
37
|
+
Object.defineProperty(exports, "ComparisonView", { enumerable: true, get: function () { return ComparisonView_1.ComparisonView; } });
|
|
38
|
+
// Cascade model types
|
|
39
|
+
var model_1 = require("./model");
|
|
40
|
+
Object.defineProperty(exports, "CASCADE_NEW_ENTITY_ID", { enumerable: true, get: function () { return model_1.CASCADE_NEW_ENTITY_ID; } });
|
|
41
|
+
// Cascade transition hooks
|
|
42
|
+
var useCascadeTransitions_1 = require("./useCascadeTransitions");
|
|
43
|
+
Object.defineProperty(exports, "useSquashAt", { enumerable: true, get: function () { return useCascadeTransitions_1.useSquashAt; } });
|
|
44
|
+
Object.defineProperty(exports, "useCascadeDrillDown", { enumerable: true, get: function () { return useCascadeTransitions_1.useCascadeDrillDown; } });
|
|
45
|
+
// Semantic cascade operations
|
|
46
|
+
var useCascadeOps_1 = require("./useCascadeOps");
|
|
47
|
+
Object.defineProperty(exports, "useCascadeOps", { enumerable: true, get: function () { return useCascadeOps_1.useCascadeOps; } });
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base cascade model types for column cascade navigation.
|
|
3
|
+
*
|
|
4
|
+
* These types are domain-agnostic — they define the structure and semantics
|
|
5
|
+
* of cascade navigation without knowledge of specific entity types.
|
|
6
|
+
* Domain-specific applications extend {@link ICascadeEntryBase} with their
|
|
7
|
+
* own entity types and additional fields.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Mode for a cascade column (view-only, editing, or creating a new entity).
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export type CascadeColumnMode = 'view' | 'edit' | 'create' | 'preview';
|
|
16
|
+
/**
|
|
17
|
+
* How a cascade entry was opened — determines save/cancel behavior.
|
|
18
|
+
*
|
|
19
|
+
* - `'primary'` — selected from the entity list. Save/cancel transitions to view mode in-place.
|
|
20
|
+
* - `'nested'` — reached via drill-down, typeahead-create, or sub-entity editing. Save/cancel pops (removes entry).
|
|
21
|
+
*
|
|
22
|
+
* Entries without an explicit origin are treated as `'primary'` for backwards compatibility.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export type CascadeEntryOrigin = 'primary' | 'nested';
|
|
26
|
+
/**
|
|
27
|
+
* Sentinel value used as entityId when creating a new entity.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export declare const CASCADE_NEW_ENTITY_ID: '__new__';
|
|
31
|
+
/**
|
|
32
|
+
* Base interface for a single entry in the column cascade stack.
|
|
33
|
+
*
|
|
34
|
+
* This interface contains only the fields needed by the generic cascade
|
|
35
|
+
* operations ({@link useCascadeOps}, {@link useSquashAt}, {@link useCascadeDrillDown}).
|
|
36
|
+
* Domain-specific applications should extend this interface with additional
|
|
37
|
+
* fields (e.g., target weights, source references, session context).
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export interface ICascadeEntryBase {
|
|
42
|
+
/** The type of entity displayed in this column (domain-specific string). */
|
|
43
|
+
readonly entityType: string;
|
|
44
|
+
/** The ID of the entity (qualified ID, e.g. 'collection.base-id'). */
|
|
45
|
+
readonly entityId: string;
|
|
46
|
+
/** Whether the column is in view, edit, create, or preview mode. */
|
|
47
|
+
readonly mode: CascadeColumnMode;
|
|
48
|
+
/** How this entry was opened. Determines save/cancel behavior. @see CascadeEntryOrigin */
|
|
49
|
+
readonly origin?: CascadeEntryOrigin;
|
|
50
|
+
/** Optional pre-resolved materialized entity. */
|
|
51
|
+
readonly entity?: unknown;
|
|
52
|
+
/** Whether this cascade entry has unsaved changes (set by the owning tab component). */
|
|
53
|
+
readonly hasChanges?: boolean;
|
|
54
|
+
/** Pre-fill name for entity creation (set when on-blur typeahead doesn't match). */
|
|
55
|
+
readonly prefillName?: string;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2026 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.CASCADE_NEW_ENTITY_ID = void 0;
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Cascade Entry Base
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Sentinel value used as entityId when creating a new entity.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
exports.CASCADE_NEW_ENTITY_ID = '__new__';
|
|
33
|
+
//# sourceMappingURL=model.js.map
|