@rokkit/ui 1.0.0-next.120 → 1.0.0-next.122

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/README.md CHANGED
@@ -113,7 +113,7 @@ bun add @rokkit/ui
113
113
  - @rokkit/actions
114
114
  - @rokkit/core
115
115
  - @rokkit/data
116
- - @rokkit/input
116
+ - @rokkit/forms
117
117
  - @rokkit/states
118
118
  - d3-scale
119
119
  - date-fns
package/dist/index.d.ts CHANGED
@@ -33,11 +33,6 @@ export { default as ToggleThemeMode } from "./ToggleThemeMode.svelte";
33
33
  export { default as Overlay } from "./Overlay.svelte";
34
34
  export { default as Message } from "./Message.svelte";
35
35
  export { default as SlidingColumns } from "./SlidingColumns.svelte";
36
- export { default as InputField } from "./input/InputField.svelte";
37
- export { default as Form } from "./Form.svelte";
38
- export { default as FieldLayout } from "./FieldLayout.svelte";
39
- export { default as DataEditor } from "./DataEditor.svelte";
40
- export { default as NestedEditor } from "./NestedEditor.svelte";
41
36
  export { default as Stepper } from "./Stepper.svelte";
42
37
  export { default as ProgressDots } from "./ProgressDots.svelte";
43
38
  export { default as Card } from "./Card.svelte";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/ui",
3
- "version": "1.0.0-next.120",
3
+ "version": "1.0.0-next.122",
4
4
  "description": "Data driven UI components, improving DX",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "@rokkit/actions": "latest",
35
35
  "@rokkit/core": "latest",
36
36
  "@rokkit/data": "latest",
37
- "@rokkit/input": "latest",
37
+ "@rokkit/forms": "latest",
38
38
  "@rokkit/states": "latest",
39
39
  "d3-scale": "^4.0.2",
40
40
  "date-fns": "^4.1.0",
@@ -1,7 +1,7 @@
1
1
  <script>
2
- import { getSnippet } from '@rokkit/core'
3
2
  import Item from './Item.svelte'
4
-
3
+ import Icon from './Icon.svelte'
4
+ import { Proxy } from '@rokkit/states'
5
5
  /**
6
6
  * @typedef {Object} Props
7
7
  * @property {string} [class]
@@ -12,26 +12,21 @@
12
12
  */
13
13
 
14
14
  /** @type {Props} */
15
- let { class: classes = '', items = [], separator = '/', fields, crumb } = $props()
15
+ let { class: classes = '', items = [], separator = '/', fields, child } = $props()
16
+ let childSnippet = $derived(child ? child : defaultChild)
16
17
  </script>
17
18
 
18
- <rk-crumbs class={classes}>
19
+ {#snippet defaultChild(proxy)}
20
+ <Item {proxy} />
21
+ {/snippet}
22
+ <div data-crumb-root class={classes}>
19
23
  {#each items as item, index (index)}
24
+ {@const proxy = new Proxy(item, fields)}
20
25
  {#if index > 0}
21
- <span>
22
- {#if separator.length === 1}
23
- {separator}
24
- {:else}
25
- <icon class={separator}></icon>
26
- {/if}
27
- </span>
26
+ <Icon name={separator} data-crumb-separator></Icon>
28
27
  {/if}
29
- <rk-crumb class:is-selected={index === items.length - 1}>
30
- {#if crumb}
31
- {@render crumb(item, fields)}
32
- {:else}
33
- <Item value={item} {fields} />
34
- {/if}
35
- </rk-crumb>
28
+ <div data-crumb-item class:is-selected={index === items.length - 1}>
29
+ {@render childSnippet?.(proxy)}
30
+ </div>
36
31
  {/each}
37
- </rk-crumbs>
32
+ </div>
package/src/Button.svelte CHANGED
@@ -25,16 +25,12 @@
25
25
  disabled = false,
26
26
  onclick
27
27
  } = $props()
28
-
29
- const primary = $derived(variant === 'primary')
30
- const secondary = $derived(variant === 'secondary')
31
- const tertiary = $derived(variant === 'tertiary')
32
28
  </script>
33
29
 
34
30
  <button
35
- class:primary
36
- class:secondary
37
- class:tertiary
31
+ data-button-root
32
+ data-variant={variant}
33
+ data-disabled={disabled}
38
34
  class={classes}
39
35
  {disabled}
40
36
  {type}
package/src/Icon.svelte CHANGED
@@ -1,5 +1,4 @@
1
1
  <script>
2
- import { createEmitter } from '@rokkit/core'
3
2
  /**
4
3
  * @typedef {Object} Props
5
4
  * @property {string} [class]
@@ -21,40 +20,41 @@
21
20
  let {
22
21
  ref = $bindable(),
23
22
  class: classes = '',
24
- name,
23
+ name = '?',
25
24
  state = null,
26
25
  size = 'base',
27
26
  role = 'img',
28
27
  label = null,
29
28
  disabled = false,
30
29
  tabindex = $bindable(0),
31
- checked = $bindable(null),
32
- ...events
30
+ checked = $bindable(),
31
+ onclick,
32
+ onchange,
33
+ onmouseenter,
34
+ onmouseleave,
35
+ ...restProps
33
36
  } = $props()
34
37
 
35
- let emitter = $derived(createEmitter(events, ['click', 'change', 'mouseenter', 'mouseleave']))
36
38
  function handleClick(e) {
37
39
  if (role === 'img') return
38
40
  e.preventDefault()
39
41
 
40
42
  if (!disabled) {
41
43
  if (isCheckbox) {
42
- checked = !checked
43
- emitter?.change(checked)
44
+ checked = !Boolean(checked)
45
+ onchange?.(checked)
44
46
  }
45
- emitter?.click()
47
+ onclick?.()
46
48
  }
47
49
  }
48
50
 
49
51
  let isCheckbox = $derived(role === 'checkbox' || role === 'option')
50
52
  let validatedTabindex = $derived(role === 'img' || disabled ? -1 : tabindex)
51
- let ariaChecked = $derived(
52
- ['checkbox', 'option'].includes(role) ? (checked !== null ? checked : false) : null
53
- )
53
+ let ariaChecked = $derived(['checkbox', 'option'].includes(role) && checked)
54
54
  </script>
55
55
 
56
56
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
57
- <rk-icon
57
+ <icon
58
58
  bind:this={ref}
59
59
  data-tag-icon
60
60
  data-state={state}
@@ -69,8 +69,13 @@
69
69
  onclick={handleClick}
70
70
  onkeydown={(e) => e.key === 'Enter' && e.currentTarget.click()}
71
71
  tabindex={validatedTabindex}
72
- onmouseenter={emitter.mouseenter}
73
- onnmouseleave={emitter.nmouseleave}
72
+ {onmouseenter}
73
+ {onmouseleave}
74
+ {...restProps}
74
75
  >
75
- <i class={name} aria-hidden="true"></i>
76
- </rk-icon>
76
+ {#if name.length <= 2}
77
+ <span>{name}</span>
78
+ {:else}
79
+ <i class={name} aria-hidden="true"></i>
80
+ {/if}
81
+ </icon>
package/src/Item.svelte CHANGED
@@ -7,12 +7,12 @@
7
7
  */
8
8
 
9
9
  /** @type {Props} */
10
- let { value, fields } = $props()
11
- let proxy = $derived(new Proxy(value, fields))
12
- let content = $derived(proxy.get('text'))
13
- let ariaLabel = $derived(proxy.get('label') ?? content)
14
- let icon = $derived(proxy.get('icon'))
15
- let image = $derived(proxy.get('image'))
10
+ let { value, fields, proxy = null } = $props()
11
+ let proxyItem = $derived(proxy ?? new Proxy(value, fields))
12
+ let content = $derived(proxyItem.get('text'))
13
+ let ariaLabel = $derived(proxyItem.get('label') ?? content)
14
+ let icon = $derived(proxyItem.get('icon'))
15
+ let image = $derived(proxyItem.get('image'))
16
16
  </script>
17
17
 
18
18
  {#if icon}
package/src/List.svelte CHANGED
@@ -52,7 +52,8 @@
52
52
  let wrapper = new ListController(items, value, fields, { multiSelect })
53
53
  </script>
54
54
 
55
- <rk-list
55
+ <div
56
+ data-list
56
57
  class={classes}
57
58
  role="listbox"
58
59
  aria-label={name}
@@ -61,14 +62,14 @@
61
62
  onaction={handleAction}
62
63
  >
63
64
  {#if header}
64
- <rk-header>{@render header()}</rk-header>
65
+ <div data-list-header>{@render header()}</div>
65
66
  {/if}
66
- <rk-body>
67
+ <div data-list-body>
67
68
  {#if items.length === 0}
68
69
  {#if empty}
69
70
  {@render empty()}
70
71
  {:else}
71
- <rk-message>No items found.</rk-message>
72
+ <p>No items found.</p>
72
73
  {/if}
73
74
  {:else}
74
75
  <ListBody
@@ -81,8 +82,8 @@
81
82
  {snippets}
82
83
  />
83
84
  {/if}
84
- </rk-body>
85
+ </div>
85
86
  {#if footer}
86
- <rk-footer>{@render footer()}</rk-footer>
87
+ <div data-list-footer>{@render footer()}</div>
87
88
  {/if}
88
- </rk-list>
89
+ </div>
@@ -22,7 +22,8 @@
22
22
  {@const template = getSnippet(snippets, fm.get('snippet', item, 'stub'))}
23
23
  {@const pathKey = getKeyFromPath([...path, index])}
24
24
  {@const props = fm.get('props', item) || {}}
25
- <rk-list-item
25
+ <div
26
+ data-list-item
26
27
  role="option"
27
28
  data-path={pathKey}
28
29
  aria-selected={selectedKeys.has(pathKey)}
@@ -38,5 +39,5 @@
38
39
  <Item value={item} {fields} />
39
40
  {/if}
40
41
  </svelte:boundary>
41
- </rk-list-item>
42
+ </div>
42
43
  {/each}
package/src/Pill.svelte CHANGED
@@ -12,7 +12,7 @@
12
12
  * @property {boolean} [disabled]
13
13
  */
14
14
 
15
- /** @type {Props} */
15
+ /** @type {ListProps} */
16
16
  let {
17
17
  value,
18
18
  class: classes = '',
@@ -32,10 +32,10 @@
32
32
  </script>
33
33
 
34
34
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
35
- <rk-pill use:keyboard={keyMappings} onremove={handle} tabindex="0" class={classes}>
35
+ <div data-pill-root use:keyboard={keyMappings} onremove={handle} tabindex="0" class={classes}>
36
36
  <Item {value} {mapping}></Item>
37
37
  {#if removable}
38
38
  <Icon name="action-close" role="button" aria-label="Remove" {disabled} onclick={handle} small
39
39
  ></Icon>
40
40
  {/if}
41
- </rk-pill>
41
+ </div>
package/src/Select.svelte CHANGED
@@ -52,9 +52,6 @@
52
52
  }
53
53
  }
54
54
 
55
- // $: fields = { ...defaultFields, ...fields }
56
- // $: using = { default: Item, ...using }
57
- // $: activeIndex = options.findIndex((item) => item === value)
58
55
  let offsetTop = $derived(activeItem?.offsetTop + activeItem?.clientHeight ?? 0)
59
56
  </script>
60
57
 
package/src/Switch.svelte CHANGED
@@ -1,35 +1,37 @@
1
1
  <script>
2
2
  import { equals } from 'ramda'
3
- import { noop, FieldMapper } from '@rokkit/core'
4
3
  import { keyboard } from '@rokkit/actions'
4
+ import { Proxy } from '@rokkit/states'
5
5
  import Item from './Item.svelte'
6
- // import { defaultMapping } from './constants'
7
6
 
8
7
  /**
9
8
  * @typedef {Object} Props
10
- * @property {string} [class]
11
- * @property {any} value
12
- * @property {Array<any>} [options]
13
- * @property {FieldMapper} [mapping]
14
- * @property {boolean} [compact]
15
- * @property {boolean} [disabled]
9
+ * @property {string} [class]
10
+ * @property {any} value
11
+ * @property {import('@rokkit/core').FieldMapping} fields
12
+ * @property {Array<any>} [options]
13
+ * @property {boolean} [compact]
14
+ * @property {boolean} [disabled]
16
15
  */
17
16
 
18
17
  /** @type {Props} */
19
18
  let {
20
19
  class: classes = '',
21
20
  value = $bindable(),
21
+ description = 'Toggle Switch',
22
22
  options = [false, true],
23
23
  fields,
24
24
  compact = false,
25
25
  disabled = false,
26
- onchange = noop,
27
- stub,
26
+ onchange,
27
+ child,
28
28
  ...extra
29
29
  } = $props()
30
30
 
31
- // let cursor = $state([])
32
-
31
+ /**
32
+ * Toggles the value of the switch
33
+ * @param {number} direction - The direction to toggle the switch
34
+ */
33
35
  function toggle(direction = 1) {
34
36
  let nextIndex
35
37
  const index = options.indexOf(value)
@@ -43,6 +45,10 @@
43
45
  onchange(value)
44
46
  }
45
47
 
48
+ /**
49
+ *
50
+ * @param event
51
+ */
46
52
  function handleClick(event) {
47
53
  const index = event.target.closest('[data-path]').dataset.path
48
54
  value = options[index]
@@ -52,20 +58,25 @@
52
58
  next: ['ArrowRight', 'ArrowDown', ' ', 'Enter'],
53
59
  prev: ['ArrowLeft', 'ArrowUp']
54
60
  }
55
- // let useComponent = $derived(!options.every((item) => [false, true].includes(item)))
56
- // let mapper = new FieldMapper(fields)
61
+
62
+ let childSnippet = $derived(child ? child : defaultChild)
57
63
  </script>
58
64
 
65
+ {#snippet defaultChild(proxy)}
66
+ <Item {proxy} />
67
+ {/snippet}
68
+
59
69
  {#if !Array.isArray(options) || options.length < 2}
60
- <rk-error>Items should be an array with at least two items.</rk-error>
70
+ <div data-error>Items should be an array with at least two items.</div>
61
71
  {:else}
62
72
  <!-- svelte-ignore a11y_click_events_have_key_events -->
63
- <rk-switch
73
+ <div
64
74
  class={classes}
65
- class:is-off={options.length === 2 && equals(value, options[0])}
66
- class:is-on={options.length === 2 && equals(value, options[1])}
67
- class:compact
68
- aria-label="Toggle Switch"
75
+ data-switch-root
76
+ data-switch-off={options.length === 2 && equals(value, options[0])}
77
+ data-switch-on={options.length === 2 && equals(value, options[1])}
78
+ data-switch-compact={compact}
79
+ aria-label={description}
69
80
  aria-orientation="horizontal"
70
81
  aria-disabled={disabled}
71
82
  tabindex="0"
@@ -75,19 +86,21 @@
75
86
  onprev={() => toggle(-1)}
76
87
  onclick={handleClick}
77
88
  >
78
- {#each options as item, index (item)}
79
- <!-- {@const Template = getSnippet(extra, mapper.get('snippet', item), stub)} -->
80
- <rk-item class="relative" role="option" aria-selected={equals(item, value)} data-path={index}>
89
+ {#each options as item, index (index)}
90
+ {@const proxy = new Proxy(item, fields)}
91
+ <div
92
+ data-switch-item
93
+ class="relative"
94
+ role="option"
95
+ aria-selected={equals(item, value)}
96
+ data-path={index}
97
+ >
81
98
  {#if equals(item, value)}
82
- <rk-indicator class="absolute bottom-0 left-0 right-0 top-0"></rk-indicator>
99
+ <div data-switch-mark class="absolute bottom-0 left-0 right-0 top-0"></div>
83
100
  {/if}
84
- {#if stub}
85
- {@render stub(item, fields)}
86
- <!-- <Template value={item} {fields} /> -->
87
- {:else}
88
- <Item value={item} {fields} />
89
- {/if}
90
- </rk-item>
101
+
102
+ {@render childSnippet?.(proxy)}
103
+ </div>
91
104
  {/each}
92
- </rk-switch>
105
+ </div>
93
106
  {/if}