impact-nova 1.3.0 → 1.5.2

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 (117) hide show
  1. package/README.md +49 -0
  2. package/dist/components/layout/dashboard-layout.d.ts +15 -1
  3. package/dist/components/ui/accordion-nested-list/accordion-nested-list.js +65 -64
  4. package/dist/components/ui/accordion.js +38 -34
  5. package/dist/components/ui/ag-grid-react/cell-renderers/badge-cell-renderer.js +1 -1
  6. package/dist/components/ui/ag-grid-react/cell-renderers/cell-renderer-utils.d.ts +58 -0
  7. package/dist/components/ui/ag-grid-react/cell-renderers/cell-renderer-utils.js +104 -0
  8. package/dist/components/ui/ag-grid-react/cell-renderers/editors/input-cell-editor.js +62 -54
  9. package/dist/components/ui/ag-grid-react/cell-renderers/editors/split-cell-editor.d.ts +4 -6
  10. package/dist/components/ui/ag-grid-react/cell-renderers/editors/split-cell-editor.js +54 -68
  11. package/dist/components/ui/ag-grid-react/cell-renderers/index.d.ts +3 -1
  12. package/dist/components/ui/ag-grid-react/cell-renderers/index.js +33 -27
  13. package/dist/components/ui/ag-grid-react/cell-renderers/input-display-renderer.d.ts +3 -0
  14. package/dist/components/ui/ag-grid-react/cell-renderers/input-display-renderer.js +28 -12
  15. package/dist/components/ui/ag-grid-react/cell-renderers/link-with-batch-cell-renderer.d.ts +2 -0
  16. package/dist/components/ui/ag-grid-react/cell-renderers/link-with-batch-cell-renderer.js +45 -44
  17. package/dist/components/ui/ag-grid-react/cell-renderers/split-cell-renderer.d.ts +4 -6
  18. package/dist/components/ui/ag-grid-react/cell-renderers/split-cell-renderer.js +23 -37
  19. package/dist/components/ui/ag-grid-react/cell-renderers/types.d.ts +33 -17
  20. package/dist/components/ui/ag-grid-react/editable-utils.d.ts +27 -0
  21. package/dist/components/ui/ag-grid-react/editable-utils.js +62 -0
  22. package/dist/components/ui/ag-grid-react/headers/advanced-filter/advanced-filter-dialog.js +99 -98
  23. package/dist/components/ui/ag-grid-react/headers/advanced-filter/column-filter-section.js +110 -143
  24. package/dist/components/ui/ag-grid-react/headers/column-menu/column-settings-menu.js +72 -69
  25. package/dist/components/ui/ag-grid-react/headers/components/header-info.js +36 -35
  26. package/dist/components/ui/ag-grid-react/headers/components/info-modal.js +14 -12
  27. package/dist/components/ui/ag-grid-react/headers/custom-header.js +111 -110
  28. package/dist/components/ui/ag-grid-react/headers/header-search-input.js +204 -203
  29. package/dist/components/ui/alert.js +62 -58
  30. package/dist/components/ui/breadcrumb.js +81 -74
  31. package/dist/components/ui/calendar.js +354 -354
  32. package/dist/components/ui/chart/chart.js +63 -62
  33. package/dist/components/ui/chips.js +42 -38
  34. package/dist/components/ui/command-palette/command-palette-context.d.ts +52 -0
  35. package/dist/components/ui/command-palette/command-palette-context.js +110 -0
  36. package/dist/components/ui/command-palette/command-palette.d.ts +67 -0
  37. package/dist/components/ui/command-palette/command-palette.js +402 -0
  38. package/dist/components/ui/command-palette/index.d.ts +23 -0
  39. package/dist/components/ui/command-palette/index.js +44 -0
  40. package/dist/components/ui/command-palette/kbd.d.ts +28 -0
  41. package/dist/components/ui/command-palette/kbd.js +52 -0
  42. package/dist/components/ui/command-palette/shortcut-registry.d.ts +68 -0
  43. package/dist/components/ui/command-palette/shortcut-registry.js +183 -0
  44. package/dist/components/ui/command-palette/shortcut-scope-provider.d.ts +55 -0
  45. package/dist/components/ui/command-palette/shortcut-scope-provider.js +55 -0
  46. package/dist/components/ui/command-palette/shortcut-settings.d.ts +27 -0
  47. package/dist/components/ui/command-palette/shortcut-settings.js +266 -0
  48. package/dist/components/ui/command-palette/use-browser-shortcuts.d.ts +32 -0
  49. package/dist/components/ui/command-palette/use-browser-shortcuts.js +48 -0
  50. package/dist/components/ui/command-palette/use-global-shortcut.d.ts +3 -0
  51. package/dist/components/ui/command-palette/use-global-shortcut.js +7 -0
  52. package/dist/components/ui/command-palette/use-shortcut.d.ts +47 -0
  53. package/dist/components/ui/command-palette/use-shortcut.js +49 -0
  54. package/dist/components/ui/command-palette/utils.d.ts +119 -0
  55. package/dist/components/ui/command-palette/utils.js +248 -0
  56. package/dist/components/ui/data-table/data-table-column-list.js +87 -86
  57. package/dist/components/ui/data-table/data-table-format-options.js +45 -44
  58. package/dist/components/ui/data-table/data-table-view-options.js +39 -38
  59. package/dist/components/ui/date-picker/date-picker.js +89 -87
  60. package/dist/components/ui/date-picker/date-range-picker.js +140 -138
  61. package/dist/components/ui/date-picker/month-picker.js +82 -81
  62. package/dist/components/ui/date-picker/month-range-picker.js +108 -105
  63. package/dist/components/ui/date-picker/multi-date-picker.js +68 -66
  64. package/dist/components/ui/date-picker/multi-month-picker.js +59 -58
  65. package/dist/components/ui/date-picker/multi-week-picker.js +80 -78
  66. package/dist/components/ui/date-picker/week-picker.js +117 -115
  67. package/dist/components/ui/date-picker/week-range-picker.js +166 -164
  68. package/dist/components/ui/dialog.js +78 -73
  69. package/dist/components/ui/drawer.js +71 -66
  70. package/dist/components/ui/file-upload.js +131 -127
  71. package/dist/components/ui/filter-panel/filter-panel.js +98 -94
  72. package/dist/components/ui/filter-strip/filter-strip.js +95 -91
  73. package/dist/components/ui/filter-strip/filter-summary.js +91 -90
  74. package/dist/components/ui/header.js +57 -53
  75. package/dist/components/ui/horizontal-scroller/horizontal-scroller.js +78 -76
  76. package/dist/components/ui/loader.js +17 -16
  77. package/dist/components/ui/nested-list/components/NestedListHeader.d.ts +1 -0
  78. package/dist/components/ui/nested-list/components/NestedListHeader.js +51 -48
  79. package/dist/components/ui/nested-list/components/SortableItem.js +60 -59
  80. package/dist/components/ui/nested-list/nested-list.js +184 -182
  81. package/dist/components/ui/notification-panel/notification-panel.js +60 -53
  82. package/dist/components/ui/popover.js +45 -40
  83. package/dist/components/ui/prompt.js +90 -86
  84. package/dist/components/ui/select/select.js +206 -209
  85. package/dist/components/ui/sheet.d.ts +1 -0
  86. package/dist/components/ui/sheet.js +50 -48
  87. package/dist/components/ui/sidebar.js +273 -267
  88. package/dist/components/ui/stepper.js +75 -63
  89. package/dist/components/ui/tag.js +48 -44
  90. package/dist/components/ui/toast.js +46 -41
  91. package/dist/i18n/ImpactNovaI18nContext.d.ts +21 -0
  92. package/dist/i18n/ImpactNovaI18nContext.js +76 -0
  93. package/dist/i18n/defaultMessages.d.ts +231 -0
  94. package/dist/i18n/defaultMessages.js +206 -0
  95. package/dist/i18n/getDateFnsLocale.d.ts +11 -0
  96. package/dist/i18n/getDateFnsLocale.js +21 -0
  97. package/dist/i18n/index.d.ts +5 -0
  98. package/dist/i18n/locales/de.d.ts +2 -0
  99. package/dist/i18n/locales/de.js +206 -0
  100. package/dist/i18n/locales/es.d.ts +2 -0
  101. package/dist/i18n/locales/es.js +206 -0
  102. package/dist/i18n/locales/hi.d.ts +2 -0
  103. package/dist/i18n/locales/hi.js +206 -0
  104. package/dist/i18n/locales/index.d.ts +4 -0
  105. package/dist/i18n/locales/kn.d.ts +2 -0
  106. package/dist/i18n/locales/kn.js +206 -0
  107. package/dist/icons/assets/boxAdd.svg.js +5 -0
  108. package/dist/icons/assets/boxed.svg.js +5 -0
  109. package/dist/icons/assets/trolley.svg.js +5 -0
  110. package/dist/icons/assets/unlocked.svg.js +5 -0
  111. package/dist/icons/index.d.ts +4 -0
  112. package/dist/icons/index.js +179 -171
  113. package/dist/impact-nova.css +1 -1
  114. package/dist/index.d.ts +4 -0
  115. package/dist/index.js +232 -172
  116. package/package.json +36 -4
  117. package/dist/components/ui/ag-grid-react/cell-renderers/types.js +0 -74
@@ -0,0 +1,183 @@
1
+ import { isReservedShortcut as f, keybindingsEqual as m, matchesKeybinding as u, scopePriority as o, deserialiseOverrides as g, serialiseOverrides as v } from "./utils.js";
2
+ const l = "impact-nova-shortcuts", h = "impact-nova-recent-commands", p = 10;
3
+ class C {
4
+ commands = /* @__PURE__ */ new Map();
5
+ overrides = /* @__PURE__ */ new Map();
6
+ recentCommandIds = [];
7
+ listeners = /* @__PURE__ */ new Set();
8
+ activeScopes = /* @__PURE__ */ new Set();
9
+ activeInstance = null;
10
+ constructor() {
11
+ this.activeScopes.add("global"), this.loadOverrides(), this.loadRecentCommands();
12
+ }
13
+ // ─── Instance Management ────────────────────────────────────────────────
14
+ setActiveInstance(e) {
15
+ this.activeInstance !== e && (this.activeInstance = e, this.emit({ type: "scope-change" }));
16
+ }
17
+ getActiveInstance() {
18
+ return this.activeInstance;
19
+ }
20
+ /**
21
+ * Get all unique instance identifiers currently registered.
22
+ */
23
+ getRegisteredInstances() {
24
+ const e = /* @__PURE__ */ new Set();
25
+ for (const t of this.commands.values())
26
+ t.instance && e.add(t.instance);
27
+ return Array.from(e);
28
+ }
29
+ // ─── Registration ───────────────────────────────────────────────────────
30
+ register(e) {
31
+ this.commands.set(e.id, e);
32
+ const t = this.overrides.get(e.id);
33
+ t && (e.keybinding = t), this.emit({ type: "register", commandId: e.id });
34
+ }
35
+ unregister(e) {
36
+ this.commands.delete(e), this.emit({ type: "unregister", commandId: e });
37
+ }
38
+ // ─── Keybinding Management ─────────────────────────────────────────────
39
+ getEffectiveKeybinding(e) {
40
+ const t = this.commands.get(e);
41
+ if (t)
42
+ return t.keybinding ?? t.defaultKeybinding;
43
+ }
44
+ updateKeybinding(e, t) {
45
+ const s = this.commands.get(e);
46
+ if (!s) return { success: !1 };
47
+ if (!s.customisable) return { success: !1 };
48
+ if (f(t))
49
+ return { success: !1, reserved: !0 };
50
+ const n = this.findConflict(e, t, s.scope);
51
+ return n ? { success: !1, conflict: n } : (s.keybinding = t, this.overrides.set(e, t), this.saveOverrides(), this.emit({ type: "update-keybinding", commandId: e }), { success: !0 });
52
+ }
53
+ resetKeybinding(e) {
54
+ const t = this.commands.get(e);
55
+ t && (t.keybinding = void 0, this.overrides.delete(e), this.saveOverrides(), this.emit({ type: "reset-keybinding", commandId: e }));
56
+ }
57
+ // ─── Conflict Detection ────────────────────────────────────────────────
58
+ findConflict(e, t, s) {
59
+ for (const [n, r] of this.commands) {
60
+ if (n === e || r.scope !== s) continue;
61
+ const c = this.getEffectiveKeybinding(n);
62
+ if (c && m(c, t))
63
+ return {
64
+ conflictingCommandId: n,
65
+ conflictingLabel: r.label,
66
+ scope: r.scope
67
+ };
68
+ }
69
+ return null;
70
+ }
71
+ // ─── Scope Management ──────────────────────────────────────────────────
72
+ pushScope(e) {
73
+ this.activeScopes.add(e), this.emit({ type: "scope-change" });
74
+ }
75
+ popScope(e) {
76
+ e !== "global" && (this.activeScopes.delete(e), this.emit({ type: "scope-change" }));
77
+ }
78
+ getActiveScopes() {
79
+ return Array.from(this.activeScopes);
80
+ }
81
+ getHighestActiveScope() {
82
+ let e = "global";
83
+ for (const t of this.activeScopes)
84
+ o(t) > o(e) && (e = t);
85
+ return e;
86
+ }
87
+ // ─── Command Queries ───────────────────────────────────────────────────
88
+ getCommand(e) {
89
+ return this.commands.get(e);
90
+ }
91
+ getAllCommands() {
92
+ return Array.from(this.commands.values());
93
+ }
94
+ /**
95
+ * Get commands visible in the command palette.
96
+ * Instance-scoped commands are filtered (only active instance shows unless
97
+ * there's only one instance, in which case it always shows).
98
+ * When multiple instances exist, labels are auto-prefixed with the instance name.
99
+ */
100
+ getPaletteCommands() {
101
+ const t = this.getRegisteredInstances().length > 1;
102
+ return this.getAllCommands().filter((s) => !(s.hidden || s.when && !s.when() || s.instance && t && this.activeInstance && s.instance !== this.activeInstance));
103
+ }
104
+ /**
105
+ * Get commands for the settings panel (all registered, including hidden).
106
+ */
107
+ getSettingsCommands() {
108
+ return this.getAllCommands();
109
+ }
110
+ // ─── Keyboard Event Handling ───────────────────────────────────────────
111
+ /**
112
+ * Handle a keyboard event. Finds the highest-priority matching command
113
+ * and executes its handler.
114
+ *
115
+ * @returns true if a command was executed, false otherwise
116
+ */
117
+ handleKeyEvent(e) {
118
+ const t = this.activeScopes.has("modal"), n = this.getRegisteredInstances().length > 1;
119
+ let r = null, c = -1;
120
+ for (const i of this.commands.values()) {
121
+ if (i.passive) continue;
122
+ const a = this.getEffectiveKeybinding(i.id);
123
+ if (a && !(t && i.scope !== "modal") && !(i.instance && n && i.instance !== this.activeInstance) && !(i.when && !i.when()) && u(e, a)) {
124
+ const d = o(i.scope);
125
+ d > c && (r = i, c = d);
126
+ }
127
+ }
128
+ return r ? (e.preventDefault(), e.stopPropagation(), r.handler(), this.addRecentCommand(r.id), !0) : !1;
129
+ }
130
+ // ─── Recent Commands ───────────────────────────────────────────────────
131
+ getRecentCommandIds() {
132
+ return [...this.recentCommandIds];
133
+ }
134
+ addRecentCommand(e) {
135
+ this.recentCommandIds = [
136
+ e,
137
+ ...this.recentCommandIds.filter((t) => t !== e)
138
+ ].slice(0, p), this.saveRecentCommands();
139
+ }
140
+ // ─── Event System ─────────────────────────────────────────────────────
141
+ subscribe(e) {
142
+ return this.listeners.add(e), () => {
143
+ this.listeners.delete(e);
144
+ };
145
+ }
146
+ emit(e) {
147
+ this.listeners.forEach((t) => t(e));
148
+ }
149
+ // ─── Persistence ──────────────────────────────────────────────────────
150
+ loadOverrides() {
151
+ if (!(typeof localStorage > "u"))
152
+ try {
153
+ const e = localStorage.getItem(l);
154
+ e && (this.overrides = g(e));
155
+ } catch {
156
+ }
157
+ }
158
+ saveOverrides() {
159
+ if (!(typeof localStorage > "u"))
160
+ try {
161
+ localStorage.setItem(l, v(this.overrides));
162
+ } catch {
163
+ }
164
+ }
165
+ loadRecentCommands() {
166
+ if (!(typeof localStorage > "u"))
167
+ try {
168
+ const e = localStorage.getItem(h);
169
+ e && (this.recentCommandIds = JSON.parse(e));
170
+ } catch {
171
+ }
172
+ }
173
+ saveRecentCommands() {
174
+ if (!(typeof localStorage > "u"))
175
+ try {
176
+ localStorage.setItem(h, JSON.stringify(this.recentCommandIds));
177
+ } catch {
178
+ }
179
+ }
180
+ }
181
+ export {
182
+ C as ShortcutRegistry
183
+ };
@@ -0,0 +1,55 @@
1
+ import { ShortcutScope } from './utils';
2
+ /**
3
+ * ShortcutScopeProvider — Scope boundary component with instance awareness.
4
+ *
5
+ * When mounted, it pushes a scope onto the registry. When unmounted,
6
+ * it pops the scope. This allows sections of the UI to own their shortcuts.
7
+ *
8
+ * When `instance` is provided, the provider wraps its children in a
9
+ * container div that detects focus events. When anything inside the
10
+ * container receives focus (click or tab), the instance becomes "active"
11
+ * in the registry, and only that instance's commands are dispatched.
12
+ *
13
+ * Usage:
14
+ * // Basic scope (no instance — all commands fire)
15
+ * <ShortcutScopeProvider scope="module" name="planning">
16
+ * <PlanningModule />
17
+ * </ShortcutScopeProvider>
18
+ *
19
+ * // Instance-aware (for multi-table pages)
20
+ * <ShortcutScopeProvider scope="page" instance="sales-table" label="Sales Table">
21
+ * <DataTable ... />
22
+ * </ShortcutScopeProvider>
23
+ *
24
+ * <ShortcutScopeProvider scope="page" instance="inventory-table" label="Inventory Table">
25
+ * <DataTable ... />
26
+ * </ShortcutScopeProvider>
27
+ */
28
+ import * as React from 'react';
29
+ export interface ShortcutScopeProviderProps {
30
+ /** The scope level to activate */
31
+ scope: ShortcutScope;
32
+ /** Human-readable name for debugging */
33
+ name?: string;
34
+ /**
35
+ * Unique instance identifier. When provided, enables focus-based
36
+ * dispatch so that only the focused instance's commands fire.
37
+ */
38
+ instance?: string;
39
+ /**
40
+ * Human-readable label for the instance (shown in command palette
41
+ * when multiple instances are present, e.g. "Sales Table").
42
+ */
43
+ label?: string;
44
+ /** Optional className for the wrapper div (only used when instance is set) */
45
+ className?: string;
46
+ children: React.ReactNode;
47
+ }
48
+ export declare const ShortcutInstanceContext: React.Context<{
49
+ instance?: string;
50
+ label?: string;
51
+ }>;
52
+ export declare function ShortcutScopeProvider({ scope, instance, label, className, children, }: ShortcutScopeProviderProps): import("react/jsx-runtime").JSX.Element;
53
+ export declare namespace ShortcutScopeProvider {
54
+ var displayName: string;
55
+ }
@@ -0,0 +1,55 @@
1
+ import { jsx as c, Fragment as m } from "react/jsx-runtime";
2
+ import * as a from "react";
3
+ import { useCommandPalette as f } from "./command-palette-context.js";
4
+ import { cn as l } from "../../../lib/utils.js";
5
+ const d = a.createContext(null);
6
+ function v({
7
+ scope: t,
8
+ instance: e,
9
+ label: o,
10
+ className: n,
11
+ children: u
12
+ }) {
13
+ const { pushScope: r, popScope: p, setActiveInstance: s, getActiveInstance: i } = f();
14
+ return a.useEffect(() => (r(t), () => {
15
+ p(t);
16
+ }), [t, r, p]), e ? /* @__PURE__ */ c(d.Provider, { value: { instance: e, label: o }, children: /* @__PURE__ */ c(
17
+ C,
18
+ {
19
+ instance: e,
20
+ className: n,
21
+ setActiveInstance: s,
22
+ getActiveInstance: i,
23
+ children: u
24
+ }
25
+ ) }) : /* @__PURE__ */ c(m, { children: u });
26
+ }
27
+ v.displayName = "ShortcutScopeProvider";
28
+ function C({
29
+ instance: t,
30
+ className: e,
31
+ setActiveInstance: o,
32
+ getActiveInstance: n,
33
+ children: u
34
+ }) {
35
+ const r = a.useCallback(() => {
36
+ o(t);
37
+ }, [t, o]);
38
+ return a.useEffect(() => () => {
39
+ queueMicrotask(() => {
40
+ });
41
+ }, [t]), /* @__PURE__ */ c(
42
+ "div",
43
+ {
44
+ onFocusCapture: r,
45
+ onClickCapture: r,
46
+ className: l("relative", e),
47
+ "data-shortcut-instance": t,
48
+ children: u
49
+ }
50
+ );
51
+ }
52
+ export {
53
+ d as ShortcutInstanceContext,
54
+ v as ShortcutScopeProvider
55
+ };
@@ -0,0 +1,27 @@
1
+ import { ShortcutScope } from './utils';
2
+ /**
3
+ * ShortcutSettings — Keyboard shortcut customisation panel built with AG Grid.
4
+ *
5
+ * Features:
6
+ * - AG Grid with search, sort, and filter on every column
7
+ * - Source column with set filter (All / User / Browser / AG Grid / System)
8
+ * - Click keybinding cell → "recording mode" (press new keys)
9
+ * - Non-customisable rows are read-only
10
+ * - Conflict detection with inline warning
11
+ * - Reset individual overrides to defaults
12
+ * - Persists changes to localStorage immediately
13
+ */
14
+ import * as React from 'react';
15
+ export interface ShortcutSettingsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
16
+ /** Filter to specific scopes */
17
+ scopes?: ShortcutScope[];
18
+ /** Filter to specific sources */
19
+ sources?: Array<'system' | 'user' | 'ag-grid' | 'browser'>;
20
+ /** Optional render prop to hoist the recording indicator/conflict message up to a parent toolbar */
21
+ renderStatus?: (node: React.ReactNode | null) => React.ReactNode;
22
+ }
23
+ declare function ShortcutSettings({ className, scopes, sources, renderStatus, ...props }: ShortcutSettingsProps): import("react/jsx-runtime").JSX.Element;
24
+ declare namespace ShortcutSettings {
25
+ var displayName: string;
26
+ }
27
+ export { ShortcutSettings };
@@ -0,0 +1,266 @@
1
+ import { jsx as r, jsxs as h, Fragment as N } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { User as L, Monitor as F, AlertTriangle as I, Lock as R, RotateCcw as U } from "lucide-react";
4
+ import { cn as p } from "../../../lib/utils.js";
5
+ import { ModuleRegistry as _, AllCommunityModule as K } from "ag-grid-community";
6
+ import { AllEnterpriseModule as j } from "ag-grid-enterprise";
7
+ import { DataTable as z, DataTableContent as B } from "../data-table/data-table.js";
8
+ import { AG_CELL_NO_PADDING as S } from "../ag-grid-react/cell-renderers/index.js";
9
+ import { Kbd as O } from "./kbd.js";
10
+ import { useCommandPalette as $ } from "./command-palette-context.js";
11
+ import { keybindingToString as H, keybindingFromEvent as V, isReservedShortcut as W } from "./utils.js";
12
+ import { BadgeCellRenderer as q } from "../ag-grid-react/cell-renderers/badge-cell-renderer.js";
13
+ _.registerModules([K, j]);
14
+ const J = {
15
+ system: "System",
16
+ user: "User",
17
+ "ag-grid": "AG Grid",
18
+ browser: "Browser"
19
+ };
20
+ function Q(l) {
21
+ const e = l.data;
22
+ return e ? /* @__PURE__ */ h("div", { className: "flex items-center gap-2 min-w-0 h-full", children: [
23
+ !e.customisable && /* @__PURE__ */ r(R, { className: "h-3 w-3 text-[#9ca3af] shrink-0" }),
24
+ /* @__PURE__ */ h("div", { className: "flex flex-col min-w-0 gap-0", children: [
25
+ /* @__PURE__ */ r("span", { className: "truncate font-medium text-[#374151] text-xs leading-tight", children: e.command }),
26
+ e.description && /* @__PURE__ */ r("span", { className: "truncate text-[10px] text-[#9ca3af] leading-tight", children: e.description })
27
+ ] })
28
+ ] }) : null;
29
+ }
30
+ function X(l) {
31
+ const e = l.data;
32
+ if (!e) return null;
33
+ const c = l.recordingCommandId === e.id;
34
+ return /* @__PURE__ */ r("div", { className: p(
35
+ "w-full h-full flex items-center ag-cell-inner-padding",
36
+ e.customisable ? "in-ag-editable-cell-highlight" : ""
37
+ ), children: /* @__PURE__ */ r(
38
+ "div",
39
+ {
40
+ className: p(
41
+ "flex items-center justify-between w-full h-7 rounded-[8px] px-1.5 group/row relative",
42
+ e.customisable ? "bg-white" : "bg-transparent",
43
+ c && "ring-1 ring-[#4259ee] border border-[#4259ee]"
44
+ ),
45
+ children: c ? /* @__PURE__ */ r("span", { className: "text-xs text-[#4259ee] font-medium animate-pulse", children: "Press desired shortcut..." }) : /* @__PURE__ */ h(N, { children: [
46
+ e.keybinding ? /* @__PURE__ */ r(
47
+ "button",
48
+ {
49
+ onClick: (a) => {
50
+ a.stopPropagation(), e.customisable && l.onStartRecording(e.id);
51
+ },
52
+ disabled: !e.customisable,
53
+ className: p(
54
+ "flex items-center justify-end h-full w-full text-right",
55
+ e.customisable ? "cursor-pointer" : "cursor-default opacity-70"
56
+ ),
57
+ children: /* @__PURE__ */ r(O, { keybinding: e.keybinding, size: "sm" })
58
+ }
59
+ ) : e.customisable ? /* @__PURE__ */ r(
60
+ "button",
61
+ {
62
+ onClick: (a) => {
63
+ a.stopPropagation(), l.onStartRecording(e.id);
64
+ },
65
+ className: "flex items-center justify-end h-full w-full text-xs text-[#9ca3af] hover:text-[#4259ee] transition-colors cursor-pointer text-right",
66
+ children: "Add shortcut"
67
+ }
68
+ ) : /* @__PURE__ */ r("span", { className: "text-xs text-transparent", children: "--" }),
69
+ e.hasOverride && e.customisable && !c && /* @__PURE__ */ r(
70
+ "button",
71
+ {
72
+ onClick: (a) => {
73
+ a.stopPropagation(), l.onReset(e.id);
74
+ },
75
+ className: "absolute right-1 p-0.5 rounded bg-white hover:bg-[#f3f4f6] hover:text-[#ef4444] cursor-pointer opacity-0 group-hover/row:opacity-100 transition-opacity z-10",
76
+ title: "Reset to default",
77
+ children: /* @__PURE__ */ r(U, { className: "h-3 w-3" })
78
+ }
79
+ )
80
+ ] })
81
+ }
82
+ ) });
83
+ }
84
+ function Y(l) {
85
+ const e = l.data;
86
+ return e ? /* @__PURE__ */ r("div", { className: "flex items-center h-full", children: /* @__PURE__ */ r("span", { className: "text-xs text-[#6b7280] capitalize", children: e.scope }) }) : null;
87
+ }
88
+ function Z({
89
+ className: l,
90
+ scopes: e,
91
+ sources: c,
92
+ renderStatus: a,
93
+ ...k
94
+ }) {
95
+ const {
96
+ getSettingsCommands: E,
97
+ getEffectiveKeybinding: M,
98
+ updateKeybinding: g,
99
+ resetKeybinding: b,
100
+ version: A
101
+ } = $(), [o, f] = n.useState(null), [d, i] = n.useState(null), G = n.useMemo(() => {
102
+ let s = E();
103
+ return e && (s = s.filter((t) => e.includes(t.scope))), c && (s = s.filter((t) => t.source && c.includes(t.source))), s.map((t) => {
104
+ const u = M(t.id), m = t.source ?? "user", C = J[m] ?? t.source ?? "User", v = C.toLowerCase() === "user";
105
+ return {
106
+ id: t.id,
107
+ command: t.label,
108
+ description: t.description || "",
109
+ category: t.category || "General",
110
+ keybinding: u,
111
+ keybindingDisplay: u ? H(u) : "",
112
+ scope: t.scope,
113
+ source: C,
114
+ sourceColor: v ? "primary" : "neutral",
115
+ sourceIcon: v ? /* @__PURE__ */ r(L, { className: "h-3 w-3" }) : /* @__PURE__ */ r(F, { className: "h-3 w-3" }),
116
+ customisable: t.customisable !== !1,
117
+ passive: t.passive === !0,
118
+ hasOverride: t.keybinding !== void 0,
119
+ _def: t
120
+ };
121
+ });
122
+ }, [A, e, c]), x = n.useCallback((s) => {
123
+ f(s), i(null);
124
+ }, []), y = n.useCallback((s) => {
125
+ b(s), i(null);
126
+ }, [b]);
127
+ n.useEffect(() => {
128
+ if (!o) return;
129
+ const s = (t) => {
130
+ if (t.preventDefault(), t.stopPropagation(), t.key === "Escape") {
131
+ f(null), i(null);
132
+ return;
133
+ }
134
+ const u = V(t);
135
+ if (!u) return;
136
+ if (W(u)) {
137
+ i({ type: "reserved", text: "This shortcut is reserved by the browser and cannot be used" }), f(null), setTimeout(() => i(null), 3e3);
138
+ return;
139
+ }
140
+ const m = g(o, u);
141
+ m.success ? (f(null), i(null)) : m.conflict ? (i({
142
+ type: "conflict",
143
+ text: `Conflicts with "${m.conflict.conflictingLabel}" in ${m.conflict.scope} scope`
144
+ }), f(null), setTimeout(() => i(null), 3e3)) : m.reserved && (i({ type: "reserved", text: "This shortcut is reserved by the browser" }), f(null), setTimeout(() => i(null), 3e3));
145
+ };
146
+ return window.addEventListener("keydown", s, !0), () => window.removeEventListener("keydown", s, !0);
147
+ }, [o, g]);
148
+ const P = n.useMemo(() => [
149
+ {
150
+ field: "command",
151
+ headerName: "Command",
152
+ flex: 1,
153
+ minWidth: 200,
154
+ filter: "agTextColumnFilter",
155
+ cellRenderer: Q,
156
+ filterValueGetter: (s) => {
157
+ const t = s.data;
158
+ return t ? `${t.command} ${t.description}` : "";
159
+ }
160
+ },
161
+ {
162
+ field: "category",
163
+ headerName: "Category",
164
+ width: 140,
165
+ filter: "agSetColumnFilter"
166
+ },
167
+ {
168
+ field: "keybindingDisplay",
169
+ headerName: "Shortcut",
170
+ width: 180,
171
+ type: "rightAligned",
172
+ filter: "agTextColumnFilter",
173
+ cellRenderer: X,
174
+ cellClass: S,
175
+ cellRendererParams: {
176
+ recordingCommandId: o,
177
+ onStartRecording: x,
178
+ onReset: y
179
+ },
180
+ sortable: !0
181
+ },
182
+ {
183
+ field: "scope",
184
+ headerName: "Scope",
185
+ width: 100,
186
+ filter: "agSetColumnFilter",
187
+ cellRenderer: Y
188
+ },
189
+ {
190
+ field: "source",
191
+ headerName: "Source",
192
+ width: 130,
193
+ filter: "agSetColumnFilter",
194
+ cellClass: S,
195
+ cellRenderer: q,
196
+ cellRendererParams: {
197
+ variant: "subtle",
198
+ colorField: "sourceColor",
199
+ isIcon: !0,
200
+ iconField: "sourceIcon",
201
+ size: "small"
202
+ },
203
+ headerComponentParams: {
204
+ isSearchable: !0,
205
+ advanceSearchEnabled: !0,
206
+ selectOptions: [
207
+ { label: "System", value: "System" },
208
+ { label: "User", value: "User" },
209
+ { label: "AG Grid", value: "AG Grid" },
210
+ { label: "Browser", value: "Browser" }
211
+ ],
212
+ isMultiSelect: !0
213
+ }
214
+ }
215
+ ], [o, x, y]), T = n.useMemo(() => ({
216
+ filter: {
217
+ filterModel: {
218
+ source: {
219
+ filterType: "set",
220
+ values: ["System", "User", "AG Grid"]
221
+ }
222
+ }
223
+ }
224
+ }), []), D = n.useMemo(() => ({
225
+ sortable: !0,
226
+ resizable: !0,
227
+ filter: !0,
228
+ headerComponentParams: {
229
+ isSearchable: !0,
230
+ advanceSearchEnabled: !0
231
+ }
232
+ }), []), w = d || o ? /* @__PURE__ */ h("div", { className: p(
233
+ "px-3 py-1.5 text-[10px] md:text-sm font-medium rounded-md whitespace-nowrap flex items-center gap-2",
234
+ d?.type === "conflict" ? "bg-[#fef3c7] text-[#92400e]" : d?.type === "reserved" ? "bg-[#fee2e2] text-[#991b1b]" : o ? "bg-[#eff6ff] text-[#1e40af] animate-[pulse_1.5s_ease-in-out_infinite]" : ""
235
+ ), children: [
236
+ d?.type === "conflict" ? /* @__PURE__ */ r(I, { className: "h-3.5 w-3.5 shrink-0" }) : d?.type === "reserved" ? /* @__PURE__ */ r(R, { className: "h-3.5 w-3.5 shrink-0" }) : o ? /* @__PURE__ */ r("span", { className: "shrink-0 text-base", children: "⌨️" }) : null,
237
+ /* @__PURE__ */ r("span", { children: d ? d.text : /* @__PURE__ */ h(N, { children: [
238
+ /* @__PURE__ */ r("strong", { children: "Recording:" }),
239
+ " Press shortcut or ",
240
+ /* @__PURE__ */ r("strong", { children: "Esc" })
241
+ ] }) })
242
+ ] }) : null;
243
+ return /* @__PURE__ */ h(z, { className: p("flex flex-col w-full h-full border-t-0", l), ...k, children: [
244
+ a ? a(w) : w,
245
+ /* @__PURE__ */ r(
246
+ B,
247
+ {
248
+ rowData: G,
249
+ columnDefs: P,
250
+ defaultColDef: D,
251
+ initialState: T,
252
+ rowHeight: 44,
253
+ animateRows: !1,
254
+ rowSelection: "single",
255
+ suppressCellFocus: !0,
256
+ getRowId: (s) => s.data.id,
257
+ suppressRowClickSelection: !0,
258
+ domLayout: "normal"
259
+ }
260
+ )
261
+ ] });
262
+ }
263
+ Z.displayName = "ShortcutSettings";
264
+ export {
265
+ Z as ShortcutSettings
266
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * useBrowserShortcuts — Registers all browser-reserved shortcuts as passive,
3
+ * non-customisable commands so they appear in the command palette and settings
4
+ * panel. This lets users discover what shortcuts are browser-reserved and why
5
+ * they can't be overridden.
6
+ *
7
+ * Usage:
8
+ * // Show all browser shortcuts
9
+ * useBrowserShortcuts();
10
+ *
11
+ * // Hide DevTools shortcuts from the palette
12
+ * useBrowserShortcuts({ exclude: ['devtools'] });
13
+ *
14
+ * // Hide entire categories
15
+ * useBrowserShortcuts({ exclude: ['System', 'Address Bar'] });
16
+ *
17
+ * // Hide specific shortcuts by their label (partial match, case-insensitive)
18
+ * useBrowserShortcuts({ exclude: ['devtools', 'caret browsing'] });
19
+ */
20
+ export interface UseBrowserShortcutsOptions {
21
+ /**
22
+ * Patterns to exclude from the palette. Each pattern is matched against
23
+ * the shortcut's label AND category (case-insensitive, partial match).
24
+ *
25
+ * Examples:
26
+ * - `['devtools']` hides all DevTools-related shortcuts
27
+ * - `['System']` hides entire System category
28
+ * - `['devtools', 'caret browsing', 'page source']` hides specific items
29
+ */
30
+ exclude?: string[];
31
+ }
32
+ export declare function useBrowserShortcuts(options?: UseBrowserShortcutsOptions): void;
@@ -0,0 +1,48 @@
1
+ import * as u from "react";
2
+ import { useCommandPalette as f } from "./command-palette-context.js";
3
+ import { BROWSER_SHORTCUTS as d } from "./utils.js";
4
+ function m(r) {
5
+ const s = r.split("+"), e = { key: "" };
6
+ for (const t of s)
7
+ t === "meta" ? e.meta = !0 : t === "ctrl" ? e.ctrl = !0 : t === "alt" ? e.alt = !0 : t === "shift" ? e.shift = !0 : e.key = t;
8
+ return e;
9
+ }
10
+ function b(r) {
11
+ const { registerCommand: s, unregisterCommand: e } = f(), t = r?.exclude;
12
+ u.useEffect(() => {
13
+ const c = [];
14
+ for (const o of d) {
15
+ if (t?.length) {
16
+ const a = `${o.label} ${o.category}`.toLowerCase();
17
+ if (t.some(
18
+ (l) => a.includes(l.toLowerCase())
19
+ )) continue;
20
+ }
21
+ const n = `browser.${o.shortcut.replace(/\+/g, "-")}`;
22
+ c.push(n);
23
+ const i = {
24
+ id: n,
25
+ label: o.label,
26
+ description: `Browser shortcut (${o.category})`,
27
+ category: o.category,
28
+ scope: "global",
29
+ defaultKeybinding: m(o.shortcut),
30
+ customisable: !1,
31
+ hidden: !1,
32
+ handler: () => {
33
+ },
34
+ // no-op — browser handles these
35
+ source: "browser",
36
+ passive: !0
37
+ };
38
+ s(i);
39
+ }
40
+ return () => {
41
+ for (const o of c)
42
+ e(o);
43
+ };
44
+ }, [s, e, JSON.stringify(t)]);
45
+ }
46
+ export {
47
+ b as useBrowserShortcuts
48
+ };
@@ -0,0 +1,3 @@
1
+ import { UseShortcutOptions } from './use-shortcut';
2
+ export type UseGlobalShortcutOptions = Omit<UseShortcutOptions, 'scope'>;
3
+ export declare function useGlobalShortcut(options: UseGlobalShortcutOptions): void;
@@ -0,0 +1,7 @@
1
+ import { useShortcut as t } from "./use-shortcut.js";
2
+ function u(o) {
3
+ t({ ...o, scope: "global" });
4
+ }
5
+ export {
6
+ u as useGlobalShortcut
7
+ };