@rokkit/actions 1.0.0-next.112 → 1.0.0-next.114

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/actions",
3
- "version": "1.0.0-next.112",
3
+ "version": "1.0.0-next.114",
4
4
  "description": "Contains generic actions that can be used in various components.",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
package/src/kbd.js ADDED
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Gets horizontal movement actions based on text direction
3
+ * @param {Object} handlers - Handler functions
4
+ * @param {string} [dir='ltr'] - Text direction ('ltr' or 'rtl')
5
+ * @returns {Object} Object mapping arrow keys to movement handlers
6
+ */
7
+ function getHorizontalMovementActions(handlers, dir = 'ltr') {
8
+ return dir === 'rtl'
9
+ ? { ArrowRight: handlers.previous, ArrowLeft: handlers.next }
10
+ : { ArrowLeft: handlers.previous, ArrowRight: handlers.next }
11
+ }
12
+
13
+ /**
14
+ * Gets vertical movement actions (not affected by direction)
15
+ * @param {Object} handlers - Handler functions
16
+ * @returns {Object} Object mapping arrow keys to movement handlers
17
+ */
18
+ function getVerticalMovementActions(handlers) {
19
+ return { ArrowUp: handlers.previous, ArrowDown: handlers.next }
20
+ }
21
+
22
+ /**
23
+ * Gets horizontal expand/collapse actions (not affected by direction)
24
+ * @param {Object} handlers - Handler functions
25
+ * @returns {Object} Object mapping arrow keys to expand/collapse handlers
26
+ */
27
+ function getHorizontalExpandActions(handlers) {
28
+ return { ArrowUp: handlers.collapse, ArrowDown: handlers.expand }
29
+ }
30
+
31
+ /**
32
+ * Gets vertical expand/collapse actions based on text direction
33
+ * @param {Object} handlers - Handler functions
34
+ * @param {string} [dir='ltr'] - Text direction ('ltr' or 'rtl')
35
+ * @returns {Object} Object mapping arrow keys to expand/collapse handlers
36
+ */
37
+ function getVerticalExpandActions(handlers, dir = 'ltr') {
38
+ return dir === 'rtl'
39
+ ? { ArrowRight: handlers.collapse, ArrowLeft: handlers.expand }
40
+ : { ArrowLeft: handlers.collapse, ArrowRight: handlers.expand }
41
+ }
42
+
43
+ /**
44
+ * Gets common selection actions
45
+ * @param {Object} handlers - Handler functions
46
+ * @returns {Object} Object mapping keys to selection handlers
47
+ */
48
+ function getCommonActions(handlers) {
49
+ return {
50
+ Enter: handlers.select,
51
+ ' ': handlers.select
52
+ }
53
+ }
54
+
55
+ // Default navigation options
56
+ export const defaultNavigationOptions = {
57
+ orientation: 'vertical',
58
+ dir: 'ltr',
59
+ nested: false,
60
+ enabled: true
61
+ }
62
+
63
+ /**
64
+ * Gets keyboard action handlers based on orientation and direction
65
+ * @param {Object} options - Configuration options
66
+ * @param {Object} handlers - Event handler functions
67
+ * @returns {Object} Object mapping key presses to handler functions
68
+ */
69
+ export function getKeyboardActions(options, handlers) {
70
+ const { orientation, dir, nested, enabled } = { ...defaultNavigationOptions, ...options }
71
+
72
+ if (!enabled) return {}
73
+
74
+ const common = getCommonActions(handlers)
75
+
76
+ // Determine movement actions based on orientation
77
+ const isHorizontal = orientation === 'horizontal'
78
+ const movement = isHorizontal
79
+ ? getHorizontalMovementActions(handlers, dir)
80
+ : getVerticalMovementActions(handlers)
81
+
82
+ // If not nested, we don't need expand/collapse actions
83
+ if (!nested) {
84
+ return { ...common, ...movement }
85
+ }
86
+
87
+ // Determine expand/collapse actions based on orientation
88
+ const expandCollapse = isHorizontal
89
+ ? getHorizontalExpandActions(handlers)
90
+ : getVerticalExpandActions(handlers, dir)
91
+
92
+ return { ...common, ...movement, ...expandCollapse }
93
+ }
94
+
95
+ /**
96
+ * Creates a keyboard action mapping based on navigation options
97
+ *
98
+ * @param {Object} options - Navigation options
99
+ * @param {string} options.orientation - Whether navigation is horizontal or vertical
100
+ * @param {string} options.dir - Text direction ('ltr' or 'rtl')
101
+ * @param {boolean} options.nested - Whether navigation is nested
102
+ * @returns {Object} Mapping of keys to actions
103
+ */
104
+ export function createKeyboardActionMap(options) {
105
+ const { orientation, dir, nested } = options
106
+ const isHorizontal = orientation === 'horizontal'
107
+
108
+ // Define movement actions based on orientation and direction
109
+ let movementActions = {}
110
+ if (isHorizontal) {
111
+ movementActions = dir === 'rtl'
112
+ ? { ArrowRight: 'previous', ArrowLeft: 'next' }
113
+ : { ArrowLeft: 'previous', ArrowRight: 'next' }
114
+ } else {
115
+ movementActions = { ArrowUp: 'previous', ArrowDown: 'next' }
116
+ }
117
+
118
+ // Define expand/collapse actions for nested option
119
+ let nestedActions = {}
120
+ if (nested) {
121
+ if (isHorizontal) {
122
+ nestedActions = { ArrowUp: 'collapse', ArrowDown: 'expand' }
123
+ } else {
124
+ nestedActions = dir === 'rtl'
125
+ ? { ArrowRight: 'collapse', ArrowLeft: 'expand' }
126
+ : { ArrowLeft: 'collapse', ArrowRight: 'expand' }
127
+ }
128
+ }
129
+
130
+ // Common actions regardless of options
131
+ const commonActions = {
132
+ Enter: 'select',
133
+ ' ': 'select',
134
+ Home: 'first',
135
+ End: 'last'
136
+ }
137
+
138
+ // Combine all possible actions
139
+ return {
140
+ ...commonActions,
141
+ ...movementActions,
142
+ ...nestedActions
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Creates a keyboard action mapping for modifier keys based on navigation options
148
+ *
149
+ * @param {Object} options - Navigation options
150
+ * @param {string} options.orientation - Whether navigation is horizontal or vertical
151
+ * @returns {Object} Mapping of keys to actions
152
+ */
153
+ export function createModifierKeyboardActionMap(options) {
154
+ const isHorizontal = options.orientation === 'horizontal'
155
+ const common = { ' ': 'extend', Home: 'first', End: 'last' }
156
+ const directional = isHorizontal
157
+ ? { ArrowLeft: 'first', ArrowRight: 'last' }
158
+ : { ArrowUp: 'first', ArrowDown: 'last' }
159
+ return { ...common, ...directional }
160
+ }
161
+
162
+ /**
163
+ * Gets the keyboard action for a key event
164
+ * @param {KeyboardEvent} event - The keyboard event
165
+ * @param {Object} options - Configuration options
166
+ * @returns {string|null} The action to perform, or null if no action is defined
167
+ */
168
+ export function getKeyboardAction(event, options = {}) {
169
+ const { key, ctrlKey, metaKey } = event
170
+
171
+ // Use updated options with defaults
172
+ const mergedOptions = { ...defaultNavigationOptions, ...options }
173
+
174
+ // Check for modifier keys first (highest priority)
175
+ if (ctrlKey || metaKey) {
176
+ const modifierMap = createModifierKeyboardActionMap(mergedOptions)
177
+ return modifierMap[key] || null
178
+ }
179
+
180
+ // Get the action map based on options
181
+ const actionMap = createKeyboardActionMap(mergedOptions)
182
+
183
+ // Return the action or null if no matching key
184
+ return actionMap[key] || null
185
+ }
@@ -1,7 +1,14 @@
1
1
  import { on } from 'svelte/events'
2
- import { handleAction, getKeyboardActions } from './utils'
2
+ import { getKeyboardActions, defaultNavigationOptions } from './kbd'
3
3
 
4
- const defaultOptions = { horizontal: true, nested: false, enabled: true }
4
+ // Handle keyboard events
5
+ function handleAction(actions, event) {
6
+ if (event.key in actions) {
7
+ event.preventDefault()
8
+ event.stopPropagation()
9
+ actions[event.key]()
10
+ }
11
+ }
5
12
  /**
6
13
  * A svelte action function that captures keyboard evvents and emits event for corresponding movements.
7
14
  *
@@ -22,8 +29,10 @@ export function navigable(node, options) {
22
29
  const handleKeydown = (event) => handleAction(actions, event)
23
30
 
24
31
  $effect(() => {
25
- const props = { ...defaultOptions, ...options }
32
+ // Use defaultNavigationOptions from kbd.js
33
+ const props = { ...defaultNavigationOptions, ...options }
26
34
  actions = getKeyboardActions(props, handlers)
35
+
27
36
  const cleanup = on(node, 'keyup', handleKeydown)
28
37
 
29
38
  return () => cleanup()
@@ -1,8 +1,7 @@
1
1
  import { on } from 'svelte/events'
2
2
  import { omit } from 'ramda'
3
- import { getClickAction, getKeyboardAction, getPathFromEvent } from './utils'
4
-
5
- const defaultOptions = { horizontal: false, nested: false, enabled: true }
3
+ import { getKeyboardAction, defaultNavigationOptions } from './kbd'
4
+ import { getClickAction, getPathFromEvent } from './utils'
6
5
 
7
6
  const EVENT_MAP = {
8
7
  first: ['move'],
@@ -79,7 +78,7 @@ function getHandlers(wrapper) {
79
78
  */
80
79
  export function navigator(node, options) {
81
80
  const { wrapper } = options
82
- const config = { ...defaultOptions, ...omit(['wrapper'], options) }
81
+ const config = { ...defaultNavigationOptions, ...omit(['wrapper'], options) }
83
82
  const handlers = getHandlers(wrapper)
84
83
 
85
84
  const handleKeydown = (event) => {
package/src/utils.js CHANGED
@@ -1,5 +1,11 @@
1
1
  import { find, toPairs } from 'ramda'
2
2
 
3
+ const defaultNavigationOptions = {
4
+ orientation: 'vertical',
5
+ dir: 'ltr',
6
+ nested: false,
7
+ enabled: true
8
+ }
3
9
  /**
4
10
  * Finds the closest ancestor of the given element that has the given attribute.
5
11
  *
@@ -42,30 +48,31 @@ export function handleAction(actions, event) {
42
48
  }
43
49
  }
44
50
 
45
- /**
46
- * Maps keys to actions based on the configuration.
47
- *
48
- * @param {import('./types').NavigableOptions} options
49
- * @param {import('./types').NavigableHandlers} handlers
50
- */
51
- export function getKeyboardActions(options, handlers) {
52
- const { horizontal, nested } = options
53
- if (!options.enabled) return {}
54
-
55
- const common = {
56
- Enter: handlers.select,
57
- ' ': handlers.select
58
- }
59
- const movement = horizontal
60
- ? { ArrowLeft: handlers.previous, ArrowRight: handlers.next }
61
- : { ArrowUp: handlers.previous, ArrowDown: handlers.next }
62
- const change = horizontal
63
- ? { ArrowUp: handlers.collapse, ArrowDown: handlers.expand }
64
- : { ArrowLeft: handlers.collapse, ArrowRight: handlers.expand }
65
-
66
- if (nested) return { ...common, ...movement, ...change }
67
- return { ...common, ...movement }
68
- }
51
+ // /**
52
+ // * Maps keys to actions based on the configuration.
53
+ // *
54
+ // * @param {import('./types').NavigableOptions} options
55
+ // * @param {import('./types').NavigableHandlers} handlers
56
+ // */
57
+ // export function getKeyboardActions(options, handlers) {
58
+ // const { horizontal, nested } = options
59
+ // if (!options.enabled) return {}
60
+
61
+ // const common = {
62
+ // Enter: handlers.select,
63
+ // ' ': handlers.select
64
+ // }
65
+ // const movement = horizontal
66
+ // ? { ArrowLeft: handlers.previous, ArrowRight: handlers.next }
67
+ // : { ArrowUp: handlers.previous, ArrowDown: handlers.next }
68
+ // const change = horizontal
69
+ // ? { ArrowUp: handlers.collapse, ArrowDown: handlers.expand }
70
+ // : { ArrowLeft: handlers.collapse, ArrowRight: handlers.expand }
71
+
72
+ // if (nested) return { ...common, ...movement, ...change }
73
+ // return { ...common, ...movement }
74
+ // }
75
+ // Keyboard related functions moved to kbd.js
69
76
 
70
77
  /**
71
78
  * Finds and returns an index path based on data-path attribute
@@ -79,61 +86,9 @@ export function getPathFromEvent(event) {
79
86
  // return node ? getPathFromKey(node.getAttribute('data-path')) : null
80
87
  }
81
88
 
82
- /**
83
- * Creates a keyboard action mapping based on navigation options
84
- *
85
- * @param {Object} options - Navigation options
86
- * @param {boolean} options.horizontal - Whether navigation is horizontal
87
- * @param {boolean} options.nested - Whether navigation is nested
88
- * @returns {Object} Mapping of keys to actions
89
- */
90
- function createKeyboardActionMap(options) {
91
- const { horizontal, nested } = options
92
-
93
- // Define movement actions based on horizontal option
94
- const movementActions = horizontal
95
- ? { ArrowLeft: 'previous', ArrowRight: 'next' }
96
- : { ArrowUp: 'previous', ArrowDown: 'next' }
97
-
98
- // Define expand/collapse actions for nested option
99
- const nestedActions = nested
100
- ? horizontal
101
- ? { ArrowUp: 'collapse', ArrowDown: 'expand' }
102
- : { ArrowLeft: 'collapse', ArrowRight: 'expand' }
103
- : {}
104
-
105
- // Common actions regardless of options
106
- const commonActions = {
107
- Enter: 'select',
108
- ' ': 'select',
109
- Home: 'first',
110
- End: 'last'
111
- }
112
-
113
- // Combine all possible actions
114
- return {
115
- ...commonActions,
116
- ...movementActions,
117
- ...nestedActions
118
- }
119
- }
89
+ // createKeyboardActionMap moved to kbd.js
120
90
 
121
- /**
122
- * Creates a keyboard action mapping based on navigation options
123
- *
124
- * @param {Object} options - Navigation options
125
- * @param {boolean} options.horizontal - Whether navigation is horizontal
126
- * @param {boolean} options.nested - Whether navigation is nested
127
- * @returns {Object} Mapping of keys to actions
128
- */
129
- function createModifierKeyboardActionMap(options) {
130
- const { horizontal } = options
131
- const common = { ' ': 'extend', Home: 'first', End: 'last' }
132
- const directional = horizontal
133
- ? { ArrowLeft: 'first', ArrowRight: 'last' }
134
- : { ArrowUp: 'first', ArrowDown: 'last' }
135
- return { ...common, ...directional }
136
- }
91
+ // createModifierKeyboardActionMap moved to kbd.js
137
92
  /**
138
93
  * Identifies if an element is a collapsible icon
139
94
  * @param {HTMLElement} target
@@ -142,34 +97,11 @@ function createModifierKeyboardActionMap(options) {
142
97
  function isNodeToggle(target) {
143
98
  return (
144
99
  target &&
145
- target.getAttribute('data-tag') === 'icon' &&
100
+ target.hasAttribute('data-tag-icon') &&
146
101
  ['closed', 'opened'].includes(target.getAttribute('data-state'))
147
102
  )
148
103
  }
149
- /**
150
- * Determines an action based on a keyboard event and navigation options
151
- *
152
- * @param {KeyboardEvent} event - The keyboard event
153
- * @param {Object} options - Navigation options
154
- * @param {boolean} options.horizontal - Whether navigation is horizontal
155
- * @param {boolean} options.nested - Whether navigation is nested
156
- * @returns {string|null} The determined action or null if no action matches
157
- */
158
- export const getKeyboardAction = (event, options) => {
159
- const { key, ctrlKey, metaKey } = event
160
-
161
- // Check for modifier keys first (highest priority)
162
- if (ctrlKey || metaKey) {
163
- const modifierMap = createModifierKeyboardActionMap(options)
164
- return modifierMap[key] || null
165
- }
166
-
167
- // Get the action map based on options
168
- const actionMap = createKeyboardActionMap(options)
169
-
170
- // Return the action or null if no matching key
171
- return actionMap[key] || null
172
- }
104
+ // getKeyboardAction moved to kbd.js
173
105
 
174
106
  /**
175
107
  * Determines an action based on a click event