@keybindy/react 1.1.7 → 1.1.9

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.
@@ -1,38 +1,57 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
 
4
4
  /**
5
- * `<ShortcutLabel />` is a utility React component that visually renders a keyboard shortcut label.
6
- *
7
- * It accepts an array of keys (e.g. `["Ctrl", "S"]`) and renders a styled label using platform-aware
8
- * symbols (⌘ for Mac, Ctrl for others). Users can also provide a custom render function to override
9
- * the default display logic for advanced layouts or custom themes.
10
- *
11
- * @component
5
+ * ... (rest of the description) ...
12
6
  *
13
7
  * @example
14
8
  * // Default usage
15
9
  * <ShortcutLabel keys={['ctrl', 's']} />
16
10
  *
17
11
  * @example
18
- * // With custom renderKey
12
+ * // With multiple bindings
13
+ * <ShortcutLabel keys={[['ctrl', 's'], ['meta', 's']]} />
14
+ *
15
+ * @example
16
+ * // With custom render prop
17
+ * <ShortcutLabel
18
+ * keys={['ctrl', 'shift', 'a']}
19
+ * render={(keys) => {
20
+ * // 'keys' here will be ['ctrl', 'shift', 'a']
21
+ * return keys.map((key) => (
22
+ * <span key={key} style={{ color: '#00eaff' }}>
23
+ * {key.toUpperCase()}
24
+ * </span>
25
+ * ));
26
+ * }}
27
+ * />
28
+ *
29
+ * @example
30
+ * // With custom render prop for multiple bindings
19
31
  * <ShortcutLabel
20
- * keys={['ctrl', 'alt', 'delete']}
21
- * renderKey={(key, i, all) => (
22
- * <>
23
- * <span style={{ color: '#00eaff' }}>{key.toUpperCase()}</span>
24
- * {i < all.length - 1 && <span style={{ opacity: 0.5 }}> + </span>}
25
- * </>
26
- * )}
32
+ * keys={[['ctrl', 's'], ['meta', 's']]}
33
+ * render={(bindings) => {
34
+ * // 'bindings' here will be [['ctrl', 's'], ['meta', 's']]
35
+ * return bindings.map((binding, bindingIndex) => (
36
+ * <React.Fragment key={bindingIndex}>
37
+ * {binding.map((key, keyIndex) => (
38
+ * <span key={keyIndex} style={{ fontWeight: 'bold' }}>
39
+ * {key}
40
+ * </span>
41
+ * ))}
42
+ * {bindingIndex < bindings.length - 1 && ' or '}
43
+ * </React.Fragment>
44
+ * ));
45
+ * }}
27
46
  * />
28
47
  *
29
48
  * @param {ShortcutLabelProps} props - Props for the ShortcutLabel component
30
- * @param {string[]} props.keys - The list of keys to display.
31
- * @param {Function} [props.renderKey] - Optional custom render function for full control over how each key appears.
49
+ * @param {string[] | string[][]} props.keys - The list of keys to display.
50
+ * @param {Function} [props.render] - Optional custom render function for full control over how your keys are rendered.
32
51
  *
33
52
  * @returns {JSX.Element} Rendered shortcut label
34
53
  */
35
- const ShortcutLabel = ({ keys, renderKey, style, ...props }) => {
54
+ const ShortcutLabel = ({ keys, render, style, ...props }) => {
36
55
  const isMac = typeof navigator !== 'undefined' && /Mac/.test(navigator.userAgent);
37
56
  const defaultRenderKey = (key) => {
38
57
  switch (key.toLowerCase()) {
@@ -50,11 +69,13 @@ const ShortcutLabel = ({ keys, renderKey, style, ...props }) => {
50
69
  return key.toUpperCase();
51
70
  }
52
71
  };
53
- const rendered = renderKey
54
- ? keys.map((key, i) => (jsx(React.Fragment, { children: renderKey(key, i, keys) }, i)))
55
- : defaultRenderKey
56
- ? [keys.map(key => defaultRenderKey(key)).join(' + ')]
57
- : [];
72
+ const renderBinding = (binding) => {
73
+ if (render) {
74
+ return render(binding);
75
+ }
76
+ return binding.map(key => defaultRenderKey(key)).join(' + ');
77
+ };
78
+ const isNestedArray = Array.isArray(keys[0]);
58
79
  return (jsx("kbd", { style: {
59
80
  fontFamily: 'monospace',
60
81
  padding: '2.5px 5px',
@@ -63,7 +84,11 @@ const ShortcutLabel = ({ keys, renderKey, style, ...props }) => {
63
84
  borderRadius: '4px',
64
85
  userSelect: 'none',
65
86
  ...style,
66
- }, ...props, children: rendered }));
87
+ }, ...props, children: isNestedArray
88
+ ? render
89
+ ? renderBinding(keys)
90
+ : keys.map((binding, index) => (jsxs(React.Fragment, { children: [renderBinding(binding), index < keys.length - 1 && ' / '] }, index)))
91
+ : renderBinding(keys) }));
67
92
  };
68
93
 
69
94
  export { ShortcutLabel };
package/dist/index.d.ts CHANGED
@@ -56,60 +56,70 @@ type KeybindyProps = {
56
56
  };
57
57
  declare const Keybindy: React.NamedExoticComponent<KeybindyProps>;
58
58
 
59
+ type AllowedKeys = Omit<Keys, 'Ctrl (Left)' | 'Ctrl (Right)' | 'Shift (Left)' | 'Shift (Right)' | 'Alt (Left)' | 'Alt (Right)' | 'Meta (Left)' | 'Meta (Right)'>;
59
60
  interface ShortcutLabelProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
60
61
  /**
61
- * Array of keys to display
62
+ * Array of keys to display. Can be a single binding `['Ctrl', 'S']` or multiple bindings `[['Ctrl', 'S'], ['Cmd', 'S']]`.
62
63
  */
63
- keys: Omit<Keys, 'Ctrl (Left)' | 'Ctrl (Right)' | 'Shift (Left)' | 'Shift (Right)' | 'Alt (Left)' | 'Alt (Right)' | 'Meta (Left)' | 'Meta (Right)'>[];
64
+ keys: AllowedKeys[] | AllowedKeys[][];
64
65
  /**
65
- * Custom render function for each key
66
+ * Custom render function for full control over how your keys are rendered.
67
+ * This function receives the entire `keys` array (either `string[]` or `string[][]`)
68
+ * and should return the ReactNode to be displayed.
66
69
  */
67
- renderKey?: (
68
- /**
69
- * The key to render
70
- */
71
- key: string,
72
- /**
73
- * The index of the key in the array
74
- */
75
- index: number,
76
- /**
77
- * All keys in the array
78
- */
79
- allKeys: string[]) => React.ReactNode;
70
+ render?: (keys: AllowedKeys[] | AllowedKeys[][]) => React.ReactNode;
80
71
  }
81
72
  /**
82
- * `<ShortcutLabel />` is a utility React component that visually renders a keyboard shortcut label.
83
- *
84
- * It accepts an array of keys (e.g. `["Ctrl", "S"]`) and renders a styled label using platform-aware
85
- * symbols (⌘ for Mac, Ctrl for others). Users can also provide a custom render function to override
86
- * the default display logic for advanced layouts or custom themes.
87
- *
88
- * @component
73
+ * ... (rest of the description) ...
89
74
  *
90
75
  * @example
91
76
  * // Default usage
92
77
  * <ShortcutLabel keys={['ctrl', 's']} />
93
78
  *
94
79
  * @example
95
- * // With custom renderKey
80
+ * // With multiple bindings
81
+ * <ShortcutLabel keys={[['ctrl', 's'], ['meta', 's']]} />
82
+ *
83
+ * @example
84
+ * // With custom render prop
85
+ * <ShortcutLabel
86
+ * keys={['ctrl', 'shift', 'a']}
87
+ * render={(keys) => {
88
+ * // 'keys' here will be ['ctrl', 'shift', 'a']
89
+ * return keys.map((key) => (
90
+ * <span key={key} style={{ color: '#00eaff' }}>
91
+ * {key.toUpperCase()}
92
+ * </span>
93
+ * ));
94
+ * }}
95
+ * />
96
+ *
97
+ * @example
98
+ * // With custom render prop for multiple bindings
96
99
  * <ShortcutLabel
97
- * keys={['ctrl', 'alt', 'delete']}
98
- * renderKey={(key, i, all) => (
99
- * <>
100
- * <span style={{ color: '#00eaff' }}>{key.toUpperCase()}</span>
101
- * {i < all.length - 1 && <span style={{ opacity: 0.5 }}> + </span>}
102
- * </>
103
- * )}
100
+ * keys={[['ctrl', 's'], ['meta', 's']]}
101
+ * render={(bindings) => {
102
+ * // 'bindings' here will be [['ctrl', 's'], ['meta', 's']]
103
+ * return bindings.map((binding, bindingIndex) => (
104
+ * <React.Fragment key={bindingIndex}>
105
+ * {binding.map((key, keyIndex) => (
106
+ * <span key={keyIndex} style={{ fontWeight: 'bold' }}>
107
+ * {key}
108
+ * </span>
109
+ * ))}
110
+ * {bindingIndex < bindings.length - 1 && ' or '}
111
+ * </React.Fragment>
112
+ * ));
113
+ * }}
104
114
  * />
105
115
  *
106
116
  * @param {ShortcutLabelProps} props - Props for the ShortcutLabel component
107
- * @param {string[]} props.keys - The list of keys to display.
108
- * @param {Function} [props.renderKey] - Optional custom render function for full control over how each key appears.
117
+ * @param {string[] | string[][]} props.keys - The list of keys to display.
118
+ * @param {Function} [props.render] - Optional custom render function for full control over how your keys are rendered.
109
119
  *
110
120
  * @returns {JSX.Element} Rendered shortcut label
111
121
  */
112
- declare const ShortcutLabel: ({ keys, renderKey, style, ...props }: ShortcutLabelProps) => react_jsx_runtime.JSX.Element;
122
+ declare const ShortcutLabel: ({ keys, render, style, ...props }: ShortcutLabelProps) => react_jsx_runtime.JSX.Element;
113
123
 
114
124
  type UseKeybindyReturn = {
115
125
  register: (keys: Keys[] | Keys[][], handler: ShortcutHandler, options?: ShortcutOptions) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keybindy/react",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "Keybindy for React: Simple, scoped keyboard shortcuts that require little setup. designed to smoothly blend in with your React applications, allowing for robust keybinding functionality without the overhead.",
5
5
  "author": {
6
6
  "name": "PRASSamin",