@rokkit/actions 1.0.0-next.35 → 1.0.0-next.37
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 +9 -8
- package/src/dismissable.js +10 -1
- package/src/fillable.js +10 -16
- package/src/hierarchy.js +28 -18
- package/src/index.js +1 -0
- package/src/navigable.js +7 -0
- package/src/navigator.js +72 -60
- package/src/pannable.js +2 -3
- package/src/swipeable.js +8 -0
- package/src/themeable.js +18 -9
- package/src/types.js +53 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rokkit/actions",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.37",
|
|
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",
|
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@sveltejs/vite-plugin-svelte": "^2.4.
|
|
16
|
+
"@sveltejs/vite-plugin-svelte": "^2.4.3",
|
|
17
17
|
"@testing-library/svelte": "^4.0.3",
|
|
18
|
-
"@vitest/coverage-v8": "^0.
|
|
19
|
-
"@vitest/ui": "~0.
|
|
18
|
+
"@vitest/coverage-v8": "^0.33.0",
|
|
19
|
+
"@vitest/ui": "~0.33.0",
|
|
20
20
|
"jsdom": "^22.1.0",
|
|
21
|
-
"svelte": "^4.
|
|
21
|
+
"svelte": "^4.1.1",
|
|
22
22
|
"typescript": "^5.1.6",
|
|
23
23
|
"validators": "latest",
|
|
24
|
-
"vite": "^4.
|
|
25
|
-
"vitest": "~0.
|
|
26
|
-
"shared-config": "1.0.0-next.
|
|
24
|
+
"vite": "^4.4.7",
|
|
25
|
+
"vitest": "~0.33.0",
|
|
26
|
+
"shared-config": "1.0.0-next.37"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"src/**/*.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@rokkit/core": "latest",
|
|
43
44
|
"@rokkit/stores": "latest"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
package/src/dismissable.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
const KEYCODE_ESC = 27
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* A svelte action function that captures clicks outside the element or escape keypress
|
|
5
|
+
* emits a `dismiss` event. This is useful for closing a modal or dropdown.
|
|
6
|
+
*
|
|
7
|
+
* @param {HTMLElement} node
|
|
8
|
+
* @returns {import('./types').SvelteActionReturn}
|
|
9
|
+
*/
|
|
3
10
|
export function dismissable(node) {
|
|
4
11
|
const handleClick = (event) => {
|
|
5
12
|
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
|
@@ -7,7 +14,9 @@ export function dismissable(node) {
|
|
|
7
14
|
}
|
|
8
15
|
}
|
|
9
16
|
const keyup = (event) => {
|
|
10
|
-
if (event.keyCode === KEYCODE_ESC) {
|
|
17
|
+
if (event.keyCode === KEYCODE_ESC || event.key === 'Escape') {
|
|
18
|
+
event.stopPropagation()
|
|
19
|
+
|
|
11
20
|
node.dispatchEvent(new CustomEvent('dismiss', node))
|
|
12
21
|
}
|
|
13
22
|
}
|
package/src/fillable.js
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef FillOptions
|
|
3
|
-
* @property {Array<string>} options available options to fill
|
|
4
|
-
* @property {integer} current index of option to be filled
|
|
5
|
-
* @property {boolean} check validate filled values
|
|
6
|
-
*/
|
|
7
1
|
/**
|
|
8
2
|
* Action for filling a <del>?</del> element in html block.
|
|
9
3
|
*
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {FillOptions} options
|
|
4
|
+
* @param {HTMLElement} node
|
|
5
|
+
* @param {import('./types').FillOptions} options
|
|
12
6
|
* @returns
|
|
13
7
|
*/
|
|
14
8
|
export function fillable(node, { options, current, check }) {
|
|
@@ -43,8 +37,8 @@ export function fillable(node, { options, current, check }) {
|
|
|
43
37
|
/**
|
|
44
38
|
* Initialize empty fillable element style and add listener for click
|
|
45
39
|
*
|
|
46
|
-
* @param {
|
|
47
|
-
* @param {
|
|
40
|
+
* @param {HTMLCollection} blanks
|
|
41
|
+
* @param {EventListener} click
|
|
48
42
|
*/
|
|
49
43
|
function initialize(blanks, click) {
|
|
50
44
|
Object.keys(blanks).map((ref) => {
|
|
@@ -58,8 +52,8 @@ function initialize(blanks, click) {
|
|
|
58
52
|
/**
|
|
59
53
|
* Fill current blank with provided option
|
|
60
54
|
*
|
|
61
|
-
* @param {
|
|
62
|
-
* @param {
|
|
55
|
+
* @param {HTMLCollection} blanks
|
|
56
|
+
* @param {Array<import('./types.js').FillableData>} options
|
|
63
57
|
* @param {*} current
|
|
64
58
|
*/
|
|
65
59
|
function fill(blanks, options, current) {
|
|
@@ -76,8 +70,8 @@ function fill(blanks, options, current) {
|
|
|
76
70
|
/**
|
|
77
71
|
* Clear all fillable elements
|
|
78
72
|
*
|
|
79
|
-
* @param {
|
|
80
|
-
* @param {
|
|
73
|
+
* @param {EventListener} event
|
|
74
|
+
* @param {HTMLElement} node
|
|
81
75
|
*/
|
|
82
76
|
function clear(event, node) {
|
|
83
77
|
event.target.innerHTML = '?'
|
|
@@ -98,8 +92,8 @@ function clear(event, node) {
|
|
|
98
92
|
/**
|
|
99
93
|
* Validate the filled values
|
|
100
94
|
*
|
|
101
|
-
* @param {
|
|
102
|
-
* @param {
|
|
95
|
+
* @param {HTMLCollection} blanks
|
|
96
|
+
* @param {import('./types').FillOptions} data
|
|
103
97
|
*/
|
|
104
98
|
function validate(blanks, data) {
|
|
105
99
|
Object.keys(blanks).map((ref) => {
|
package/src/hierarchy.js
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A part of the path to node in hierarchy
|
|
3
|
-
*
|
|
4
|
-
* @typedef PathFragment
|
|
5
|
-
* @property {integer} index - Index to item in array
|
|
6
|
-
* @property {Array<*>} items - Array of items
|
|
7
|
-
* @property {import('../constants').FieldMapping} fields - Field mapping for the data
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
1
|
/**
|
|
11
2
|
* Check if the current item is a parent
|
|
12
3
|
*
|
|
13
4
|
* @param {*} item
|
|
14
|
-
* @param {import('
|
|
5
|
+
* @param {import('@rokkit/core').FieldMapping} fields
|
|
15
6
|
* @returns {boolean}
|
|
16
7
|
*/
|
|
17
8
|
export function hasChildren(item, fields) {
|
|
@@ -26,7 +17,7 @@ export function hasChildren(item, fields) {
|
|
|
26
17
|
* Check if the current item is a parent and is expanded
|
|
27
18
|
*
|
|
28
19
|
* @param {*} item
|
|
29
|
-
* @param {import('
|
|
20
|
+
* @param {import('@rokkit/core').FieldMapping} fields
|
|
30
21
|
* @returns {boolean}
|
|
31
22
|
*/
|
|
32
23
|
export function isExpanded(item, fields) {
|
|
@@ -42,7 +33,7 @@ export function isExpanded(item, fields) {
|
|
|
42
33
|
* Verify if at least one item has children
|
|
43
34
|
*
|
|
44
35
|
* @param {Array<*>} items
|
|
45
|
-
* @param {import('
|
|
36
|
+
* @param {import('@rokkit/core').FieldMapping} fields
|
|
46
37
|
* @returns {boolean}
|
|
47
38
|
*/
|
|
48
39
|
export function isNested(items, fields) {
|
|
@@ -55,12 +46,12 @@ export function isNested(items, fields) {
|
|
|
55
46
|
/**
|
|
56
47
|
* Navigate to last visible child in the hirarchy starting with the provided path
|
|
57
48
|
*
|
|
58
|
-
* @param {Array<PathFragment>} path - path to a node in the hierarchy
|
|
49
|
+
* @param {Array<import('./types').PathFragment>} path - path to a node in the hierarchy
|
|
59
50
|
* @returns
|
|
60
51
|
*/
|
|
61
52
|
export function navigateToLastVisibleChild(path) {
|
|
62
53
|
let current = path[path.length - 1]
|
|
63
|
-
|
|
54
|
+
|
|
64
55
|
while (isExpanded(current.items[current.index], current.fields)) {
|
|
65
56
|
const items = current.items[current.index][current.fields.children]
|
|
66
57
|
const level = {
|
|
@@ -78,9 +69,9 @@ export function navigateToLastVisibleChild(path) {
|
|
|
78
69
|
/**
|
|
79
70
|
* Navigate to the next item
|
|
80
71
|
*
|
|
81
|
-
* @param {Array<PathFragment>} path - path to a node in the hierarchy
|
|
72
|
+
* @param {Array<import('./types').PathFragment>} path - path to a node in the hierarchy
|
|
82
73
|
* @param {Array<*>} items - array of items
|
|
83
|
-
* @param {import('
|
|
74
|
+
* @param {import('@rokkit/core').FieldMapping} fields - field mapping
|
|
84
75
|
* @returns
|
|
85
76
|
*/
|
|
86
77
|
export function moveNext(path, items, fields) {
|
|
@@ -115,7 +106,7 @@ export function moveNext(path, items, fields) {
|
|
|
115
106
|
/**
|
|
116
107
|
* Navigate to the previous item
|
|
117
108
|
*
|
|
118
|
-
* @param {Array<PathFragment>} path - path to a node in the hierarchy
|
|
109
|
+
* @param {Array<import('./types').PathFragment>} path - path to a node in the hierarchy
|
|
119
110
|
* @returns
|
|
120
111
|
*/
|
|
121
112
|
export function movePrevious(path) {
|
|
@@ -139,7 +130,7 @@ export function movePrevious(path) {
|
|
|
139
130
|
*
|
|
140
131
|
* @param {Array<integer>} indices
|
|
141
132
|
* @param {Array<*>} items
|
|
142
|
-
* @param {import('
|
|
133
|
+
* @param {import('@rokkit/core').FieldMapping} fields
|
|
143
134
|
* @returns
|
|
144
135
|
*/
|
|
145
136
|
export function pathFromIndices(indices, items, fields) {
|
|
@@ -160,15 +151,34 @@ export function pathFromIndices(indices, items, fields) {
|
|
|
160
151
|
return path
|
|
161
152
|
}
|
|
162
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Get the indices from the path
|
|
156
|
+
* @param {Array<import('./types').PathFragment>} path
|
|
157
|
+
* @returns {Array<integer>}
|
|
158
|
+
*/
|
|
163
159
|
export function indicesFromPath(path) {
|
|
164
160
|
return path.map(({ index }) => index)
|
|
165
161
|
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get the current node from the path
|
|
165
|
+
* @param {Array<import('./types').PathFragment>} path
|
|
166
|
+
* @returns {*}
|
|
167
|
+
*/
|
|
166
168
|
export function getCurrentNode(path) {
|
|
167
169
|
if (path.length === 0) return null
|
|
168
170
|
const lastIndex = path.length - 1
|
|
169
171
|
return path[lastIndex].items[path[lastIndex].index]
|
|
170
172
|
}
|
|
171
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Find the item in the hierarchy using the indices
|
|
176
|
+
*
|
|
177
|
+
* @param {Array<*>} items
|
|
178
|
+
* @param {Array<integer>} indices
|
|
179
|
+
* @param {import('@rokkit/core').FieldMapping} fields
|
|
180
|
+
* @returns {*}
|
|
181
|
+
*/
|
|
172
182
|
export function findItem(items, indices, fields) {
|
|
173
183
|
let item = items[indices[0]]
|
|
174
184
|
let levelFields = fields
|
package/src/index.js
CHANGED
package/src/navigable.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A svelte action function that captures keyboard evvents and emits event for corresponding movements.
|
|
3
|
+
*
|
|
4
|
+
* @param {HTMLElement} node
|
|
5
|
+
* @param {import('./types').NavigableOptions} options
|
|
6
|
+
* @returns {import('./types').SvelteActionReturn}
|
|
7
|
+
*/
|
|
1
8
|
export function navigable(
|
|
2
9
|
node,
|
|
3
10
|
{ horizontal = true, nested = false, enabled = true } = {}
|
package/src/navigator.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// import { tick } from 'svelte'
|
|
1
2
|
import {
|
|
2
3
|
moveNext,
|
|
3
4
|
movePrevious,
|
|
@@ -5,72 +6,67 @@ import {
|
|
|
5
6
|
hasChildren,
|
|
6
7
|
pathFromIndices,
|
|
7
8
|
indicesFromPath,
|
|
8
|
-
getCurrentNode
|
|
9
|
+
getCurrentNode,
|
|
10
|
+
isExpanded
|
|
9
11
|
} from './hierarchy'
|
|
10
|
-
/**
|
|
11
|
-
* @typedef NavigatorOptions
|
|
12
|
-
* @property {Array<*>} items - An array containing the data set to navigate
|
|
13
|
-
* @property {boolean} [vertical=true] - Identifies whether navigation shoud be vertical or horizontal
|
|
14
|
-
* @property {string} [idPrefix='id-'] - id prefix used for identifying individual node
|
|
15
|
-
* @property {import('../constants').FieldMapping} fields - Field mapping to identify attributes to be used for state and identification of children
|
|
16
|
-
*/
|
|
17
12
|
|
|
18
13
|
/**
|
|
19
14
|
* Keyboard navigation for Lists and NestedLists. The data is either nested or not and is not
|
|
20
15
|
* expected to switch from nested to simple list or vice-versa.
|
|
21
16
|
*
|
|
22
|
-
* @param {HTMLElement}
|
|
23
|
-
* @param {NavigatorOptions} options - Configuration options for the action
|
|
17
|
+
* @param {HTMLElement} element - Root element for the actionn
|
|
18
|
+
* @param {import('./types').NavigatorOptions} options - Configuration options for the action
|
|
24
19
|
* @returns
|
|
25
20
|
*/
|
|
26
|
-
export function navigator(
|
|
21
|
+
export function navigator(element, options) {
|
|
27
22
|
const { fields, enabled = true, vertical = true, idPrefix = 'id-' } = options
|
|
28
23
|
let items, path, currentNode
|
|
29
24
|
|
|
30
25
|
if (!enabled) return { destroy: () => {} }
|
|
31
26
|
|
|
27
|
+
// todo: Update should handle selection value change
|
|
28
|
+
// should we wait a tick before updating?
|
|
32
29
|
const update = (options) => {
|
|
30
|
+
const previousNode = currentNode
|
|
33
31
|
items = options.items
|
|
34
32
|
path = pathFromIndices(options.indices ?? [], items, fields)
|
|
35
33
|
currentNode = getCurrentNode(path)
|
|
34
|
+
|
|
35
|
+
if (previousNode !== currentNode && currentNode) {
|
|
36
|
+
const indices = indicesFromPath(path)
|
|
37
|
+
let current = element.querySelector('#' + idPrefix + indices.join('-'))
|
|
38
|
+
if (current) {
|
|
39
|
+
current.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
|
|
40
|
+
}
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
const next = () => {
|
|
39
45
|
const previousNode = currentNode
|
|
40
46
|
path = moveNext(path, items, fields)
|
|
41
47
|
currentNode = getCurrentNode(path)
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
if (previousNode !== currentNode)
|
|
49
|
+
moveTo(element, path, currentNode, idPrefix)
|
|
44
50
|
}
|
|
51
|
+
|
|
45
52
|
const previous = () => {
|
|
46
53
|
const previousNode = currentNode
|
|
47
54
|
path = movePrevious(path)
|
|
48
55
|
if (path.length > 0) {
|
|
49
56
|
currentNode = getCurrentNode(path)
|
|
50
57
|
if (previousNode !== currentNode)
|
|
51
|
-
moveTo(
|
|
58
|
+
moveTo(element, path, currentNode, idPrefix)
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
const select = () => {
|
|
55
|
-
if (currentNode)
|
|
56
|
-
node.dispatchEvent(
|
|
57
|
-
new CustomEvent('select', {
|
|
58
|
-
detail: { path: indicesFromPath(path), node: currentNode }
|
|
59
|
-
})
|
|
60
|
-
)
|
|
62
|
+
if (currentNode) emit('select', element, indicesFromPath(path), currentNode)
|
|
61
63
|
}
|
|
62
64
|
const collapse = () => {
|
|
63
65
|
if (currentNode) {
|
|
64
|
-
const collapse =
|
|
65
|
-
hasChildren(currentNode, path[path.length - 1].fields) &&
|
|
66
|
-
currentNode[path[path.length - 1].fields.isOpen]
|
|
66
|
+
const collapse = isExpanded(currentNode, path[path.length - 1].fields)
|
|
67
67
|
if (collapse) {
|
|
68
68
|
currentNode[path[path.length - 1].fields.isOpen] = false
|
|
69
|
-
|
|
70
|
-
new CustomEvent('collapse', {
|
|
71
|
-
detail: { path: indicesFromPath(path), node: currentNode }
|
|
72
|
-
})
|
|
73
|
-
)
|
|
69
|
+
emit('collapse', element, indicesFromPath(path), currentNode)
|
|
74
70
|
} else if (path.length > 0) {
|
|
75
71
|
path = path.slice(0, -1)
|
|
76
72
|
currentNode = getCurrentNode(path)
|
|
@@ -81,11 +77,7 @@ export function navigator(node, options) {
|
|
|
81
77
|
const expand = () => {
|
|
82
78
|
if (currentNode && hasChildren(currentNode, path[path.length - 1].fields)) {
|
|
83
79
|
currentNode[path[path.length - 1].fields.isOpen] = true
|
|
84
|
-
|
|
85
|
-
new CustomEvent('expand', {
|
|
86
|
-
detail: { path: indicesFromPath(path), node: currentNode }
|
|
87
|
-
})
|
|
88
|
-
)
|
|
80
|
+
emit('expand', element, indicesFromPath(path), currentNode)
|
|
89
81
|
}
|
|
90
82
|
}
|
|
91
83
|
|
|
@@ -111,7 +103,7 @@ export function navigator(node, options) {
|
|
|
111
103
|
}
|
|
112
104
|
|
|
113
105
|
const handleClick = (event) => {
|
|
114
|
-
let target = findParentWithDataPath(event.target)
|
|
106
|
+
let target = findParentWithDataPath(event.target, element)
|
|
115
107
|
let indices = !target
|
|
116
108
|
? []
|
|
117
109
|
: target.dataset.path
|
|
@@ -128,52 +120,72 @@ export function navigator(node, options) {
|
|
|
128
120
|
const event = currentNode[path[path.length - 1].fields.isOpen]
|
|
129
121
|
? 'expand'
|
|
130
122
|
: 'collapse'
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
detail: { path: indices, node: currentNode }
|
|
134
|
-
})
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
node.dispatchEvent(
|
|
138
|
-
new CustomEvent('select', {
|
|
139
|
-
detail: { path: indices, node: currentNode }
|
|
140
|
-
})
|
|
141
|
-
)
|
|
123
|
+
emit(event, element, indices, currentNode)
|
|
124
|
+
} else if (currentNode) emit('select', element, indices, currentNode)
|
|
142
125
|
}
|
|
143
126
|
}
|
|
144
127
|
|
|
145
|
-
|
|
146
|
-
|
|
128
|
+
element.addEventListener('keydown', handleKeyDown)
|
|
129
|
+
element.addEventListener('click', handleClick)
|
|
147
130
|
|
|
148
131
|
return {
|
|
149
132
|
update,
|
|
150
133
|
destroy() {
|
|
151
|
-
|
|
152
|
-
|
|
134
|
+
element.removeEventListener('keydown', handleKeyDown)
|
|
135
|
+
element.removeEventListener('click', handleClick)
|
|
153
136
|
}
|
|
154
137
|
}
|
|
155
138
|
}
|
|
156
139
|
|
|
157
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Move to the element with the given path
|
|
142
|
+
*
|
|
143
|
+
* @param {HTMLElement} element
|
|
144
|
+
* @param {*} path
|
|
145
|
+
* @param {*} currentNode
|
|
146
|
+
* @param {*} idPrefix
|
|
147
|
+
*/
|
|
148
|
+
export function moveTo(element, path, currentNode, idPrefix) {
|
|
158
149
|
const indices = indicesFromPath(path)
|
|
159
|
-
|
|
160
|
-
let current = node.querySelector('#' + idPrefix + indices.join('-'))
|
|
150
|
+
let current = element.querySelector('#' + idPrefix + indices.join('-'))
|
|
161
151
|
if (current) current.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
|
|
162
152
|
|
|
163
|
-
|
|
164
|
-
new CustomEvent('move', {
|
|
165
|
-
detail: { path: indices, node: currentNode }
|
|
166
|
-
})
|
|
167
|
-
)
|
|
153
|
+
emit('move', element, indices, currentNode)
|
|
168
154
|
}
|
|
169
155
|
|
|
170
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Find the parent element with data-path attribute
|
|
158
|
+
*
|
|
159
|
+
* @param {HTMLElement} element
|
|
160
|
+
* @param {HTMLElement} root
|
|
161
|
+
* @returns {HTMLElement}
|
|
162
|
+
*/
|
|
163
|
+
export function findParentWithDataPath(element, root) {
|
|
171
164
|
if (element.hasAttribute('data-path')) return element
|
|
172
165
|
let parent = element.parentNode
|
|
173
166
|
|
|
174
|
-
while (parent && !parent.hasAttribute('data-path')) {
|
|
167
|
+
while (parent && parent !== root && !parent.hasAttribute('data-path')) {
|
|
175
168
|
parent = parent.parentNode
|
|
176
169
|
}
|
|
177
170
|
|
|
178
|
-
return parent
|
|
171
|
+
return parent !== root ? parent : null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Emit a custom event on the element with the path and node as detail
|
|
176
|
+
*
|
|
177
|
+
* @param {string} event
|
|
178
|
+
* @param {HTMLElement} element
|
|
179
|
+
* @param {Array<integer>} indices
|
|
180
|
+
* @param {*} node
|
|
181
|
+
*/
|
|
182
|
+
function emit(event, element, indices, node) {
|
|
183
|
+
element.dispatchEvent(
|
|
184
|
+
new CustomEvent(event, {
|
|
185
|
+
detail: {
|
|
186
|
+
path: indices,
|
|
187
|
+
node: node
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
)
|
|
179
191
|
}
|
package/src/pannable.js
CHANGED
package/src/swipeable.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A svelte action function that captures swipe actions and emits event for corresponding movements.
|
|
3
|
+
*
|
|
4
|
+
* @param {HTMLElement} node
|
|
5
|
+
* @param {import(./types).SwipeableOptions} options
|
|
6
|
+
* @returns {import('./types').SvelteActionReturn}
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
export function swipeable(
|
|
2
10
|
node,
|
|
3
11
|
{
|
package/src/themeable.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { theme } from '@rokkit/stores'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* A svelte action function that adds theme classes to the element
|
|
5
5
|
*
|
|
6
6
|
* @param {HTMLElement} node
|
|
7
7
|
*/
|
|
@@ -9,15 +9,24 @@ export function themable(node) {
|
|
|
9
9
|
let previous = {}
|
|
10
10
|
|
|
11
11
|
theme.subscribe((data) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
node.classList.add(data.name)
|
|
15
|
-
}
|
|
16
|
-
if (data.mode && data.mode !== previous.mode) {
|
|
17
|
-
node.classList.remove(previous.mode)
|
|
18
|
-
node.classList.add(data.mode)
|
|
19
|
-
}
|
|
12
|
+
switchClass(node, data.name, previous.name)
|
|
13
|
+
switchClass(node, data.mode, previous.mode)
|
|
20
14
|
|
|
21
15
|
previous = data
|
|
22
16
|
})
|
|
23
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Switch the class on the node
|
|
21
|
+
*
|
|
22
|
+
* @param {HTMLElement} node
|
|
23
|
+
* @param {string} current
|
|
24
|
+
* @param {string} previous
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
function switchClass(node, current, previous) {
|
|
28
|
+
if (current && current !== previous) {
|
|
29
|
+
node.classList.remove(previous)
|
|
30
|
+
node.classList.add(current)
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/types.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef SvelteActionReturn
|
|
3
|
+
* @property {() => void} destroy
|
|
4
|
+
* @property {() => void} [update]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef FillableData
|
|
9
|
+
* @property {string} value
|
|
10
|
+
* @property {integer} actualIndex
|
|
11
|
+
* @property {integer} expectedIndex
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef FillOptions
|
|
16
|
+
* @property {Array<FillableData>} options available options to fill
|
|
17
|
+
* @property {integer} current index of option to be filled
|
|
18
|
+
* @property {boolean} check validate filled values
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A part of the path to node in hierarchy
|
|
23
|
+
*
|
|
24
|
+
* @typedef PathFragment
|
|
25
|
+
* @property {integer} index - Index to item in array
|
|
26
|
+
* @property {Array<*>} items - Array of items
|
|
27
|
+
* @property {import('@rokkit/core').FieldMapping} fields - Field mapping for the data
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Options for the Navigable action
|
|
32
|
+
* @typedef NavigableOptions
|
|
33
|
+
* @property {boolean} horizontal - Navigate horizontally
|
|
34
|
+
* @property {boolean} nested - Navigate nested items
|
|
35
|
+
* @property {boolean} enabled - Enable navigation
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef NavigatorOptions
|
|
40
|
+
* @property {Array<*>} items - An array containing the data set to navigate
|
|
41
|
+
* @property {boolean} [vertical=true] - Identifies whether navigation shoud be vertical or horizontal
|
|
42
|
+
* @property {string} [idPrefix='id-'] - id prefix used for identifying individual node
|
|
43
|
+
* @property {import('../constants').FieldMapping} fields - Field mapping to identify attributes to be used for state and identification of children
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef SwipeableOptions
|
|
48
|
+
* @property {boolean} horizontal - Swipe horizontally
|
|
49
|
+
* @property {boolean} vertical - Swipe vertically
|
|
50
|
+
* @property {boolean} enabled - Enable swiping
|
|
51
|
+
* @property {number} threshold - Threshold for swipe
|
|
52
|
+
* @property {number} minSpeed - Minimum speed for swipe
|
|
53
|
+
*/
|