@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.
Files changed (180) hide show
  1. package/README.md +26 -0
  2. package/dist/index.browser.js +3 -0
  3. package/dist/index.js +43 -0
  4. package/dist/packlets/ai-assist/index.js +6 -0
  5. package/dist/packlets/ai-assist/useAiAssist.js +219 -0
  6. package/dist/packlets/cascade/CascadeContainer.js +83 -0
  7. package/dist/packlets/cascade/ComparisonView.js +48 -0
  8. package/dist/packlets/cascade/EntityTabLayout.js +104 -0
  9. package/dist/packlets/cascade/MobileCascadeStack.js +63 -0
  10. package/dist/packlets/cascade/index.js +37 -0
  11. package/dist/packlets/cascade/model.js +30 -0
  12. package/dist/packlets/cascade/useCascadeOps.js +206 -0
  13. package/dist/packlets/cascade/useCascadeTransitions.js +58 -0
  14. package/dist/packlets/detail/DetailHelpers.js +103 -0
  15. package/dist/packlets/detail/index.js +6 -0
  16. package/dist/packlets/drop-zone/JsonDropZone.js +112 -0
  17. package/dist/packlets/drop-zone/index.js +6 -0
  18. package/dist/packlets/editing/EditFieldHelpers.js +130 -0
  19. package/dist/packlets/editing/MultiActionButton.js +73 -0
  20. package/dist/packlets/editing/NumericInput.js +119 -0
  21. package/dist/packlets/editing/TypeaheadInput.js +207 -0
  22. package/dist/packlets/editing/index.js +10 -0
  23. package/dist/packlets/editing/useTypeaheadMatch.js +102 -0
  24. package/dist/packlets/keyboard/index.js +7 -0
  25. package/dist/packlets/keyboard/registry.js +133 -0
  26. package/dist/packlets/keyboard/useKeyboardShortcuts.js +117 -0
  27. package/dist/packlets/messages/MessagesContext.js +76 -0
  28. package/dist/packlets/messages/MessagesLogger.js +103 -0
  29. package/dist/packlets/messages/StatusBar.js +154 -0
  30. package/dist/packlets/messages/Toast.js +68 -0
  31. package/dist/packlets/messages/index.js +11 -0
  32. package/dist/packlets/messages/model.js +56 -0
  33. package/dist/packlets/messages/useLogReporter.js +66 -0
  34. package/dist/packlets/modal/ConfirmDialog.js +78 -0
  35. package/dist/packlets/modal/Modal.js +55 -0
  36. package/dist/packlets/modal/index.js +7 -0
  37. package/dist/packlets/print/PrintEnclosure.js +60 -0
  38. package/dist/packlets/print/index.js +7 -0
  39. package/dist/packlets/print/openPrintWindow.js +112 -0
  40. package/dist/packlets/responsive/ResponsiveProvider.js +56 -0
  41. package/dist/packlets/responsive/index.js +7 -0
  42. package/dist/packlets/responsive/useResponsiveLayout.js +118 -0
  43. package/dist/packlets/selectors/EntityRow.js +276 -0
  44. package/dist/packlets/selectors/PreferredSelector.js +251 -0
  45. package/dist/packlets/selectors/index.js +24 -0
  46. package/dist/packlets/sidebar/CollectionSection.js +107 -0
  47. package/dist/packlets/sidebar/EntityList.js +164 -0
  48. package/dist/packlets/sidebar/FilterBar.js +42 -0
  49. package/dist/packlets/sidebar/FilterRow.js +182 -0
  50. package/dist/packlets/sidebar/GroupedEntityList.js +183 -0
  51. package/dist/packlets/sidebar/SearchBar.js +34 -0
  52. package/dist/packlets/sidebar/SidebarLayout.js +62 -0
  53. package/dist/packlets/sidebar/index.js +12 -0
  54. package/dist/packlets/theme/ThemeProvider.js +141 -0
  55. package/dist/packlets/theme/index.js +6 -0
  56. package/dist/packlets/top-bar/ModeSelector.js +46 -0
  57. package/dist/packlets/top-bar/TabBar.js +37 -0
  58. package/dist/packlets/top-bar/index.js +7 -0
  59. package/dist/packlets/url-sync/index.js +6 -0
  60. package/dist/packlets/url-sync/useUrlSync.js +157 -0
  61. package/eslint.config.js +22 -0
  62. package/lib/index.browser.d.ts +2 -0
  63. package/lib/index.browser.js +19 -0
  64. package/lib/index.d.ts +28 -0
  65. package/lib/index.js +59 -0
  66. package/lib/packlets/ai-assist/index.d.ts +6 -0
  67. package/lib/packlets/ai-assist/index.js +11 -0
  68. package/lib/packlets/ai-assist/useAiAssist.d.ts +77 -0
  69. package/lib/packlets/ai-assist/useAiAssist.js +223 -0
  70. package/lib/packlets/cascade/CascadeContainer.d.ts +44 -0
  71. package/lib/packlets/cascade/CascadeContainer.js +119 -0
  72. package/lib/packlets/cascade/ComparisonView.d.ts +35 -0
  73. package/lib/packlets/cascade/ComparisonView.js +54 -0
  74. package/lib/packlets/cascade/EntityTabLayout.d.ts +47 -0
  75. package/lib/packlets/cascade/EntityTabLayout.js +110 -0
  76. package/lib/packlets/cascade/MobileCascadeStack.d.ts +20 -0
  77. package/lib/packlets/cascade/MobileCascadeStack.js +99 -0
  78. package/lib/packlets/cascade/index.d.ts +12 -0
  79. package/lib/packlets/cascade/index.js +48 -0
  80. package/lib/packlets/cascade/model.d.ts +57 -0
  81. package/lib/packlets/cascade/model.js +33 -0
  82. package/lib/packlets/cascade/useCascadeOps.d.ts +111 -0
  83. package/lib/packlets/cascade/useCascadeOps.js +209 -0
  84. package/lib/packlets/cascade/useCascadeTransitions.d.ts +19 -0
  85. package/lib/packlets/cascade/useCascadeTransitions.js +62 -0
  86. package/lib/packlets/detail/DetailHelpers.d.ts +83 -0
  87. package/lib/packlets/detail/DetailHelpers.js +113 -0
  88. package/lib/packlets/detail/index.d.ts +6 -0
  89. package/lib/packlets/detail/index.js +14 -0
  90. package/lib/packlets/drop-zone/JsonDropZone.d.ts +40 -0
  91. package/lib/packlets/drop-zone/JsonDropZone.js +149 -0
  92. package/lib/packlets/drop-zone/index.d.ts +6 -0
  93. package/lib/packlets/drop-zone/index.js +10 -0
  94. package/lib/packlets/editing/EditFieldHelpers.d.ts +171 -0
  95. package/lib/packlets/editing/EditFieldHelpers.js +144 -0
  96. package/lib/packlets/editing/MultiActionButton.d.ts +45 -0
  97. package/lib/packlets/editing/MultiActionButton.js +109 -0
  98. package/lib/packlets/editing/NumericInput.d.ts +47 -0
  99. package/lib/packlets/editing/NumericInput.js +155 -0
  100. package/lib/packlets/editing/TypeaheadInput.d.ts +46 -0
  101. package/lib/packlets/editing/TypeaheadInput.js +243 -0
  102. package/lib/packlets/editing/index.d.ts +10 -0
  103. package/lib/packlets/editing/index.js +26 -0
  104. package/lib/packlets/editing/useTypeaheadMatch.d.ts +42 -0
  105. package/lib/packlets/editing/useTypeaheadMatch.js +105 -0
  106. package/lib/packlets/keyboard/index.d.ts +7 -0
  107. package/lib/packlets/keyboard/index.js +15 -0
  108. package/lib/packlets/keyboard/registry.d.ts +92 -0
  109. package/lib/packlets/keyboard/registry.js +138 -0
  110. package/lib/packlets/keyboard/useKeyboardShortcuts.d.ts +50 -0
  111. package/lib/packlets/keyboard/useKeyboardShortcuts.js +155 -0
  112. package/lib/packlets/messages/MessagesContext.d.ts +40 -0
  113. package/lib/packlets/messages/MessagesContext.js +113 -0
  114. package/lib/packlets/messages/MessagesLogger.d.ts +50 -0
  115. package/lib/packlets/messages/MessagesLogger.js +107 -0
  116. package/lib/packlets/messages/StatusBar.d.ts +22 -0
  117. package/lib/packlets/messages/StatusBar.js +190 -0
  118. package/lib/packlets/messages/Toast.d.ts +31 -0
  119. package/lib/packlets/messages/Toast.js +105 -0
  120. package/lib/packlets/messages/index.d.ts +11 -0
  121. package/lib/packlets/messages/index.js +24 -0
  122. package/lib/packlets/messages/model.d.ts +59 -0
  123. package/lib/packlets/messages/model.js +61 -0
  124. package/lib/packlets/messages/useLogReporter.d.ts +22 -0
  125. package/lib/packlets/messages/useLogReporter.js +69 -0
  126. package/lib/packlets/modal/ConfirmDialog.d.ts +39 -0
  127. package/lib/packlets/modal/ConfirmDialog.js +114 -0
  128. package/lib/packlets/modal/Modal.d.ts +22 -0
  129. package/lib/packlets/modal/Modal.js +91 -0
  130. package/lib/packlets/modal/index.d.ts +7 -0
  131. package/lib/packlets/modal/index.js +12 -0
  132. package/lib/packlets/print/PrintEnclosure.d.ts +33 -0
  133. package/lib/packlets/print/PrintEnclosure.js +96 -0
  134. package/lib/packlets/print/index.d.ts +7 -0
  135. package/lib/packlets/print/index.js +12 -0
  136. package/lib/packlets/print/openPrintWindow.d.ts +35 -0
  137. package/lib/packlets/print/openPrintWindow.js +118 -0
  138. package/lib/packlets/responsive/ResponsiveProvider.d.ts +35 -0
  139. package/lib/packlets/responsive/ResponsiveProvider.js +93 -0
  140. package/lib/packlets/responsive/index.d.ts +7 -0
  141. package/lib/packlets/responsive/index.js +13 -0
  142. package/lib/packlets/responsive/useResponsiveLayout.d.ts +48 -0
  143. package/lib/packlets/responsive/useResponsiveLayout.js +121 -0
  144. package/lib/packlets/selectors/EntityRow.d.ts +45 -0
  145. package/lib/packlets/selectors/EntityRow.js +315 -0
  146. package/lib/packlets/selectors/PreferredSelector.d.ts +50 -0
  147. package/lib/packlets/selectors/PreferredSelector.js +287 -0
  148. package/lib/packlets/selectors/index.d.ts +5 -0
  149. package/lib/packlets/selectors/index.js +29 -0
  150. package/lib/packlets/sidebar/CollectionSection.d.ts +82 -0
  151. package/lib/packlets/sidebar/CollectionSection.js +143 -0
  152. package/lib/packlets/sidebar/EntityList.d.ts +105 -0
  153. package/lib/packlets/sidebar/EntityList.js +200 -0
  154. package/lib/packlets/sidebar/FilterBar.d.ts +26 -0
  155. package/lib/packlets/sidebar/FilterBar.js +48 -0
  156. package/lib/packlets/sidebar/FilterRow.d.ts +42 -0
  157. package/lib/packlets/sidebar/FilterRow.js +218 -0
  158. package/lib/packlets/sidebar/GroupedEntityList.d.ts +59 -0
  159. package/lib/packlets/sidebar/GroupedEntityList.js +219 -0
  160. package/lib/packlets/sidebar/SearchBar.d.ts +19 -0
  161. package/lib/packlets/sidebar/SearchBar.js +40 -0
  162. package/lib/packlets/sidebar/SidebarLayout.d.ts +28 -0
  163. package/lib/packlets/sidebar/SidebarLayout.js +98 -0
  164. package/lib/packlets/sidebar/index.d.ts +12 -0
  165. package/lib/packlets/sidebar/index.js +22 -0
  166. package/lib/packlets/theme/ThemeProvider.d.ts +68 -0
  167. package/lib/packlets/theme/ThemeProvider.js +178 -0
  168. package/lib/packlets/theme/index.d.ts +6 -0
  169. package/lib/packlets/theme/index.js +11 -0
  170. package/lib/packlets/top-bar/ModeSelector.d.ts +38 -0
  171. package/lib/packlets/top-bar/ModeSelector.js +52 -0
  172. package/lib/packlets/top-bar/TabBar.d.ts +31 -0
  173. package/lib/packlets/top-bar/TabBar.js +43 -0
  174. package/lib/packlets/top-bar/index.d.ts +7 -0
  175. package/lib/packlets/top-bar/index.js +12 -0
  176. package/lib/packlets/url-sync/index.d.ts +6 -0
  177. package/lib/packlets/url-sync/index.js +12 -0
  178. package/lib/packlets/url-sync/useUrlSync.d.ts +75 -0
  179. package/lib/packlets/url-sync/useUrlSync.js +162 -0
  180. package/package.json +82 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Configuration for the URL sync hook.
3
+ * Provides the validation tables and default values needed to
4
+ * parse and validate URL hash segments.
5
+ * @public
6
+ */
7
+ export interface IUrlSyncConfig<TMode extends string, TTab extends string> {
8
+ /** All valid mode identifiers */
9
+ readonly validModes: ReadonlyArray<TMode>;
10
+ /** Valid tabs per mode */
11
+ readonly validTabs: Record<TMode, ReadonlyArray<TTab>>;
12
+ /** Default tab for each mode (used when hash has a valid mode but no valid tab) */
13
+ readonly defaultTabs: Record<TMode, TTab>;
14
+ }
15
+ /**
16
+ * Callbacks that connect the URL sync hook to the application's state management.
17
+ * @public
18
+ */
19
+ export interface IUrlSyncCallbacks<TMode extends string, TTab extends string> {
20
+ /** Set the active mode */
21
+ readonly setMode: (mode: TMode) => void;
22
+ /** Set the active tab */
23
+ readonly setTab: (tab: TTab) => void;
24
+ }
25
+ /**
26
+ * Current navigation state to sync to the URL.
27
+ * @public
28
+ */
29
+ export interface IUrlSyncState<TMode extends string, TTab extends string> {
30
+ /** Current mode */
31
+ readonly mode: TMode;
32
+ /** Current active tab */
33
+ readonly activeTab: TTab;
34
+ }
35
+ /**
36
+ * Result of parsing a URL hash.
37
+ * @public
38
+ */
39
+ export interface IParsedHash<TMode extends string, TTab extends string> {
40
+ readonly mode: TMode;
41
+ readonly tab: TTab;
42
+ }
43
+ /**
44
+ * Encodes mode + tab into a URL hash string.
45
+ * @param mode - The current mode
46
+ * @param tab - The current tab
47
+ * @returns Hash string (e.g., '#/library/ingredients')
48
+ * @public
49
+ */
50
+ export declare function encodeUrlHash<TMode extends string, TTab extends string>(mode: TMode, tab: TTab): string;
51
+ /**
52
+ * Parses a URL hash string into mode + tab, validated against the config.
53
+ * Returns undefined if the hash is invalid or empty.
54
+ * @param hash - The hash string (with or without leading '#')
55
+ * @param config - Validation configuration
56
+ * @returns Parsed mode and tab, or undefined
57
+ * @public
58
+ */
59
+ export declare function parseUrlHash<TMode extends string, TTab extends string>(hash: string, config: IUrlSyncConfig<TMode, TTab>): IParsedHash<TMode, TTab> | undefined;
60
+ /**
61
+ * Hook that synchronizes two-tier mode/tab navigation state with the URL hash.
62
+ *
63
+ * - On mount: reads the URL hash and applies it to the store
64
+ * - On state change: updates the URL hash (pushes history entry)
65
+ * - On popstate (back/forward): reads the URL hash and applies it to the store
66
+ *
67
+ * Should be called once at the app root level.
68
+ *
69
+ * @param config - Validation configuration (modes, tabs, defaults)
70
+ * @param state - Current navigation state
71
+ * @param callbacks - State mutation callbacks
72
+ * @public
73
+ */
74
+ export declare function useUrlSync<TMode extends string, TTab extends string>(config: IUrlSyncConfig<TMode, TTab>, state: IUrlSyncState<TMode, TTab>, callbacks: IUrlSyncCallbacks<TMode, TTab>): void;
75
+ //# sourceMappingURL=useUrlSync.d.ts.map
@@ -0,0 +1,162 @@
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.encodeUrlHash = encodeUrlHash;
25
+ exports.parseUrlHash = parseUrlHash;
26
+ exports.useUrlSync = useUrlSync;
27
+ /**
28
+ * Generic URL hash synchronization for two-tier mode/tab navigation.
29
+ *
30
+ * Encodes mode + tab in the URL hash: `#/{mode}/{tab}`
31
+ * Syncs bidirectionally between application state and the URL.
32
+ * Handles browser back/forward via popstate.
33
+ *
34
+ * @packageDocumentation
35
+ */
36
+ const react_1 = require("react");
37
+ /**
38
+ * Encodes mode + tab into a URL hash string.
39
+ * @param mode - The current mode
40
+ * @param tab - The current tab
41
+ * @returns Hash string (e.g., '#/library/ingredients')
42
+ * @public
43
+ */
44
+ function encodeUrlHash(mode, tab) {
45
+ return `#/${mode}/${tab}`;
46
+ }
47
+ /**
48
+ * Parses a URL hash string into mode + tab, validated against the config.
49
+ * Returns undefined if the hash is invalid or empty.
50
+ * @param hash - The hash string (with or without leading '#')
51
+ * @param config - Validation configuration
52
+ * @returns Parsed mode and tab, or undefined
53
+ * @public
54
+ */
55
+ function parseUrlHash(hash, config) {
56
+ const cleaned = hash.replace(/^#\/?/, '');
57
+ if (cleaned.length === 0) {
58
+ return undefined;
59
+ }
60
+ const parts = cleaned.split('/');
61
+ if (parts.length < 1) {
62
+ return undefined;
63
+ }
64
+ const mode = parts[0];
65
+ if (!config.validModes.includes(mode)) {
66
+ return undefined;
67
+ }
68
+ const validTabs = config.validTabs[mode];
69
+ if (parts.length >= 2) {
70
+ const tab = parts[1];
71
+ if (validTabs.includes(tab)) {
72
+ return { mode, tab };
73
+ }
74
+ }
75
+ // Valid mode but no valid tab — use default
76
+ return { mode, tab: config.defaultTabs[mode] };
77
+ }
78
+ // ============================================================================
79
+ // URL Sync Hook
80
+ // ============================================================================
81
+ /**
82
+ * Hook that synchronizes two-tier mode/tab navigation state with the URL hash.
83
+ *
84
+ * - On mount: reads the URL hash and applies it to the store
85
+ * - On state change: updates the URL hash (pushes history entry)
86
+ * - On popstate (back/forward): reads the URL hash and applies it to the store
87
+ *
88
+ * Should be called once at the app root level.
89
+ *
90
+ * @param config - Validation configuration (modes, tabs, defaults)
91
+ * @param state - Current navigation state
92
+ * @param callbacks - State mutation callbacks
93
+ * @public
94
+ */
95
+ function useUrlSync(config, state, callbacks) {
96
+ const { mode, activeTab } = state;
97
+ const { setMode, setTab } = callbacks;
98
+ // Track whether we're currently applying a URL change to avoid circular updates
99
+ const isApplyingUrl = (0, react_1.useRef)(false);
100
+ // Track whether we've done the initial load
101
+ const initialized = (0, react_1.useRef)(false);
102
+ // Keep refs to the latest values so the mount effect captures them without
103
+ // needing them in its dependency array (the effect must only run once).
104
+ const configRef = (0, react_1.useRef)(config);
105
+ configRef.current = config;
106
+ const modeRef = (0, react_1.useRef)(mode);
107
+ modeRef.current = mode;
108
+ const activeTabRef = (0, react_1.useRef)(activeTab);
109
+ activeTabRef.current = activeTab;
110
+ const setModeRef = (0, react_1.useRef)(setMode);
111
+ setModeRef.current = setMode;
112
+ const setTabRef = (0, react_1.useRef)(setTab);
113
+ setTabRef.current = setTab;
114
+ // ---- Initial load: URL → store ----
115
+ (0, react_1.useEffect)(() => {
116
+ if (initialized.current) {
117
+ return;
118
+ }
119
+ initialized.current = true;
120
+ const parsed = parseUrlHash(window.location.hash, configRef.current);
121
+ if (parsed) {
122
+ isApplyingUrl.current = true;
123
+ setModeRef.current(parsed.mode);
124
+ setTabRef.current(parsed.tab);
125
+ isApplyingUrl.current = false;
126
+ }
127
+ else {
128
+ // No valid hash — write current state to URL
129
+ const hash = encodeUrlHash(modeRef.current, activeTabRef.current);
130
+ window.history.replaceState(null, '', hash);
131
+ }
132
+ // Intentionally empty: this effect must run exactly once on mount.
133
+ // All values are accessed via refs to avoid stale closures.
134
+ }, []);
135
+ // ---- Store → URL: push history on navigation changes ----
136
+ (0, react_1.useEffect)(() => {
137
+ if (isApplyingUrl.current) {
138
+ return;
139
+ }
140
+ const hash = encodeUrlHash(mode, activeTab);
141
+ if (window.location.hash !== hash) {
142
+ window.history.pushState(null, '', hash);
143
+ }
144
+ }, [mode, activeTab]);
145
+ // ---- URL → store: handle popstate (back/forward) ----
146
+ (0, react_1.useEffect)(() => {
147
+ const handlePopState = () => {
148
+ const parsed = parseUrlHash(window.location.hash, config);
149
+ if (parsed) {
150
+ isApplyingUrl.current = true;
151
+ setMode(parsed.mode);
152
+ setTab(parsed.tab);
153
+ isApplyingUrl.current = false;
154
+ }
155
+ };
156
+ window.addEventListener('popstate', handlePopState);
157
+ return () => {
158
+ window.removeEventListener('popstate', handlePopState);
159
+ };
160
+ }, [config, setMode, setTab]);
161
+ }
162
+ //# sourceMappingURL=useUrlSync.js.map
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@fgv/ts-app-shell",
3
+ "version": "5.1.0-1",
4
+ "description": "Shared React UI primitives for application shells: column cascade, sidebar, toast/log messages, command palette, keybinding registry",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "scripts": {
8
+ "build": "heft build --clean",
9
+ "clean": "heft clean",
10
+ "test": "heft test --clean",
11
+ "lint": "eslint src --ext .ts,.tsx",
12
+ "fixlint": "eslint src --ext .ts,.tsx --fix",
13
+ "coverage": "jest --coverage"
14
+ },
15
+ "sideEffects": false,
16
+ "keywords": [
17
+ "typescript",
18
+ "react",
19
+ "components",
20
+ "app-shell",
21
+ "ui"
22
+ ],
23
+ "author": "Erik Fortune",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@fgv/ts-utils": "workspace:*",
27
+ "@heroicons/react": "~2.2.0",
28
+ "tslib": "^2.8.1",
29
+ "@fgv/ts-extras": "workspace:*"
30
+ },
31
+ "peerDependencies": {
32
+ "react": ">=18.0.0",
33
+ "react-dom": ">=18.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@fgv/heft-dual-rig": "workspace:*",
37
+ "@fgv/ts-utils-jest": "workspace:*",
38
+ "@types/react": "~19.2.8",
39
+ "@types/react-dom": "~19.2.3",
40
+ "react": "~19.2.3",
41
+ "react-dom": "~19.2.3",
42
+ "@types/jest": "^29.5.14",
43
+ "@types/node": "^20.14.9",
44
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
45
+ "@typescript-eslint/parser": "^8.52.0",
46
+ "eslint": "^9.39.2",
47
+ "eslint-plugin-import": "^2.32.0",
48
+ "eslint-plugin-node": "^11.1.0",
49
+ "eslint-plugin-promise": "^7.2.1",
50
+ "eslint-plugin-react": "^7.34.0",
51
+ "eslint-plugin-react-hooks": "^5.2.0",
52
+ "jest": "^29.7.0",
53
+ "@testing-library/react": "^16",
54
+ "@testing-library/user-event": "^14.6.1",
55
+ "@testing-library/jest-dom": "^6.4.2",
56
+ "rimraf": "^6.1.2",
57
+ "ts-jest": "^29.4.6",
58
+ "typescript": "5.9.3",
59
+ "@rushstack/heft": "1.2.6",
60
+ "@rushstack/eslint-config": "4.6.4",
61
+ "@rushstack/heft-jest-plugin": "1.2.6",
62
+ "@testing-library/dom": "^10.4.0",
63
+ "@rushstack/heft-node-rig": "2.11.26"
64
+ },
65
+ "exports": {
66
+ ".": {
67
+ "node": {
68
+ "import": "./lib/index.js",
69
+ "require": "./lib/index.js"
70
+ },
71
+ "default": {
72
+ "import": "./lib/index.browser.js",
73
+ "require": "./lib/index.browser.js"
74
+ },
75
+ "types": "lib/index.d.ts"
76
+ }
77
+ },
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "https://github.com/ErikFortune/fgv.git"
81
+ }
82
+ }