@rokkit/ui 1.0.0-next.107 → 1.0.0-next.108
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/dist/index.d.ts +0 -1
- package/package.json +1 -1
- package/src/Accordion.svelte +37 -33
- package/src/Icon.svelte +1 -0
- package/src/Link.svelte +2 -2
- package/src/List.svelte +23 -26
- package/src/ListBody.svelte +43 -0
- package/src/NestedList.svelte +57 -13
- package/src/Node.svelte +37 -21
- package/src/RadioGroup.svelte +3 -2
- package/src/ResponsiveGrid.svelte +1 -1
- package/src/Switch.svelte +8 -5
- package/src/TableCell.svelte +1 -1
- package/src/Tabs.svelte +13 -10
- package/src/Toggle.svelte +7 -7
- package/src/Tree.svelte +31 -12
- package/src/TreeTable.svelte +1 -1
- package/src/index.js +0 -1
- package/src/lib/tree.js +1 -1
- package/src/wrappers/Category.svelte +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,6 @@ export { default as Toggle } from "./Toggle.svelte";
|
|
|
22
22
|
export { default as Switch } from "./Switch.svelte";
|
|
23
23
|
export { default as List } from "./List.svelte";
|
|
24
24
|
export { default as Accordion } from "./Accordion.svelte";
|
|
25
|
-
export { default as NestedList } from "./NestedList.svelte";
|
|
26
25
|
export { default as Tree } from "./Tree.svelte";
|
|
27
26
|
export { default as Tabs } from "./Tabs.svelte";
|
|
28
27
|
export { default as Select } from "./Select.svelte";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rokkit/ui",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.108",
|
|
4
4
|
"description": "Organisms are larger, more complex building blocks that are composed of multiple molecules",
|
|
5
5
|
"author": "Jerry Thomas <me@jerrythomas.name>",
|
|
6
6
|
"license": "MIT",
|
package/src/Accordion.svelte
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { equals } from 'ramda'
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
createEmitter,
|
|
5
|
+
noop,
|
|
6
|
+
getKeyFromPath,
|
|
7
|
+
getSnippet,
|
|
8
|
+
defaultFields,
|
|
9
|
+
hasChildren
|
|
10
|
+
} from '@rokkit/core'
|
|
11
|
+
import { NestedController } from '@rokkit/states'
|
|
5
12
|
import { navigator } from '@rokkit/actions'
|
|
6
13
|
import Summary from './Summary.svelte'
|
|
7
14
|
import Item from './Item.svelte'
|
|
15
|
+
import ListBody from './ListBody.svelte'
|
|
8
16
|
|
|
9
17
|
/**
|
|
10
18
|
* @typedef {Object} Props
|
|
@@ -35,39 +43,25 @@
|
|
|
35
43
|
let emitter = $derived(
|
|
36
44
|
createEmitter(events, ['collapse', 'change', 'expand', 'click', 'select', 'move'])
|
|
37
45
|
)
|
|
38
|
-
let wrapper = new
|
|
46
|
+
let wrapper = new NestedController(items, value, fields, {
|
|
47
|
+
events,
|
|
48
|
+
multiselect,
|
|
49
|
+
autoCloseSiblings
|
|
50
|
+
})
|
|
51
|
+
let derivedFields = $derived({ ...defaultFields, ...fields })
|
|
39
52
|
</script>
|
|
40
53
|
|
|
41
|
-
{#snippet listItems(nodes, onchange = noop)}
|
|
42
|
-
{#each nodes as node}
|
|
43
|
-
{@const template = getSnippet(extra, node.get('component')) ?? stub}
|
|
44
|
-
{@const path = getKeyFromPath(node.path)}
|
|
45
|
-
{@const props = node.get('props') || {}}
|
|
46
|
-
<rk-list-item
|
|
47
|
-
role="option"
|
|
48
|
-
data-path={path}
|
|
49
|
-
aria-selected={node.selected}
|
|
50
|
-
aria-current={node.focused}
|
|
51
|
-
>
|
|
52
|
-
{#if template}
|
|
53
|
-
{@render template(node, props, onchange)}
|
|
54
|
-
{:else}
|
|
55
|
-
<Item value={node.value} fields={node.fields} />
|
|
56
|
-
{/if}
|
|
57
|
-
</rk-list-item>
|
|
58
|
-
{/each}
|
|
59
|
-
{/snippet}
|
|
60
54
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
61
55
|
<rk-accordion
|
|
62
56
|
class={classes}
|
|
63
57
|
tabindex="0"
|
|
64
|
-
use:navigator={{ wrapper }}
|
|
58
|
+
use:navigator={{ wrapper, nested: true }}
|
|
65
59
|
onactivate={() => (value = wrapper.value)}
|
|
66
60
|
>
|
|
67
61
|
{#if header}
|
|
68
62
|
<rk-header>{@render header()}</rk-header>
|
|
69
63
|
{/if}
|
|
70
|
-
{#if
|
|
64
|
+
{#if items.length === 0}
|
|
71
65
|
<rk-list-item role="presentation">
|
|
72
66
|
{#if empty}
|
|
73
67
|
{@render empty()}
|
|
@@ -76,22 +70,32 @@
|
|
|
76
70
|
{/if}
|
|
77
71
|
</rk-list-item>
|
|
78
72
|
{/if}
|
|
79
|
-
{#each
|
|
73
|
+
{#each items as item, index}
|
|
74
|
+
{@const key = `${index}`}
|
|
75
|
+
{@const expanded = item[derivedFields.expanded]}
|
|
80
76
|
<div
|
|
81
77
|
class="flex flex-col"
|
|
82
|
-
class:is-expanded={
|
|
83
|
-
class:is-selected={
|
|
78
|
+
class:is-expanded={expanded}
|
|
79
|
+
class:is-selected={wrapper.selectedKeys.has(key)}
|
|
84
80
|
data-path={index}
|
|
85
81
|
>
|
|
86
82
|
<Summary
|
|
87
|
-
bind:value={
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
hasChildren={
|
|
83
|
+
bind:value={items[index]}
|
|
84
|
+
{fields}
|
|
85
|
+
{expanded}
|
|
86
|
+
hasChildren={hasChildren(item, derivedFields)}
|
|
91
87
|
/>
|
|
92
|
-
{#if
|
|
88
|
+
{#if expanded}
|
|
93
89
|
<rk-list role="listbox" tabindex="-1">
|
|
94
|
-
|
|
90
|
+
<ListBody
|
|
91
|
+
bind:items={items[fields.children]}
|
|
92
|
+
bind:value
|
|
93
|
+
fields={fields.fields ?? fields}
|
|
94
|
+
{selected}
|
|
95
|
+
{stub}
|
|
96
|
+
onchange={emitter.change}
|
|
97
|
+
{extra}
|
|
98
|
+
/>
|
|
95
99
|
</rk-list>
|
|
96
100
|
{/if}
|
|
97
101
|
</div>
|
package/src/Icon.svelte
CHANGED
package/src/Link.svelte
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
/** @type {Props} */
|
|
14
14
|
let { class: classes = '', value, mapping = new FieldMapper(), href = '#', ...rest } = $props()
|
|
15
|
-
let url = $derived(mapping.
|
|
16
|
-
let props = $derived({ ...mapping.
|
|
15
|
+
let url = $derived(mapping.get('url', value, href))
|
|
16
|
+
let props = $derived({ ...mapping.get('props', value, {}), ...rest })
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
19
|
<a href={url} class={classes} {...props}>
|
package/src/List.svelte
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEmitter
|
|
2
|
+
import { createEmitter } from '@rokkit/core'
|
|
3
3
|
import { navigator } from '@rokkit/actions'
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import ListBody from './ListBody.svelte'
|
|
5
|
+
import { ListController } from '@rokkit/states'
|
|
6
6
|
import { omit, has } from 'ramda'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -34,17 +34,21 @@
|
|
|
34
34
|
...events
|
|
35
35
|
} = $props()
|
|
36
36
|
|
|
37
|
+
let selected = $state([])
|
|
38
|
+
|
|
37
39
|
function handleAction(event) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (has(
|
|
41
|
-
|
|
40
|
+
const { name, data } = event.detail
|
|
41
|
+
|
|
42
|
+
if (has(name, emitter)) {
|
|
43
|
+
value = data.value
|
|
44
|
+
selected = data.selected
|
|
45
|
+
emitter[name](data)
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
let emitter = createEmitter(events, ['select', 'change', 'move'])
|
|
46
50
|
let extra = omit(['onselect', 'onchange', 'onmove'], events)
|
|
47
|
-
let wrapper = new
|
|
51
|
+
let wrapper = new ListController(items, value, fields, { multiSelect })
|
|
48
52
|
</script>
|
|
49
53
|
|
|
50
54
|
<rk-list
|
|
@@ -59,30 +63,23 @@
|
|
|
59
63
|
<rk-header>{@render header()}</rk-header>
|
|
60
64
|
{/if}
|
|
61
65
|
<rk-body>
|
|
62
|
-
{#if
|
|
66
|
+
{#if items.length === 0}
|
|
63
67
|
{#if empty}
|
|
64
68
|
{@render empty()}
|
|
65
69
|
{:else}
|
|
66
70
|
<rk-message>No items found.</rk-message>
|
|
67
71
|
{/if}
|
|
68
72
|
{:else}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{#if template}
|
|
80
|
-
{@render template(node, props, emitter.change)}
|
|
81
|
-
{:else}
|
|
82
|
-
<Item value={node.value} fields={node.fields} />
|
|
83
|
-
{/if}
|
|
84
|
-
</rk-list-item>
|
|
85
|
-
{/each}
|
|
73
|
+
<ListBody
|
|
74
|
+
bind:items
|
|
75
|
+
bind:value
|
|
76
|
+
{fields}
|
|
77
|
+
selectedKeys={wrapper.selectedKeys}
|
|
78
|
+
focusedKey={wrapper.focusedKey}
|
|
79
|
+
{stub}
|
|
80
|
+
onchange={emitter.change}
|
|
81
|
+
{extra}
|
|
82
|
+
/>
|
|
86
83
|
{/if}
|
|
87
84
|
</rk-body>
|
|
88
85
|
{#if footer}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getKeyFromPath, FieldMapper, getSnippet } from '@rokkit/core'
|
|
3
|
+
import Item from './Item.svelte'
|
|
4
|
+
import { equals } from 'ramda'
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
items = $bindable([]),
|
|
8
|
+
value = null,
|
|
9
|
+
fields,
|
|
10
|
+
path = [],
|
|
11
|
+
onchange = () => {},
|
|
12
|
+
selectedKeys = new SvelteSet(),
|
|
13
|
+
focusedKey = null,
|
|
14
|
+
stub = null,
|
|
15
|
+
extra
|
|
16
|
+
} = $props()
|
|
17
|
+
let fm = $derived.by(() => {
|
|
18
|
+
return new FieldMapper(fields)
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#each items as item, index}
|
|
23
|
+
{@const template = getSnippet(extra, fm.get('snippet', item, stub))}
|
|
24
|
+
{@const pathKey = getKeyFromPath([...path, index])}
|
|
25
|
+
{@const props = fm.get('props', item) || {}}
|
|
26
|
+
<rk-list-item
|
|
27
|
+
role="option"
|
|
28
|
+
data-path={pathKey}
|
|
29
|
+
aria-selected={selectedKeys.has(pathKey)}
|
|
30
|
+
aria-current={focusedKey === pathKey}
|
|
31
|
+
>
|
|
32
|
+
<svelte:boundary>
|
|
33
|
+
{#if template}
|
|
34
|
+
{@render template(item, props, onchange)}
|
|
35
|
+
{#snippet failed()}
|
|
36
|
+
<Item value={item} {fields} />
|
|
37
|
+
{/snippet}
|
|
38
|
+
{:else}
|
|
39
|
+
<Item value={item} {fields} />
|
|
40
|
+
{/if}
|
|
41
|
+
</svelte:boundary>
|
|
42
|
+
</rk-list-item>
|
|
43
|
+
{/each}
|
package/src/NestedList.svelte
CHANGED
|
@@ -1,33 +1,77 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
2
|
+
import { SvelteSet } from 'svelte/reactivity'
|
|
3
|
+
import {
|
|
4
|
+
defaultStateIcons,
|
|
5
|
+
getLineTypes,
|
|
6
|
+
getKeyFromPath,
|
|
7
|
+
getNestedFields,
|
|
8
|
+
hasChildren
|
|
9
|
+
} from '@rokkit/core'
|
|
3
10
|
import Node from './Node.svelte'
|
|
4
11
|
import NestedList from './NestedList.svelte'
|
|
5
12
|
|
|
6
13
|
/**
|
|
7
14
|
* @typedef {Object} Props
|
|
8
|
-
* @property {Array<NodeProxy>}
|
|
9
|
-
* @property {
|
|
10
|
-
* @property {
|
|
11
|
-
* @property {
|
|
15
|
+
* @property {Array<NodeProxy>} [items=[]]
|
|
16
|
+
* @property {any} [value=null]
|
|
17
|
+
* @property {import('./types').FieldMapping} fields
|
|
18
|
+
* @property {number[]} [path=[]]
|
|
19
|
+
* @property {import('./types').NodeStateIcons} icons
|
|
20
|
+
* @property {import('./types').ConnectionType[]} [types=[]]
|
|
21
|
+
* @property {string} [focusedKey]
|
|
22
|
+
* @property {SvelteSet} [selectedKeys]
|
|
12
23
|
*/
|
|
13
24
|
|
|
14
25
|
/** @type {Props} */
|
|
15
|
-
let {
|
|
26
|
+
let {
|
|
27
|
+
items = $bindable([]),
|
|
28
|
+
value = $bindable(null),
|
|
29
|
+
fields,
|
|
30
|
+
path = [],
|
|
31
|
+
icons = {},
|
|
32
|
+
types = [],
|
|
33
|
+
focusedKey,
|
|
34
|
+
selectedKeys = new SvelteSet(),
|
|
35
|
+
stub,
|
|
36
|
+
snippets
|
|
37
|
+
} = $props()
|
|
16
38
|
|
|
17
39
|
const stateIcons = $derived({ ...defaultStateIcons.node, ...icons })
|
|
40
|
+
const childFields = $derived(getNestedFields(fields))
|
|
41
|
+
// $inspect(childFields, items[0], expandedKeys)
|
|
18
42
|
</script>
|
|
19
43
|
|
|
20
44
|
<rk-nested-list role="tree">
|
|
21
45
|
{#each items as item, index}
|
|
22
|
-
{@const
|
|
46
|
+
{@const nodePath = [...path, index]}
|
|
47
|
+
{@const key = getKeyFromPath(nodePath)}
|
|
48
|
+
{@const expanded = item[fields.expanded]}
|
|
23
49
|
{@const nodeType = index === items.length - 1 ? 'last' : 'child'}
|
|
24
|
-
{@const connectors = getLineTypes(hasChildren, types, nodeType)}
|
|
50
|
+
{@const connectors = getLineTypes(hasChildren(item, fields), types, nodeType)}
|
|
25
51
|
|
|
26
|
-
<Node
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
52
|
+
<Node
|
|
53
|
+
value={item}
|
|
54
|
+
{fields}
|
|
55
|
+
{stateIcons}
|
|
56
|
+
types={connectors}
|
|
57
|
+
focused={focusedKey === key}
|
|
58
|
+
selected={selectedKeys.has(key)}
|
|
59
|
+
{expanded}
|
|
60
|
+
path={nodePath}
|
|
61
|
+
{stub}
|
|
62
|
+
{snippets}
|
|
63
|
+
>
|
|
64
|
+
{#if hasChildren(item, fields) && expanded}
|
|
65
|
+
<NestedList
|
|
66
|
+
items={item[fields.children]}
|
|
67
|
+
{value}
|
|
68
|
+
fields={childFields}
|
|
69
|
+
path={nodePath}
|
|
70
|
+
icons={stateIcons}
|
|
71
|
+
types={connectors}
|
|
72
|
+
{focusedKey}
|
|
73
|
+
{selectedKeys}
|
|
74
|
+
/>
|
|
31
75
|
{/if}
|
|
32
76
|
</Node>
|
|
33
77
|
{/each}
|
package/src/Node.svelte
CHANGED
|
@@ -5,41 +5,52 @@
|
|
|
5
5
|
import Item from './Item.svelte'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* @typedef {Object}
|
|
9
|
-
* @property {any}
|
|
10
|
-
* @property {
|
|
8
|
+
* @typedef {Object} Props
|
|
9
|
+
* @property {any} value
|
|
10
|
+
* @property {import('./types').FieldMapping} fields
|
|
11
|
+
* @property {any} [types]
|
|
11
12
|
* @property {import('./types').NodeStateIcons} [stateIcons]
|
|
13
|
+
* @property {number[]} [path=[]]
|
|
14
|
+
* @property {boolean} [focused=false]
|
|
15
|
+
* @property {boolean} [selected=false]
|
|
16
|
+
* @property {boolean} [expanded=false]
|
|
17
|
+
* @property {Function} [children]
|
|
18
|
+
* @property {Function} [stub=null]
|
|
19
|
+
* @property {Object<string, Function>} [snippets={}]
|
|
12
20
|
*/
|
|
13
21
|
|
|
14
22
|
/** @type {Props} */
|
|
15
23
|
let {
|
|
16
|
-
value = $bindable(),
|
|
24
|
+
value = $bindable(null),
|
|
25
|
+
fields,
|
|
17
26
|
types = [],
|
|
18
27
|
stateIcons = defaultStateIcons.node,
|
|
19
|
-
|
|
28
|
+
path = [],
|
|
29
|
+
focused = false,
|
|
30
|
+
selected = false,
|
|
31
|
+
expanded = false,
|
|
20
32
|
children,
|
|
21
|
-
|
|
33
|
+
stub = null,
|
|
34
|
+
snippets = {}
|
|
22
35
|
} = $props()
|
|
23
36
|
|
|
37
|
+
let stateName = $derived(expanded ? 'opened' : 'closed')
|
|
24
38
|
let icons = $derived({ ...defaultStateIcons.node, ...stateIcons })
|
|
25
|
-
let stateName = $derived(value.expanded ? 'opened' : 'closed')
|
|
26
39
|
let state = $derived(
|
|
27
|
-
|
|
28
|
-
? { icon: icons.opened, label: 'collapse' }
|
|
29
|
-
: { icon: icons.closed, label: 'expand' }
|
|
40
|
+
expanded ? { icon: icons.opened, label: 'collapse' } : { icon: icons.closed, label: 'expand' }
|
|
30
41
|
)
|
|
31
42
|
|
|
32
|
-
const template = getSnippet(value.
|
|
33
|
-
|
|
43
|
+
const template = getSnippet(value[fields.snippet], snippets, stub)
|
|
44
|
+
$inspect(template)
|
|
34
45
|
</script>
|
|
35
46
|
|
|
36
47
|
<rk-node
|
|
37
|
-
aria-current={
|
|
38
|
-
aria-selected={
|
|
39
|
-
aria-expanded={
|
|
48
|
+
aria-current={focused}
|
|
49
|
+
aria-selected={selected}
|
|
50
|
+
aria-expanded={expanded}
|
|
40
51
|
role="treeitem"
|
|
41
|
-
data-path={getKeyFromPath(
|
|
42
|
-
data-depth={
|
|
52
|
+
data-path={getKeyFromPath(path)}
|
|
53
|
+
data-depth={path.length}
|
|
43
54
|
>
|
|
44
55
|
<div class="flex flex-row items-center">
|
|
45
56
|
{#each types as type}
|
|
@@ -50,11 +61,16 @@
|
|
|
50
61
|
{/if}
|
|
51
62
|
{/each}
|
|
52
63
|
<rk-item>
|
|
53
|
-
|
|
64
|
+
<svelte:boundary>
|
|
65
|
+
<!-- {#if template} -->
|
|
54
66
|
{@render template(value)}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
{#snippet failed()}
|
|
68
|
+
<Item {value} {fields} />
|
|
69
|
+
{/snippet}
|
|
70
|
+
<!-- {:else}
|
|
71
|
+
<Item {value} {fields} />
|
|
72
|
+
{/if} -->
|
|
73
|
+
</svelte:boundary>
|
|
58
74
|
</rk-item>
|
|
59
75
|
</div>
|
|
60
76
|
{@render children?.()}
|
package/src/RadioGroup.svelte
CHANGED
|
@@ -38,8 +38,9 @@
|
|
|
38
38
|
class:disabled={readOnly}
|
|
39
39
|
>
|
|
40
40
|
{#each options as item}
|
|
41
|
-
{@const
|
|
42
|
-
{@const
|
|
41
|
+
{@const label = mapping.get('text', item)}
|
|
42
|
+
{@const itemValue = mapping.get('value', item, label)}
|
|
43
|
+
|
|
43
44
|
{@const state = equals(itemValue, value) ? 'on' : 'off'}
|
|
44
45
|
|
|
45
46
|
<label class="flex {flexDirection} items-center gap-2">
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
>
|
|
66
66
|
{#each items as item, index}
|
|
67
67
|
{@const segmentClass = 'col-' + (index + 1)}
|
|
68
|
-
{@const props = mapping.
|
|
68
|
+
{@const props = mapping.get('props', item, {})}
|
|
69
69
|
{@const Template = item[mapping.fields.component]}
|
|
70
70
|
{#if small && equals(index, activeIndex)}
|
|
71
71
|
<rk-segment
|
package/src/Switch.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { equals } from 'ramda'
|
|
3
|
-
import { noop } from '@rokkit/core'
|
|
3
|
+
import { noop, getSnippet, FieldMapper } from '@rokkit/core'
|
|
4
4
|
import { keyboard } from '@rokkit/actions'
|
|
5
5
|
import { defaultMapping } from './constants'
|
|
6
6
|
|
|
@@ -19,10 +19,12 @@
|
|
|
19
19
|
class: classes = '',
|
|
20
20
|
value = $bindable(),
|
|
21
21
|
options = [false, true],
|
|
22
|
-
|
|
22
|
+
fields,
|
|
23
23
|
compact = false,
|
|
24
24
|
disabled = false,
|
|
25
|
-
onchange = noop
|
|
25
|
+
onchange = noop,
|
|
26
|
+
stub,
|
|
27
|
+
...extra
|
|
26
28
|
} = $props()
|
|
27
29
|
|
|
28
30
|
let cursor = $state([])
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
prev: ['ArrowLeft', 'ArrowUp']
|
|
51
53
|
}
|
|
52
54
|
let useComponent = $derived(!options.every((item) => [false, true].includes(item)))
|
|
55
|
+
let mapper = new FieldMapper(fields)
|
|
53
56
|
</script>
|
|
54
57
|
|
|
55
58
|
{#if !Array.isArray(options) || options.length < 2}
|
|
@@ -72,13 +75,13 @@
|
|
|
72
75
|
onclick={handleClick}
|
|
73
76
|
>
|
|
74
77
|
{#each options as item, index (item)}
|
|
75
|
-
{@const Template =
|
|
78
|
+
{@const Template = getSnippet(extra, mapper.get('snippet', item), stub)}
|
|
76
79
|
<rk-item class="relative" role="option" aria-selected={equals(item, value)} data-path={index}>
|
|
77
80
|
{#if equals(item, value)}
|
|
78
81
|
<rk-indicator class="absolute bottom-0 left-0 right-0 top-0"></rk-indicator>
|
|
79
82
|
{/if}
|
|
80
83
|
{#if Template}
|
|
81
|
-
<Template value={item} {
|
|
84
|
+
<Template value={item} {fields} />
|
|
82
85
|
{/if}
|
|
83
86
|
</rk-item>
|
|
84
87
|
{/each}
|
package/src/TableCell.svelte
CHANGED
package/src/Tabs.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { defaultFields, defaultStateIcons, noop, getSnippet } from '@rokkit/core'
|
|
3
|
-
import {
|
|
2
|
+
import { defaultFields, defaultStateIcons, noop, getSnippet, FieldMapper } from '@rokkit/core'
|
|
3
|
+
import { ListController } from '@rokkit/states'
|
|
4
4
|
import { navigator } from '@rokkit/actions'
|
|
5
5
|
import Icon from './Icon.svelte'
|
|
6
6
|
import Item from './Item.svelte'
|
|
@@ -34,8 +34,6 @@
|
|
|
34
34
|
...extra
|
|
35
35
|
} = $props()
|
|
36
36
|
|
|
37
|
-
let cursor = $state([])
|
|
38
|
-
|
|
39
37
|
function handleRemove(event) {
|
|
40
38
|
if (typeof event.detail === Object) {
|
|
41
39
|
event.detail[fields.isDeleted] = true
|
|
@@ -56,8 +54,9 @@
|
|
|
56
54
|
onselect({ item: value, indices: cursor })
|
|
57
55
|
}
|
|
58
56
|
let stateIcons = $derived({ ...defaultStateIcons.action, ...icons })
|
|
59
|
-
let filtered = $derived(options.filter((item) => !item[fields.
|
|
60
|
-
let wrapper = new
|
|
57
|
+
let filtered = $derived(options.filter((item) => !item[fields.deleted]))
|
|
58
|
+
let wrapper = $derived(new ListController(options, value, fields))
|
|
59
|
+
let mapper = new FieldMapper(fields)
|
|
61
60
|
</script>
|
|
62
61
|
|
|
63
62
|
<rk-tabs
|
|
@@ -67,15 +66,19 @@
|
|
|
67
66
|
class:justify-end={align === 'right'}
|
|
68
67
|
tabindex="0"
|
|
69
68
|
role="listbox"
|
|
70
|
-
use:navigator={{ wrapper }}
|
|
69
|
+
use:navigator={{ wrapper, horizontal: true }}
|
|
71
70
|
onaction={handleNav}
|
|
72
71
|
onremove={handleRemove}
|
|
73
72
|
onadd={handleAdd}
|
|
74
73
|
>
|
|
75
|
-
{#each
|
|
76
|
-
{@const Template = getSnippet(extra,
|
|
74
|
+
{#each filtered as item, index}
|
|
75
|
+
{@const Template = getSnippet(extra, mapper.get('snippet', item), stub)}
|
|
77
76
|
<rk-tab>
|
|
78
|
-
|
|
77
|
+
{#if Template}
|
|
78
|
+
<Template value={item} {fields} />
|
|
79
|
+
{:else}
|
|
80
|
+
<Item value={item} {fields} />
|
|
81
|
+
{/if}
|
|
79
82
|
{#if editable}
|
|
80
83
|
<Icon
|
|
81
84
|
name="remove"
|
package/src/Toggle.svelte
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { FieldMapper, noop } from '@rokkit/core'
|
|
2
|
+
// import { FieldMapper, noop } from '@rokkit/core'
|
|
3
3
|
import { keyboard } from '@rokkit/actions'
|
|
4
4
|
import Item from './Item.svelte'
|
|
5
|
-
import { defaultMapping } from './constants'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* @typedef {Object} Props
|
|
@@ -17,8 +16,9 @@
|
|
|
17
16
|
class: classes = '',
|
|
18
17
|
value = $bindable(null),
|
|
19
18
|
options = [false, true],
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
fields,
|
|
20
|
+
label = 'toggle',
|
|
21
|
+
onchange
|
|
22
22
|
} = $props()
|
|
23
23
|
|
|
24
24
|
const keyMappings = {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
value = options[nextIndex]
|
|
40
|
-
onchange(value)
|
|
40
|
+
onchange?.(value)
|
|
41
41
|
}
|
|
42
42
|
</script>
|
|
43
43
|
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
onnext={() => toggle()}
|
|
48
48
|
onprev={() => toggle(-1)}
|
|
49
49
|
onclick={() => toggle()}
|
|
50
|
-
aria-label={
|
|
50
|
+
aria-label={label}
|
|
51
51
|
>
|
|
52
|
-
<Item {value} {
|
|
52
|
+
<Item {value} {fields} />
|
|
53
53
|
</button>
|
|
54
54
|
</rk-toggle>
|
package/src/Tree.svelte
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEmitter } from '@rokkit/core'
|
|
2
|
+
import { createEmitter, defaultFields } from '@rokkit/core'
|
|
3
3
|
import { navigator } from '@rokkit/actions'
|
|
4
4
|
import NestedList from './NestedList.svelte'
|
|
5
|
-
import {
|
|
5
|
+
import { NestedController } from '@rokkit/states'
|
|
6
6
|
import { omit, has } from 'ramda'
|
|
7
7
|
/**
|
|
8
8
|
* @typedef {Object} Props
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
* @property {import('./types').NodeStateIcons|Object} [icons]
|
|
14
14
|
* @property {boolean} [autoCloseSiblings=false]
|
|
15
15
|
* @property {boolean} [multiselect=false]
|
|
16
|
+
* @property {Function} [header]
|
|
17
|
+
* @property {Function} [footer]
|
|
18
|
+
* @property {Function} [empty]
|
|
19
|
+
* @property {Function} [stub]
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
22
|
/** @type {Props & { [key: string]: any }} */
|
|
@@ -24,37 +28,52 @@
|
|
|
24
28
|
icons = {},
|
|
25
29
|
autoCloseSiblings = false,
|
|
26
30
|
multiselect = false,
|
|
27
|
-
keys = null,
|
|
28
31
|
header,
|
|
29
32
|
footer,
|
|
30
33
|
empty,
|
|
34
|
+
stub,
|
|
31
35
|
...events
|
|
32
36
|
} = $props()
|
|
33
37
|
|
|
34
|
-
let emitter = createEmitter(events, ['select', 'move', '
|
|
35
|
-
let wrapper = new
|
|
38
|
+
let emitter = createEmitter(events, ['select', 'move', 'toggle'])
|
|
39
|
+
let wrapper = new NestedController(items, value, fields, { autoCloseSiblings, multiselect })
|
|
40
|
+
let snippets = omit(['onselect', 'onmove', 'ontoggle'], events)
|
|
41
|
+
let derivedFields = $derived({ ...defaultFields, ...fields })
|
|
36
42
|
|
|
37
43
|
function handleAction(event) {
|
|
38
|
-
const {
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
if (has([eventName], emitter)) emitter[eventName](data)
|
|
44
|
+
const { name, data } = event.detail
|
|
45
|
+
if (name === 'select') value = data.value
|
|
46
|
+
if (has([name], emitter)) emitter[name](data)
|
|
42
47
|
}
|
|
43
48
|
</script>
|
|
44
49
|
|
|
45
50
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
46
|
-
<rk-tree
|
|
51
|
+
<rk-tree
|
|
52
|
+
tabindex="0"
|
|
53
|
+
class={classes}
|
|
54
|
+
use:navigator={{ wrapper, nested: true }}
|
|
55
|
+
onaction={handleAction}
|
|
56
|
+
>
|
|
47
57
|
{#if header}
|
|
48
58
|
<rk-header>{@render header()}</rk-header>
|
|
49
59
|
{/if}
|
|
50
|
-
{#if
|
|
60
|
+
{#if items.length === 0}
|
|
51
61
|
{#if empty}
|
|
52
62
|
{@render empty()}
|
|
53
63
|
{:else}
|
|
54
64
|
<div class="m-auto p-4 text-center text-gray-500">No data available</div>
|
|
55
65
|
{/if}
|
|
56
66
|
{/if}
|
|
57
|
-
<NestedList
|
|
67
|
+
<NestedList
|
|
68
|
+
{items}
|
|
69
|
+
fields={derivedFields}
|
|
70
|
+
{value}
|
|
71
|
+
{icons}
|
|
72
|
+
focusedKey={wrapper.currentKey}
|
|
73
|
+
selectedKeys={wrapper.selectedKeys}
|
|
74
|
+
{stub}
|
|
75
|
+
{snippets}
|
|
76
|
+
/>
|
|
58
77
|
{#if footer}
|
|
59
78
|
<rk-footer>{@render footer()}</rk-footer>
|
|
60
79
|
{/if}
|
package/src/TreeTable.svelte
CHANGED
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
>
|
|
135
135
|
{#each columns as col, index}
|
|
136
136
|
{@const value = { ...pick(['icon'], col), ...item }}
|
|
137
|
-
{@const SvelteComponent = mapping.
|
|
137
|
+
{@const SvelteComponent = mapping.get('component', item)}
|
|
138
138
|
<td>
|
|
139
139
|
<cell>
|
|
140
140
|
{#if multiselect && index === 0}
|
package/src/index.js
CHANGED
|
@@ -25,7 +25,6 @@ export { default as Toggle } from './Toggle.svelte'
|
|
|
25
25
|
export { default as Switch } from './Switch.svelte'
|
|
26
26
|
export { default as List } from './List.svelte'
|
|
27
27
|
export { default as Accordion } from './Accordion.svelte'
|
|
28
|
-
export { default as NestedList } from './NestedList.svelte'
|
|
29
28
|
export { default as Tree } from './Tree.svelte'
|
|
30
29
|
export { default as Tabs } from './Tabs.svelte'
|
|
31
30
|
export { default as Select } from './Select.svelte'
|
package/src/lib/tree.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
-
import { defaultFields, FieldMapper } from '@rokkit/core'
|
|
4
3
|
|
|
5
4
|
const registry = getContext('registry')
|
|
6
5
|
|
|
7
6
|
let {
|
|
8
7
|
class: className = '',
|
|
9
8
|
options = [],
|
|
10
|
-
fields
|
|
9
|
+
fields,
|
|
11
10
|
navigator = 'tabs',
|
|
12
11
|
type = 'vertical',
|
|
13
12
|
category = null,
|
|
@@ -19,7 +18,9 @@
|
|
|
19
18
|
</script>
|
|
20
19
|
|
|
21
20
|
<section class={className}>
|
|
22
|
-
|
|
21
|
+
{#if Template}
|
|
22
|
+
<Template {options} {fields} bind:value={category} {...restProps} />
|
|
23
|
+
{/if}
|
|
23
24
|
<field-layout class={type}>
|
|
24
25
|
{@render children?.()}
|
|
25
26
|
</field-layout>
|