@witchcraft/spellcraft 0.2.0 → 0.2.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.
@@ -51,7 +51,7 @@ export function createManager(rawManager, additionalOpts = {}) {
51
51
  if (!shortcuts || isArray(shortcuts)) {
52
52
  castType(shortcuts);
53
53
  const shortcutsList = [];
54
- const m2 = { ...m, commands, keys };
54
+ const m2 = { ...m, commands, keys, context: rawManager.context };
55
55
  if (shortcuts) {
56
56
  for (const shortcut of shortcuts) {
57
57
  const res2 = createShortcut(shortcut, m2);
@@ -62,7 +62,8 @@ export function createManager(rawManager, additionalOpts = {}) {
62
62
  const res = createShortcuts(shortcutsList, {
63
63
  keys,
64
64
  commands,
65
- options
65
+ options,
66
+ context: rawManager.context
66
67
  }, additionalOpts?.shortcuts);
67
68
  if (res.isError) return res;
68
69
  shortcuts = res.value;
@@ -6,7 +6,7 @@ import type { CanHookErrors, Manager, MultipleErrors, PickManager, Shortcut, Sho
6
6
  * Creates a set of shortcuts.
7
7
  *
8
8
  */
9
- export declare function createShortcuts<THooks extends Manager["hooks"], TRawShortcuts extends Shortcut[], TCheck extends boolean | "only" = true>(shortcutsList: TRawShortcuts, manager: Pick<Manager, "keys" | "commands"> & PickManager<"options", "evaluateCondition" | "conditionEquals" | "stringifier" | "sorter" | "shortcutEqualityStrategy"> & {
9
+ export declare function createShortcuts<THooks extends Manager["hooks"], TRawShortcuts extends Shortcut[], TCheck extends boolean | "only" = true>(shortcutsList: TRawShortcuts, manager: Pick<Manager, "keys" | "commands" | "context"> & PickManager<"options", "evaluateCondition" | "conditionEquals" | "stringifier" | "sorter" | "shortcutEqualityStrategy"> & {
10
10
  hooks?: THooks;
11
11
  }, opts?: Partial<Pick<Shortcuts, "ignoreModifierConflicts" | "ignoreChainConflicts">>, { check }?: {
12
12
  check?: boolean | "only";
@@ -16,15 +16,27 @@ export function doesShortcutConflict(shortcutA, shortcutB, manager) {
16
16
  if (equalsShortcut(shortcutA, shortcutB, manager)) return true;
17
17
  const evaluateCondition = manager.options.evaluateCondition;
18
18
  const conditionEquals = manager.options.conditionEquals;
19
+ const commandA = shortcutA.command ? manager.commands.entries[shortcutA.command] : void 0;
20
+ const commandB = shortcutB.command ? manager.commands.entries[shortcutB.command] : void 0;
21
+ if ((shortcutA.condition || shortcutB.condition || commandA?.condition || commandB?.condition) && context === void 0) {
22
+ console.warn("Condition comparisons will not work without a context (the base conditionComparer is still used).");
23
+ }
19
24
  if (context) {
20
25
  if (shortcutA.condition && shortcutB.condition) {
21
26
  const shortcutCondition = evaluateCondition(shortcutA.condition, context);
22
27
  const otherCondition = evaluateCondition(shortcutB.condition, context);
23
- if (shortcutCondition !== otherCondition) return false;
24
- if (!shortcutCondition) return false;
28
+ if (!shortcutCondition || shortcutCondition !== otherCondition) return false;
29
+ }
30
+ if (commandA?.condition && commandB?.condition) {
31
+ const commandCondition = evaluateCondition(commandA.condition, context);
32
+ const otherCondition = evaluateCondition(commandB.condition, context);
33
+ if (!commandCondition || commandCondition !== otherCondition) return false;
25
34
  }
26
35
  } else {
27
36
  if (!conditionEquals(shortcutA.condition, shortcutB.condition, "shortcut")) return false;
37
+ if (commandA?.condition && commandB?.condition) {
38
+ if (!conditionEquals(commandA?.condition, commandB?.condition, "command")) return false;
39
+ }
28
40
  }
29
41
  const { keys } = manager;
30
42
  if (shortcutA.chain.length === 0 || shortcutB.chain.length === 0) {
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "witchcraftSpellcraft",
3
3
  "configKey": "witchcraftSpellcraft",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -2,4 +2,4 @@ import type { PickManager } from "../../types/general.js";
2
2
  import type { Manager } from "../../types/manager.js";
3
3
  import type { Shortcut } from "../../types/shortcuts.js";
4
4
  /** Turns a shortcut into an id to use in a v-for loop. */
5
- export declare const shortcutToId: (shortcut: Shortcut, manager: PickManager<"options", "stringifier"> & Pick<Manager, "keys">) => string;
5
+ export declare function shortcutToId(shortcut: Shortcut, manager: PickManager<"options", "stringifier"> & Pick<Manager, "keys">): string;
@@ -1,6 +1,8 @@
1
- export const shortcutToId = (shortcut, manager) => [
2
- shortcut.enabled,
3
- manager.options.stringifier.stringify(shortcut.chain, manager),
4
- shortcut.command ?? "",
5
- shortcut.condition.text
6
- ].join("--");
1
+ export function shortcutToId(shortcut, manager) {
2
+ return [
3
+ shortcut.enabled,
4
+ manager.options.stringifier.stringify(shortcut.chain, manager),
5
+ shortcut.command ?? "",
6
+ shortcut.condition.text
7
+ ].join("--");
8
+ }
@@ -124,8 +124,9 @@ export type Manager<THooks extends Partial<Hooks> = Partial<Hooks>, TKeys extend
124
124
  *
125
125
  * - `ignoreCommand` (default) will ignore both shortcuts' commands. If everything else is equal, they are considered equal.
126
126
  * - `ignoreCommandWithDifferentCondition` will ignore both commands' names and only compare their conditions. If everything else is equal, they are considered equal. Use it if you allow command conditions to equal eachother. See {@link ConditionComparer} for details.
127
- * - `all` will compare everything.
127
+ * - `all` will compare everything. Useful for finding an exact shortcut match. Should not be used when comparing shortcuts to find conflicts as it will allow shortcuts with the same chain but different commands to not be equal.
128
128
  *
129
+ * Note that regardless of this setting shortcut conflicts can arise for other reasons due to `doesShortcutConflict` which checks other conditions.
129
130
  */
130
131
  shortcutEqualityStrategy: "ignoreCommand" | "ignoreCommandWithDifferentCondition" | "all";
131
132
  /** Determines how conditions are evaluated. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@witchcraft/spellcraft",
3
3
  "description": "A shortcut manager library for handling ALL the shortcut needs of an application.",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "type": "module",
6
6
  "main": "./dist/core/index.js",
7
7
  "sideEffects": false,
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@witchcraft/expressit": "^0.4.2",
43
- "@witchcraft/ui": "^0.3.20"
43
+ "@witchcraft/ui": "^0.3.24"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "@witchcraft/ui": {
@@ -53,7 +53,7 @@
53
53
  "dependencies": {
54
54
  "@alanscodelog/utils": "^6.0.2",
55
55
  "@witchcraft/expressit": "^0.4.2",
56
- "@witchcraft/ui": "^0.3.20",
56
+ "@witchcraft/ui": "^0.3.24",
57
57
  "reka-ui": "^2.8.0",
58
58
  "vue": "^3.5.27"
59
59
  },
@@ -175,7 +175,7 @@ export function createManager<
175
175
  if (!shortcuts || isArray(shortcuts)) {
176
176
  castType<RawShortcut[]>(shortcuts)
177
177
  const shortcutsList: Shortcut[] = []
178
- const m2 = { ...m, commands: commands as Commands, keys: keys as Keys }
178
+ const m2 = { ...m, commands: commands as Commands, keys: keys as Keys, context: rawManager.context! }
179
179
  if (shortcuts) {
180
180
  for (const shortcut of shortcuts) {
181
181
  const res = createShortcut(shortcut, m2)
@@ -187,7 +187,8 @@ export function createManager<
187
187
  const res = createShortcuts(shortcutsList, {
188
188
  keys: keys! as Keys,
189
189
  commands: commands! as Commands,
190
- options
190
+ options,
191
+ context: rawManager.context!
191
192
  }, additionalOpts?.shortcuts)
192
193
  if (res.isError) return res as any
193
194
  shortcuts = res.value satisfies Shortcuts as any
@@ -16,7 +16,7 @@ export function createShortcuts<
16
16
  TCheck extends boolean | "only" = true
17
17
  >(
18
18
  shortcutsList: TRawShortcuts,
19
- manager: Pick<Manager, "keys" | "commands">
19
+ manager: Pick<Manager, "keys" | "commands" | "context">
20
20
  & PickManager<"options", | "evaluateCondition" | "conditionEquals" | "stringifier" | "sorter" | "shortcutEqualityStrategy">
21
21
  & { hooks?: THooks },
22
22
  opts?: Partial<Pick<Shortcuts, "ignoreModifierConflicts" | "ignoreChainConflicts">>,
@@ -39,15 +39,30 @@ export function doesShortcutConflict<TShortcut extends Shortcut>(
39
39
  if (equalsShortcut(shortcutA, shortcutB, manager)) return true
40
40
  const evaluateCondition = manager.options.evaluateCondition
41
41
  const conditionEquals = manager.options.conditionEquals
42
+
43
+ const commandA = shortcutA.command ? manager.commands.entries[shortcutA.command] : undefined
44
+ const commandB = shortcutB.command ? manager.commands.entries[shortcutB.command] : undefined
45
+
46
+ if ((shortcutA.condition || shortcutB.condition || commandA?.condition || commandB?.condition) && context === undefined) {
47
+ // eslint-disable-next-line no-console
48
+ console.warn("Condition comparisons will not work without a context (the base conditionComparer is still used).")
49
+ }
42
50
  if (context) {
43
51
  if (shortcutA.condition && shortcutB.condition) {
44
52
  const shortcutCondition = evaluateCondition(shortcutA.condition, context)
45
53
  const otherCondition = evaluateCondition(shortcutB.condition, context)
46
- if (shortcutCondition !== otherCondition) return false
47
- if (!shortcutCondition) return false
54
+ if (!shortcutCondition || shortcutCondition !== otherCondition) return false
55
+ }
56
+ if (commandA?.condition && commandB?.condition) {
57
+ const commandCondition = evaluateCondition(commandA.condition, context)
58
+ const otherCondition = evaluateCondition(commandB.condition, context)
59
+ if (!commandCondition || commandCondition !== otherCondition) return false
48
60
  }
49
61
  } else {
50
62
  if (!conditionEquals(shortcutA.condition, shortcutB.condition, "shortcut")) return false
63
+ if (commandA?.condition && commandB?.condition) {
64
+ if (!conditionEquals(commandA?.condition, commandB?.condition, "command")) return false
65
+ }
51
66
  }
52
67
  const { keys } = manager
53
68
  // an empty chain is always in conflict ?
@@ -3,12 +3,14 @@ import type { Manager } from "../../types/manager.js"
3
3
  import type { Shortcut } from "../../types/shortcuts.js"
4
4
 
5
5
  /** Turns a shortcut into an id to use in a v-for loop. */
6
- export const shortcutToId = (
6
+ export function shortcutToId(
7
7
  shortcut: Shortcut,
8
8
  manager: PickManager<"options", "stringifier"> & Pick<Manager, "keys">
9
- ): string => [
10
- shortcut.enabled,
11
- manager.options.stringifier.stringify(shortcut.chain, manager),
12
- shortcut.command ?? "",
13
- shortcut.condition.text
14
- ].join("--")
9
+ ): string {
10
+ return [
11
+ shortcut.enabled,
12
+ manager.options.stringifier.stringify(shortcut.chain, manager),
13
+ shortcut.command ?? "",
14
+ shortcut.condition.text
15
+ ].join("--")
16
+ }
@@ -222,8 +222,9 @@ export type Manager<
222
222
  *
223
223
  * - `ignoreCommand` (default) will ignore both shortcuts' commands. If everything else is equal, they are considered equal.
224
224
  * - `ignoreCommandWithDifferentCondition` will ignore both commands' names and only compare their conditions. If everything else is equal, they are considered equal. Use it if you allow command conditions to equal eachother. See {@link ConditionComparer} for details.
225
- * - `all` will compare everything.
225
+ * - `all` will compare everything. Useful for finding an exact shortcut match. Should not be used when comparing shortcuts to find conflicts as it will allow shortcuts with the same chain but different commands to not be equal.
226
226
  *
227
+ * Note that regardless of this setting shortcut conflicts can arise for other reasons due to `doesShortcutConflict` which checks other conditions.
227
228
  */
228
229
  shortcutEqualityStrategy: "ignoreCommand" | "ignoreCommandWithDifferentCondition" | "all"
229
230