@rokkit/core 1.0.0-next.14 → 1.0.0-next.141
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/LICENSE +1 -1
- package/README.md +121 -1
- package/dist/calendar.d.ts +10 -0
- package/dist/colors/index.d.ts +47 -0
- package/dist/connector.d.ts +8 -0
- package/dist/constants.d.ts +80 -0
- package/dist/events.d.ts +12 -0
- package/dist/field-mapper.d.ts +60 -0
- package/dist/index.d.ts +13 -0
- package/dist/key-event-map.d.ts +18 -0
- package/dist/mapped-items.d.ts +14 -0
- package/dist/mapping.d.ts +14 -0
- package/dist/nested.d.ts +9 -0
- package/dist/string.d.ts +59 -0
- package/dist/theme.d.ts +96 -0
- package/dist/ticks.d.ts +10 -0
- package/dist/types.d.ts +300 -0
- package/dist/utils.d.ts +93 -0
- package/dist/vite/icon-collections.d.ts +32 -0
- package/dist/vite/index.d.ts +1 -0
- package/package.json +31 -39
- package/src/calendar.js +44 -0
- package/src/colors/extra.json +16 -0
- package/src/colors/index.ts +24 -0
- package/src/colors/syntax.json +42 -0
- package/src/colors/tailwind.json +275 -0
- package/src/connector.js +34 -0
- package/src/constants.js +164 -107
- package/src/events.js +32 -0
- package/src/field-mapper.js +147 -0
- package/src/index.js +19 -27
- package/src/key-event-map.js +35 -0
- package/src/mapped-items.js +22 -0
- package/src/mapping.js +21 -0
- package/src/nested.js +28 -0
- package/src/string.js +97 -0
- package/src/theme.ts +206 -0
- package/src/ticks.js +26 -0
- package/src/types.js +160 -0
- package/src/utils.js +255 -0
- package/src/vite/icon-collections.js +73 -0
- package/src/vite/index.js +1 -0
- package/src/Accordion.svelte +0 -80
- package/src/Alerts.svelte +0 -39
- package/src/DropDown.svelte +0 -82
- package/src/DropSearch.svelte +0 -67
- package/src/EditableTabs.svelte +0 -31
- package/src/Icon.svelte +0 -15
- package/src/List-Discard.svelte +0 -48
- package/src/List.svelte +0 -65
- package/src/ListActions.svelte +0 -35
- package/src/NavTabs.svelte +0 -0
- package/src/NestedList.svelte +0 -77
- package/src/Overlay.svelte +0 -4
- package/src/PageNavigator.svelte +0 -94
- package/src/ResponsiveGrid.svelte +0 -73
- package/src/Scrollable.svelte +0 -8
- package/src/Searchable.svelte +0 -19
- package/src/Sidebar.svelte +0 -5
- package/src/Slider.svelte +0 -17
- package/src/SpinList.svelte +0 -48
- package/src/SplitPane.svelte +0 -109
- package/src/SplitView.svelte +0 -44
- package/src/Splitter.svelte +0 -95
- package/src/TabItem.svelte +0 -27
- package/src/TabItems.svelte +0 -34
- package/src/Tabs.svelte +0 -49
- package/src/Tree.svelte +0 -45
- package/src/actions/dismissable.js +0 -24
- package/src/actions/fillable.js +0 -114
- package/src/actions/hierarchy.js +0 -180
- package/src/actions/index.js +0 -7
- package/src/actions/navigable.js +0 -43
- package/src/actions/navigator.js +0 -179
- package/src/actions/pannable.js +0 -50
- package/src/actions/swipeable.js +0 -56
- package/src/actions/themeable.js +0 -23
- package/src/items/Collapsible.svelte +0 -51
- package/src/items/Connector.svelte +0 -26
- package/src/items/Link.svelte +0 -18
- package/src/items/Node.svelte +0 -52
- package/src/items/Pill.svelte +0 -19
- package/src/items/Separator.svelte +0 -1
- package/src/items/Summary.svelte +0 -27
- package/src/items/Text.svelte +0 -21
- package/src/items/index.js +0 -8
- package/src/list.js +0 -14
- package/src/mocks/Custom.svelte +0 -7
- package/src/mocks/index.js +0 -10
- package/src/stores/alerts.js +0 -3
- package/src/stores/index.js +0 -6
- package/src/stores/persist.js +0 -63
- package/src/stores/theme.js +0 -34
package/src/SplitPane.svelte
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
import { pannable } from './actions'
|
|
4
|
-
|
|
5
|
-
const dispatch = createEventDispatcher()
|
|
6
|
-
|
|
7
|
-
export let vertical = false
|
|
8
|
-
export let limits = [50, 30]
|
|
9
|
-
export let pos = 70
|
|
10
|
-
export let styles = ['', '']
|
|
11
|
-
|
|
12
|
-
let refs = {}
|
|
13
|
-
|
|
14
|
-
function clamp(min, max, value) {
|
|
15
|
-
return min > value ? min : max < value ? max : value
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function handlePanMove(event) {
|
|
19
|
-
const { top, bottom, left, right } = refs.wrapper.getBoundingClientRect()
|
|
20
|
-
const extents = horizontal ? [left, right] : [top, bottom]
|
|
21
|
-
let px = clamp(
|
|
22
|
-
extents[0],
|
|
23
|
-
extents[1],
|
|
24
|
-
horizontal ? event.detail.x : event.detail.y
|
|
25
|
-
)
|
|
26
|
-
pos = clamp(
|
|
27
|
-
limits[0],
|
|
28
|
-
100 - limits[1],
|
|
29
|
-
(100 * (px - extents[0])) / (extents[1] - extents[0])
|
|
30
|
-
)
|
|
31
|
-
dispatch('change', { pos })
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
$: horizontal = !vertical
|
|
35
|
-
$: side = horizontal ? 'left' : 'top'
|
|
36
|
-
$: dimension = horizontal ? 'width' : 'height'
|
|
37
|
-
$: direction = vertical ? 'vertical' : 'horizontal'
|
|
38
|
-
</script>
|
|
39
|
-
|
|
40
|
-
<div class="wrapper {direction}" bind:this={refs.wrapper}>
|
|
41
|
-
<div class={styles[0]} style="{dimension}: {pos}%;">
|
|
42
|
-
<slot name="a" />
|
|
43
|
-
</div>
|
|
44
|
-
<div class={styles[1]} style="{dimension}: {100 - pos}%;">
|
|
45
|
-
<slot name="b" />
|
|
46
|
-
</div>
|
|
47
|
-
<span
|
|
48
|
-
class="wall"
|
|
49
|
-
use:pannable
|
|
50
|
-
on:panmove={handlePanMove}
|
|
51
|
-
style="{side}: calc({pos}% - 8px)"
|
|
52
|
-
/>
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<style>
|
|
56
|
-
.wrapper {
|
|
57
|
-
position: relative;
|
|
58
|
-
display: flex;
|
|
59
|
-
height: 100%;
|
|
60
|
-
width: 100%;
|
|
61
|
-
}
|
|
62
|
-
.wrapper div {
|
|
63
|
-
flex: 1 1 auto;
|
|
64
|
-
height: 100%;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.horizontal {
|
|
68
|
-
flex-direction: row;
|
|
69
|
-
}
|
|
70
|
-
.vertical {
|
|
71
|
-
flex-direction: column;
|
|
72
|
-
}
|
|
73
|
-
.wall {
|
|
74
|
-
position: absolute;
|
|
75
|
-
z-index: 10;
|
|
76
|
-
}
|
|
77
|
-
.wall::after {
|
|
78
|
-
content: '';
|
|
79
|
-
position: absolute;
|
|
80
|
-
background-color: var(--bg-800);
|
|
81
|
-
}
|
|
82
|
-
.wall:hover {
|
|
83
|
-
cursor: ew-resize;
|
|
84
|
-
}
|
|
85
|
-
.horizontal .wall {
|
|
86
|
-
padding: 0 8px;
|
|
87
|
-
width: 0;
|
|
88
|
-
height: 100%;
|
|
89
|
-
cursor: ew-resize;
|
|
90
|
-
}
|
|
91
|
-
.horizontal .wall::after {
|
|
92
|
-
left: 8px;
|
|
93
|
-
top: 0;
|
|
94
|
-
width: 1px;
|
|
95
|
-
height: 100%;
|
|
96
|
-
}
|
|
97
|
-
.vertical .wall {
|
|
98
|
-
padding: 8px 0;
|
|
99
|
-
width: 100%;
|
|
100
|
-
height: 0;
|
|
101
|
-
cursor: ns-resize;
|
|
102
|
-
}
|
|
103
|
-
.vertical .wall::after {
|
|
104
|
-
top: 8px;
|
|
105
|
-
left: 0;
|
|
106
|
-
width: 100%;
|
|
107
|
-
height: 1px;
|
|
108
|
-
}
|
|
109
|
-
</style>
|
package/src/SplitView.svelte
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import Splitter from './Splitter.svelte'
|
|
3
|
-
|
|
4
|
-
export let vertical = false
|
|
5
|
-
export let min = 30
|
|
6
|
-
export let max = 70
|
|
7
|
-
export let pos = 30
|
|
8
|
-
|
|
9
|
-
$: sizes = [pos, 100 - pos]
|
|
10
|
-
|
|
11
|
-
$: direction = { direction: vertical ? 'flex-col' : 'flex-row' }
|
|
12
|
-
$: sizeA = {
|
|
13
|
-
width: vertical ? 100 : sizes[0],
|
|
14
|
-
height: vertical ? sizes[0] : 100
|
|
15
|
-
}
|
|
16
|
-
$: sizeB = {
|
|
17
|
-
width: vertical ? 100 : sizes[1],
|
|
18
|
-
height: vertical ? sizes[1] : 100
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function onSplitterChange(e) {
|
|
22
|
-
pos = e.detail.pos - e.detail.offset
|
|
23
|
-
}
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<div class="relative flex w-full h-full" style:--direction={direction}>
|
|
27
|
-
<section style:--sizeA={sizeA} class="flex flex-grow flex-shrink select-none">
|
|
28
|
-
<slot name="a" />
|
|
29
|
-
</section>
|
|
30
|
-
<section style:--sizeB={sizeB} class="flex flex-grow flex-shrink select-none">
|
|
31
|
-
<slot name="b" />
|
|
32
|
-
</section>
|
|
33
|
-
<Splitter {vertical} {min} {max} {pos} on:change={onSplitterChange} />
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<style>
|
|
37
|
-
div {
|
|
38
|
-
flex-direction: var(--direction);
|
|
39
|
-
}
|
|
40
|
-
section {
|
|
41
|
-
width: calc(var(--width) * 1%);
|
|
42
|
-
height: calc(var(--height) * 1%);
|
|
43
|
-
}
|
|
44
|
-
</style>
|
package/src/Splitter.svelte
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
// ensure that parent has position: relative.
|
|
3
|
-
// on reaching limit remove mouse events.
|
|
4
|
-
import { createEventDispatcher } from 'svelte'
|
|
5
|
-
import { pannable } from './actions'
|
|
6
|
-
|
|
7
|
-
const dispatch = createEventDispatcher()
|
|
8
|
-
|
|
9
|
-
export let vertical = false
|
|
10
|
-
export let index
|
|
11
|
-
export let min = 0
|
|
12
|
-
export let max = 100
|
|
13
|
-
export let pos = 50
|
|
14
|
-
export let offset = 0
|
|
15
|
-
|
|
16
|
-
let wall
|
|
17
|
-
|
|
18
|
-
function clamp(min, max, value) {
|
|
19
|
-
return min > value ? min : max < value ? max : value
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function fixLimits() {
|
|
23
|
-
if (min > max) [min, max] = [max, min]
|
|
24
|
-
max = clamp(0, 100, max)
|
|
25
|
-
min = clamp(0, 100, min)
|
|
26
|
-
pos = clamp(min, max, pos)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function handlePanMove(event) {
|
|
30
|
-
const { top, bottom, left, right } =
|
|
31
|
-
wall.parentElement.getBoundingClientRect()
|
|
32
|
-
const extents = horizontal ? [left, right] : [top, bottom]
|
|
33
|
-
let px = clamp(
|
|
34
|
-
extents[0],
|
|
35
|
-
extents[1],
|
|
36
|
-
horizontal ? event.detail.x : event.detail.y
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
pos = clamp(min, max, (100 * (px - extents[0])) / (extents[1] - extents[0]))
|
|
40
|
-
|
|
41
|
-
dispatch('change', { pos, index, offset })
|
|
42
|
-
}
|
|
43
|
-
$: fixLimits()
|
|
44
|
-
$: horizontal = !vertical
|
|
45
|
-
$: side = horizontal ? 'left' : 'top'
|
|
46
|
-
</script>
|
|
47
|
-
|
|
48
|
-
<span
|
|
49
|
-
bind:this={wall}
|
|
50
|
-
class="wall"
|
|
51
|
-
class:vertical
|
|
52
|
-
class:horizontal
|
|
53
|
-
use:pannable
|
|
54
|
-
on:panmove={handlePanMove}
|
|
55
|
-
style="{side}: calc({pos}% - 8px)"
|
|
56
|
-
/>
|
|
57
|
-
|
|
58
|
-
<style>
|
|
59
|
-
.wall {
|
|
60
|
-
position: absolute;
|
|
61
|
-
z-index: 10;
|
|
62
|
-
}
|
|
63
|
-
.wall::after {
|
|
64
|
-
content: '';
|
|
65
|
-
position: absolute;
|
|
66
|
-
background-color: #000;
|
|
67
|
-
}
|
|
68
|
-
.wall:hover {
|
|
69
|
-
cursor: ew-resize;
|
|
70
|
-
}
|
|
71
|
-
.horizontal.wall {
|
|
72
|
-
padding: 0 8px;
|
|
73
|
-
width: 0;
|
|
74
|
-
height: 100%;
|
|
75
|
-
cursor: ew-resize;
|
|
76
|
-
}
|
|
77
|
-
.horizontal.wall::after {
|
|
78
|
-
left: 8px;
|
|
79
|
-
top: 0;
|
|
80
|
-
width: 1px;
|
|
81
|
-
height: 100%;
|
|
82
|
-
}
|
|
83
|
-
.vertical.wall {
|
|
84
|
-
padding: 8px 0;
|
|
85
|
-
width: 100%;
|
|
86
|
-
height: 0;
|
|
87
|
-
cursor: ns-resize;
|
|
88
|
-
}
|
|
89
|
-
.vertical.wall::after {
|
|
90
|
-
top: 8px;
|
|
91
|
-
left: 0;
|
|
92
|
-
width: 100%;
|
|
93
|
-
height: 1px;
|
|
94
|
-
}
|
|
95
|
-
</style>
|
package/src/TabItem.svelte
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
|
|
4
|
-
const dispatch = createEventDispatcher()
|
|
5
|
-
|
|
6
|
-
export let icon = null
|
|
7
|
-
export let label
|
|
8
|
-
export let active = false
|
|
9
|
-
export let allowClose = false
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
13
|
-
<tab class="flex flex-row items-center" class:active on:click>
|
|
14
|
-
{#if icon}
|
|
15
|
-
<icon class={icon} aria-label={icon} />
|
|
16
|
-
{/if}
|
|
17
|
-
{#if label}
|
|
18
|
-
<p class="flex flex-shrink-0 flex-grow justify-center">{label}</p>
|
|
19
|
-
{/if}
|
|
20
|
-
{#if allowClose}
|
|
21
|
-
<icon
|
|
22
|
-
class="remove small"
|
|
23
|
-
aria-label="remove"
|
|
24
|
-
on:click={() => dispatch('remove')}
|
|
25
|
-
/>
|
|
26
|
-
{/if}
|
|
27
|
-
</tab>
|
package/src/TabItems.svelte
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
import { defaultFields } from './constants'
|
|
4
|
-
import TabItem from './TabItem.svelte'
|
|
5
|
-
|
|
6
|
-
const dispatch = createEventDispatcher()
|
|
7
|
-
|
|
8
|
-
export let items = []
|
|
9
|
-
export let fields = {}
|
|
10
|
-
export let allowClose = false
|
|
11
|
-
export let value = items[0]
|
|
12
|
-
|
|
13
|
-
function activate(item) {
|
|
14
|
-
value = item
|
|
15
|
-
dispatch('switch', item)
|
|
16
|
-
}
|
|
17
|
-
function closeTab(index) {
|
|
18
|
-
items[index].isClosed = true
|
|
19
|
-
}
|
|
20
|
-
$: fields = { ...defaultFields, ...fields }
|
|
21
|
-
$: filtered = items.filter((item) => !item.isClosed)
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
{#each filtered as item, index}
|
|
25
|
-
{@const label = item[fields.text]}
|
|
26
|
-
<TabItem
|
|
27
|
-
icon={item[fields.icon]}
|
|
28
|
-
{label}
|
|
29
|
-
{allowClose}
|
|
30
|
-
active={value == item}
|
|
31
|
-
on:click={() => activate(item)}
|
|
32
|
-
on:close={() => closeTab(index)}
|
|
33
|
-
/>
|
|
34
|
-
{/each}
|
package/src/Tabs.svelte
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { defaultFields } from './constants'
|
|
3
|
-
import { Text } from './items'
|
|
4
|
-
import { navigator } from './actions'
|
|
5
|
-
import { createEventDispatcher } from 'svelte'
|
|
6
|
-
|
|
7
|
-
const dispatch = createEventDispatcher()
|
|
8
|
-
|
|
9
|
-
let className = ''
|
|
10
|
-
export { className as class }
|
|
11
|
-
export let items = []
|
|
12
|
-
export let fields = {}
|
|
13
|
-
export let using = {}
|
|
14
|
-
export let value = null
|
|
15
|
-
let cursor = []
|
|
16
|
-
|
|
17
|
-
function handleNav(event) {
|
|
18
|
-
value = event.detail.node
|
|
19
|
-
cursor = event.detail.path
|
|
20
|
-
|
|
21
|
-
dispatch('select', { item: value, indices: cursor })
|
|
22
|
-
}
|
|
23
|
-
$: fields = { ...defaultFields, ...fields }
|
|
24
|
-
$: using = { default: Text, ...using }
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<tabs
|
|
28
|
-
class="flex w-full {className}"
|
|
29
|
-
tabindex="0"
|
|
30
|
-
role="listbox"
|
|
31
|
-
use:navigator={{
|
|
32
|
-
items,
|
|
33
|
-
fields,
|
|
34
|
-
vertical: false,
|
|
35
|
-
indices: cursor
|
|
36
|
-
}}
|
|
37
|
-
on:move={handleNav}
|
|
38
|
-
on:select={handleNav}
|
|
39
|
-
>
|
|
40
|
-
{#each items as item, index}
|
|
41
|
-
{@const component = item[fields.component]
|
|
42
|
-
? using[item[fields.component]] || using.default
|
|
43
|
-
: using.default}
|
|
44
|
-
|
|
45
|
-
<item class="flex" class:is-selected={item === value} data-path={index}>
|
|
46
|
-
<svelte:component this={component} content={item} {fields} />
|
|
47
|
-
</item>
|
|
48
|
-
{/each}
|
|
49
|
-
</tabs>
|
package/src/Tree.svelte
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { createEventDispatcher } from 'svelte'
|
|
3
|
-
import NestedList from './NestedList.svelte'
|
|
4
|
-
import { Text } from './items'
|
|
5
|
-
import { defaultFields } from './constants'
|
|
6
|
-
import { navigator } from './actions/navigator'
|
|
7
|
-
|
|
8
|
-
const dispatch = createEventDispatcher()
|
|
9
|
-
|
|
10
|
-
export let items = []
|
|
11
|
-
export let fields = {}
|
|
12
|
-
export let using = { default: Text }
|
|
13
|
-
export let root = null
|
|
14
|
-
export let rtl = false
|
|
15
|
-
export let value
|
|
16
|
-
|
|
17
|
-
let indices = []
|
|
18
|
-
|
|
19
|
-
function handle(event) {
|
|
20
|
-
value = event.detail.node
|
|
21
|
-
indices = event.detail.path
|
|
22
|
-
if (['collapse', 'expand'].includes(event.type)) {
|
|
23
|
-
items = items
|
|
24
|
-
}
|
|
25
|
-
dispatch(event.type, value)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
$: fields = { ...defaultFields, ...fields }
|
|
29
|
-
$: items =
|
|
30
|
-
items.length == 1 || root == null
|
|
31
|
-
? items
|
|
32
|
-
: [{ [fields.text]: root, [fields.children]: items }]
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
36
|
-
<tree
|
|
37
|
-
use:navigator={{ items, fields, indices }}
|
|
38
|
-
on:select={handle}
|
|
39
|
-
on:move={handle}
|
|
40
|
-
on:expand={handle}
|
|
41
|
-
on:collapse={handle}
|
|
42
|
-
tabindex="0"
|
|
43
|
-
>
|
|
44
|
-
<NestedList {items} {fields} {using} {rtl} {value} />
|
|
45
|
-
</tree>
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const KEYCODE_ESC = 27
|
|
2
|
-
|
|
3
|
-
export function dismissable(node) {
|
|
4
|
-
const handleClick = (event) => {
|
|
5
|
-
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
|
6
|
-
node.dispatchEvent(new CustomEvent('dismiss', node))
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
const keyup = (event) => {
|
|
10
|
-
if (event.keyCode === KEYCODE_ESC) {
|
|
11
|
-
node.dispatchEvent(new CustomEvent('dismiss', node))
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
document.addEventListener('click', handleClick, true)
|
|
16
|
-
document.addEventListener('keyup', keyup, true)
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
destroy() {
|
|
20
|
-
document.removeEventListener('click', handleClick, true)
|
|
21
|
-
document.removeEventListener('keyup', keyup, true)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
package/src/actions/fillable.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
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
|
-
/**
|
|
8
|
-
* Action for filling a <del>?</del> element in html block.
|
|
9
|
-
*
|
|
10
|
-
* @param {*} node
|
|
11
|
-
* @param {FillOptions} options
|
|
12
|
-
* @returns
|
|
13
|
-
*/
|
|
14
|
-
export function fillable(node, { options, current, check }) {
|
|
15
|
-
let data = { options, current, check }
|
|
16
|
-
let blanks = node.getElementsByTagName('del')
|
|
17
|
-
|
|
18
|
-
function click(event) {
|
|
19
|
-
if ('?' !== event.target.innerHTML) {
|
|
20
|
-
clear(event, node)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
initialize(blanks, click)
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
update({ options, current }) {
|
|
28
|
-
data.options = options
|
|
29
|
-
data.current = current
|
|
30
|
-
data.check = check
|
|
31
|
-
|
|
32
|
-
fill(blanks, data.options, data.current)
|
|
33
|
-
if (data.check) validate(blanks, data)
|
|
34
|
-
},
|
|
35
|
-
destroy() {
|
|
36
|
-
Object.keys(blanks).map((ref) => {
|
|
37
|
-
blanks[ref].removeEventListener('click', click)
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Initialize empty fillable element style and add listener for click
|
|
45
|
-
*
|
|
46
|
-
* @param {*} blanks
|
|
47
|
-
* @param {*} click
|
|
48
|
-
*/
|
|
49
|
-
function initialize(blanks, click) {
|
|
50
|
-
Object.keys(blanks).map((ref) => {
|
|
51
|
-
blanks[ref].addEventListener('click', click)
|
|
52
|
-
blanks[ref].classList.add('empty')
|
|
53
|
-
blanks[ref].name = 'fill-' + ref
|
|
54
|
-
blanks[ref]['data-index'] = ref
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Fill current blank with provided option
|
|
60
|
-
*
|
|
61
|
-
* @param {*} blanks
|
|
62
|
-
* @param {*} options
|
|
63
|
-
* @param {*} current
|
|
64
|
-
*/
|
|
65
|
-
function fill(blanks, options, current) {
|
|
66
|
-
if (current > -1 && current < Object.keys(blanks).length) {
|
|
67
|
-
let index = options.findIndex(({ actualIndex }) => actualIndex == current)
|
|
68
|
-
if (index > -1) {
|
|
69
|
-
blanks[current].innerHTML = options[index].value
|
|
70
|
-
blanks[current].classList.remove('empty')
|
|
71
|
-
blanks[current].classList.add('filled')
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Clear all fillable elements
|
|
78
|
-
*
|
|
79
|
-
* @param {*} event
|
|
80
|
-
* @param {*} node
|
|
81
|
-
*/
|
|
82
|
-
function clear(event, node) {
|
|
83
|
-
event.target.innerHTML = '?'
|
|
84
|
-
event.target.classList.remove('filled')
|
|
85
|
-
event.target.classList.remove('pass')
|
|
86
|
-
event.target.classList.remove('fail')
|
|
87
|
-
event.target.classList.add('empty')
|
|
88
|
-
node.dispatchEvent(
|
|
89
|
-
new CustomEvent('remove', {
|
|
90
|
-
detail: {
|
|
91
|
-
index: event.target.name.split('-')[1],
|
|
92
|
-
value: event.target['data-index']
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Validate the filled values
|
|
100
|
-
*
|
|
101
|
-
* @param {*} blanks
|
|
102
|
-
* @param {*} data
|
|
103
|
-
*/
|
|
104
|
-
function validate(blanks, data) {
|
|
105
|
-
Object.keys(blanks).map((ref) => {
|
|
106
|
-
let index = data.options.findIndex(({ actualIndex }) => actualIndex == ref)
|
|
107
|
-
if (index > -1)
|
|
108
|
-
blanks[ref].classList.add(
|
|
109
|
-
data.options[index].expectedIndex == data.options[index].actualIndex
|
|
110
|
-
? 'pass'
|
|
111
|
-
: 'fail'
|
|
112
|
-
)
|
|
113
|
-
})
|
|
114
|
-
}
|