@rokkit/forms 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/dist/src/forms-old/input/types.d.ts +7 -0
- package/dist/src/forms-old/lib/form.d.ts +95 -0
- package/dist/src/forms-old/lib/index.d.ts +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/input/index.d.ts +18 -0
- package/dist/src/lib/builder.svelte.d.ts +140 -0
- package/dist/src/lib/deprecated/nested.d.ts +48 -0
- package/dist/src/lib/deprecated/nested.spec.d.ts +1 -0
- package/dist/src/lib/deprecated/validator.d.ts +30 -0
- package/dist/src/lib/deprecated/validator.spec.d.ts +1 -0
- package/dist/src/lib/fields.d.ts +16 -0
- package/dist/src/lib/fields.spec.d.ts +1 -0
- package/dist/src/lib/index.d.ts +7 -0
- package/dist/src/lib/layout.d.ts +7 -0
- package/dist/src/lib/schema.d.ts +7 -0
- package/dist/src/lib/validation.d.ts +41 -0
- package/dist/src/types.d.ts +5 -0
- package/package.json +38 -0
- package/src/DataEditor.svelte +30 -0
- package/src/FieldLayout.svelte +48 -0
- package/src/FormRenderer.svelte +118 -0
- package/src/Input.svelte +75 -0
- package/src/InputField.svelte +55 -0
- package/src/ListEditor.svelte +44 -0
- package/src/NestedEditor.svelte +85 -0
- package/src/forms-old/CheckBox.svelte +56 -0
- package/src/forms-old/DataEditor.svelte +30 -0
- package/src/forms-old/FieldLayout.svelte +48 -0
- package/src/forms-old/Form.svelte +17 -0
- package/src/forms-old/Icon.svelte +76 -0
- package/src/forms-old/Item.svelte +25 -0
- package/src/forms-old/ListEditor.svelte +44 -0
- package/src/forms-old/Tabs.svelte +57 -0
- package/src/forms-old/Wrapper.svelte +12 -0
- package/src/forms-old/input/Input.svelte +17 -0
- package/src/forms-old/input/InputField.svelte +70 -0
- package/src/forms-old/input/InputSelect.svelte +23 -0
- package/src/forms-old/input/InputSwitch.svelte +19 -0
- package/src/forms-old/input/types.js +29 -0
- package/src/forms-old/lib/form.js +72 -0
- package/src/forms-old/lib/index.js +12 -0
- package/src/forms-old/mocks/CustomField.svelte +7 -0
- package/src/forms-old/mocks/CustomWrapper.svelte +8 -0
- package/src/forms-old/mocks/Register.svelte +25 -0
- package/src/index.js +7 -0
- package/src/inp/Input.svelte +17 -0
- package/src/inp/InputField.svelte +69 -0
- package/src/inp/InputSelect.svelte +23 -0
- package/src/inp/InputSwitch.svelte +19 -0
- package/src/input/InputCheckbox.svelte +74 -0
- package/src/input/InputColor.svelte +42 -0
- package/src/input/InputDate.svelte +54 -0
- package/src/input/InputDateTime.svelte +54 -0
- package/src/input/InputEmail.svelte +63 -0
- package/src/input/InputFile.svelte +45 -0
- package/src/input/InputMonth.svelte +54 -0
- package/src/input/InputNumber.svelte +57 -0
- package/src/input/InputPassword.svelte +60 -0
- package/src/input/InputRadio.svelte +60 -0
- package/src/input/InputRange.svelte +51 -0
- package/src/input/InputSelect.svelte +71 -0
- package/src/input/InputSwitch.svelte +29 -0
- package/src/input/InputTel.svelte +60 -0
- package/src/input/InputText.svelte +60 -0
- package/src/input/InputTextArea.svelte +59 -0
- package/src/input/InputTime.svelte +54 -0
- package/src/input/InputUrl.svelte +60 -0
- package/src/input/InputWeek.svelte +54 -0
- package/src/input/index.js +23 -0
- package/src/lib/Input.svelte +291 -0
- package/src/lib/builder.svelte.js +359 -0
- package/src/lib/deprecated/Form.svelte +17 -0
- package/src/lib/deprecated/FormRenderer.svelte +121 -0
- package/src/lib/deprecated/nested.js +192 -0
- package/src/lib/deprecated/nested.spec.js +512 -0
- package/src/lib/deprecated/validator.js +137 -0
- package/src/lib/deprecated/validator.spec.js +348 -0
- package/src/lib/fields.js +119 -0
- package/src/lib/fields.spec.js +250 -0
- package/src/lib/index.js +7 -0
- package/src/lib/layout.js +63 -0
- package/src/lib/schema.js +32 -0
- package/src/lib/validation.js +273 -0
- package/src/types.js +29 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Tabs } from 'bits-ui'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} TabGroupProps
|
|
6
|
+
* @property {string} [class] - Additional CSS class names
|
|
7
|
+
* @property {any[]} [options] Array of options to display
|
|
8
|
+
* @property {FieldMapping} [fields] - Field mappings for extracting data
|
|
9
|
+
* @property {any} [value] - Selected value (bindable)
|
|
10
|
+
* @property {number} [tabindex] - Tabindex for keyboard navigation
|
|
11
|
+
* @property {import('svelte').Snippet} [child] - Snippet for rendering individual items
|
|
12
|
+
* @property {import('svelte').Snippet} [children] Snippet for rendering content
|
|
13
|
+
* @property {Function} [onselect] - Callback when item is selected
|
|
14
|
+
*/
|
|
15
|
+
/** @type TabGroupProps */
|
|
16
|
+
let { options = [], value = $bindable(), fields, child, children, onchange } = $props()
|
|
17
|
+
|
|
18
|
+
// let selectedGroup = options.find
|
|
19
|
+
let tabOptions = $derived(options.map((option) => new Proxy(option, fields)))
|
|
20
|
+
let initialValue = $state()
|
|
21
|
+
let activeOption = $state()
|
|
22
|
+
let childSnippet = $derived(child ?? defaultChild)
|
|
23
|
+
|
|
24
|
+
$effect.pre(() => {
|
|
25
|
+
activeOption = tabOptions.find((proxy) => equals(proxy.value, value))
|
|
26
|
+
if (activeOption) initialValue = activeOption.id
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
function handleChange() {
|
|
30
|
+
activeOption = tabOptions.find((proxy) => equals(proxy.id, initialValue))
|
|
31
|
+
value = activeOption?.value
|
|
32
|
+
onchange?.(value)
|
|
33
|
+
// value = data
|
|
34
|
+
// onSelect?.(data)
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
{#snippet defaultChild(item)}
|
|
39
|
+
{item.get('text')}
|
|
40
|
+
{/snippet}
|
|
41
|
+
|
|
42
|
+
<Tabs.Root onValueChange={handleChange} bind:value={initialValue}>
|
|
43
|
+
<Tabs.List>
|
|
44
|
+
{#each tabOptions as tab (tab.id)}
|
|
45
|
+
<Tabs.Trigger value={tab.id}>
|
|
46
|
+
{@render childSnippet(tab)}
|
|
47
|
+
</Tabs.Trigger>
|
|
48
|
+
{/each}
|
|
49
|
+
</Tabs.List>
|
|
50
|
+
|
|
51
|
+
<!-- {#each tabOptions as tab (tab.id)} -->
|
|
52
|
+
<Tabs.Content>
|
|
53
|
+
{@render children()}
|
|
54
|
+
<!-- <ComparisonCharts {logs} groupBy={tab.value} {m} /> -->
|
|
55
|
+
</Tabs.Content>
|
|
56
|
+
<!-- {/each} -->
|
|
57
|
+
</Tabs.Root>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
let { class: className = '', type = 'vertical', title = '', children } = $props()
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<field-layout
|
|
6
|
+
class={className}
|
|
7
|
+
class:vertical={type === 'vertical'}
|
|
8
|
+
class:horizontal={type === 'horizontal'}
|
|
9
|
+
aria-label={title}
|
|
10
|
+
>
|
|
11
|
+
{@render children?.()}
|
|
12
|
+
</field-layout>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte'
|
|
3
|
+
import { types } from './types'
|
|
4
|
+
|
|
5
|
+
const registry = getContext('registry')
|
|
6
|
+
|
|
7
|
+
let { value, type = 'text', using = {}, onchange, onfocus, onblur, ...restProps } = $props()
|
|
8
|
+
|
|
9
|
+
using = { ...types, ...using, ...registry?.editors }
|
|
10
|
+
let Template = using[type]
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if type in using}
|
|
14
|
+
<Template bind:value {...restProps} {onchange} {onfocus} {onblur} />
|
|
15
|
+
{:else}
|
|
16
|
+
<error>Type "{type}" is not supported by Input</error>
|
|
17
|
+
{/if}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte'
|
|
3
|
+
import { pick, omit } from 'ramda'
|
|
4
|
+
import Icon from '../Icon.svelte'
|
|
5
|
+
import Input from './Input.svelte'
|
|
6
|
+
import { types } from './types'
|
|
7
|
+
|
|
8
|
+
const registry = getContext('registry')
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
class: className,
|
|
12
|
+
name,
|
|
13
|
+
value,
|
|
14
|
+
type,
|
|
15
|
+
required,
|
|
16
|
+
status,
|
|
17
|
+
disabled,
|
|
18
|
+
message,
|
|
19
|
+
using,
|
|
20
|
+
nolabel,
|
|
21
|
+
icon,
|
|
22
|
+
label,
|
|
23
|
+
description,
|
|
24
|
+
onchange,
|
|
25
|
+
...restProps
|
|
26
|
+
} = $props()
|
|
27
|
+
|
|
28
|
+
using = { ...types, ...registry, ...using }
|
|
29
|
+
let pass = status === 'pass'
|
|
30
|
+
let fail = status === 'fail'
|
|
31
|
+
let warn = status === 'warn'
|
|
32
|
+
let rootProps = pick(['id'], restProps)
|
|
33
|
+
let properties = {
|
|
34
|
+
required,
|
|
35
|
+
readOnly: disabled,
|
|
36
|
+
...omit(['id'], restProps),
|
|
37
|
+
name
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<input-field
|
|
42
|
+
{...rootProps}
|
|
43
|
+
class="flex flex-col input-{type} {className} "
|
|
44
|
+
class:disabled
|
|
45
|
+
class:pass
|
|
46
|
+
class:fail
|
|
47
|
+
class:warn
|
|
48
|
+
class:empty={!value}
|
|
49
|
+
>
|
|
50
|
+
{#if label && !nolabel && !['switch', 'checkbox'].includes(type)}
|
|
51
|
+
<label for={name} class:required>
|
|
52
|
+
{label}
|
|
53
|
+
</label>
|
|
54
|
+
{/if}
|
|
55
|
+
<field class="flex w-full flex-row items-center" aria-label={description ?? label ?? name}>
|
|
56
|
+
{#if icon}
|
|
57
|
+
<Icon name={icon} />
|
|
58
|
+
{/if}
|
|
59
|
+
{#if type === 'switch'}
|
|
60
|
+
<label for={name} class:required>{label}</label>
|
|
61
|
+
{/if}
|
|
62
|
+
<Input id={name} bind:value {type} {...properties} {using} {onchange} />
|
|
63
|
+
{#if type === 'checkbox'}
|
|
64
|
+
<label for={name} class:required>{label}</label>
|
|
65
|
+
{/if}
|
|
66
|
+
</field>
|
|
67
|
+
{#if message}
|
|
68
|
+
<message class={status}>{message}</message>
|
|
69
|
+
{/if}
|
|
70
|
+
</input-field>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getValue, defaultFields } from '@rokkit/core'
|
|
3
|
+
import Select from '../Select.svelte'
|
|
4
|
+
|
|
5
|
+
let { name, value, options = [], fields, onchange, ...restProps } = $props()
|
|
6
|
+
|
|
7
|
+
let selected = $state()
|
|
8
|
+
let configFields = $derived({ ...defaultFields, ...fields })
|
|
9
|
+
|
|
10
|
+
function handle(data) {
|
|
11
|
+
value = getValue(data.value, configFields)
|
|
12
|
+
onchange?.(data)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
$effect(() => {
|
|
16
|
+
if (value !== getValue(selected, configFields)) {
|
|
17
|
+
selected = options.find((option) => getValue(option, configFields) === value)
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<input {name} type="hidden" bind:value />
|
|
23
|
+
<Select name="" value={selected} {options} {fields} {...restProps} onchange={handle} />
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getValue, defaultFields } from '@rokkit/core'
|
|
3
|
+
import Switch from '../Switch.svelte'
|
|
4
|
+
|
|
5
|
+
let { name, value, options, fields, onchange, ...restProps } = $props()
|
|
6
|
+
// let selected = $state(null)
|
|
7
|
+
let configFields = $derived({ ...defaultFields, ...fields })
|
|
8
|
+
function handle(data) {
|
|
9
|
+
value = getValue(data.value, configFields)
|
|
10
|
+
onchange?.(data.value)
|
|
11
|
+
}
|
|
12
|
+
let selected = $derived(options.find((option) => getValue(option, configFields) === value))
|
|
13
|
+
// $effect(() => {
|
|
14
|
+
// selected = options.find((option) => getValue(option, configFields) === value)
|
|
15
|
+
// })
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<input {name} type="hidden" bind:value />
|
|
19
|
+
<Switch bind:value={selected} {options} {fields} {...restProps} onchange={handle} />
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { toHyphenCase } from '@rokkit/core'
|
|
2
|
+
// skipcq: JS-C1003 - Importing all components from atoms
|
|
3
|
+
import * as NativeInput from '@rokkit/forms'
|
|
4
|
+
// skipcq: JS-C1003 - Importing all components from molecules
|
|
5
|
+
import CheckBox from '../CheckBox.svelte'
|
|
6
|
+
|
|
7
|
+
// import InputSelect from './InputSelect.svelte'
|
|
8
|
+
// import InputSwitch from './InputSwitch.svelte'
|
|
9
|
+
|
|
10
|
+
function extractComponentMap(components, prefix = /^Input/) {
|
|
11
|
+
return Object.entries(components).reduce(
|
|
12
|
+
(acc, [name, component]) => ({
|
|
13
|
+
...acc,
|
|
14
|
+
[toHyphenCase(name.replace(prefix, ''))]: component
|
|
15
|
+
}),
|
|
16
|
+
{}
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
const native = extractComponentMap(NativeInput)
|
|
20
|
+
|
|
21
|
+
export const types = {
|
|
22
|
+
string: NativeInput.InputText,
|
|
23
|
+
integer: NativeInput.InputNumber,
|
|
24
|
+
boolean: CheckBox,
|
|
25
|
+
// enum: InputSelect,
|
|
26
|
+
phone: NativeInput.InputTel,
|
|
27
|
+
...native
|
|
28
|
+
// ...extractComponentMap({ InputSelect, InputSwitch })
|
|
29
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export const messages = {
|
|
2
|
+
required: '{name} is required',
|
|
3
|
+
email: '{name} should be a valid email address',
|
|
4
|
+
url: '{name} should be a valid URL',
|
|
5
|
+
color: '{name} should be a valid color',
|
|
6
|
+
number: '{name} should be a valid number',
|
|
7
|
+
min: '{name} should be greater than or equal to {min}',
|
|
8
|
+
max: '{name} should be less than or equal to {max}',
|
|
9
|
+
pattern: '{name} should match the pattern {pattern}',
|
|
10
|
+
exclusiveMin: '{name} should be greater than {min}',
|
|
11
|
+
exclusiveMax: '{name} should be less than {max}',
|
|
12
|
+
minLength: '{name} should be at least {minLength} characters',
|
|
13
|
+
maxLength: '{name} should be at most {maxLength} characters',
|
|
14
|
+
minItems: '{name} should have at least {minItems} items',
|
|
15
|
+
maxItems: '{name} should have at most {maxItems} items',
|
|
16
|
+
uniqueItems: '{name} should have unique items',
|
|
17
|
+
contains: '{name} should contain {contains}',
|
|
18
|
+
exclude: '{name} should not contain {exclude}',
|
|
19
|
+
integer: '{name} should be an integer'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const dataTypes = {
|
|
23
|
+
integer: {
|
|
24
|
+
editor: 'inputText',
|
|
25
|
+
props: { type: 'number', step: 1 },
|
|
26
|
+
availableProps: ['min', 'max']
|
|
27
|
+
},
|
|
28
|
+
number: {
|
|
29
|
+
editor: 'inputText',
|
|
30
|
+
props: { type: 'number', step: 0.01 },
|
|
31
|
+
availableProps: ['min', 'max']
|
|
32
|
+
},
|
|
33
|
+
range: {
|
|
34
|
+
editor: 'inputRange',
|
|
35
|
+
props: { type: 'range' }
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
string: {
|
|
39
|
+
default: 'inputText',
|
|
40
|
+
text: 'inputText',
|
|
41
|
+
password: 'inputPassword',
|
|
42
|
+
email: 'inputEmail',
|
|
43
|
+
url: 'inputUrl',
|
|
44
|
+
tel: 'inputTel',
|
|
45
|
+
date: 'inputDate',
|
|
46
|
+
'datetime-local': 'inputDateTimeLocal',
|
|
47
|
+
time: 'inputTime',
|
|
48
|
+
week: 'inputWeek',
|
|
49
|
+
month: 'inputMonth',
|
|
50
|
+
file: 'inputFile',
|
|
51
|
+
hidden: 'inputHidden',
|
|
52
|
+
color: 'inputColor',
|
|
53
|
+
colorpicker: 'inputColorPicker'
|
|
54
|
+
},
|
|
55
|
+
enum: {
|
|
56
|
+
default: 'inputSelect',
|
|
57
|
+
select: 'inputSelect',
|
|
58
|
+
radio: 'inputRadio'
|
|
59
|
+
},
|
|
60
|
+
boolean: {
|
|
61
|
+
default: 'inputCheckbox',
|
|
62
|
+
checkbox: 'inputCheckbox',
|
|
63
|
+
switch: 'inputSwitch',
|
|
64
|
+
radio: 'inputRadio'
|
|
65
|
+
},
|
|
66
|
+
array: {
|
|
67
|
+
default: 'inputArray'
|
|
68
|
+
},
|
|
69
|
+
object: {
|
|
70
|
+
default: 'inputObject'
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { messages, dataTypes } from './form'
|
|
2
|
+
export { deriveSchemaFromValue } from './schema'
|
|
3
|
+
export { deriveLayoutFromValue } from './layout'
|
|
4
|
+
export { getSchemaWithLayout, findAttributeByPath } from './fields'
|
|
5
|
+
export {
|
|
6
|
+
deriveNestedSchema,
|
|
7
|
+
flattenAttributes,
|
|
8
|
+
flattenObject,
|
|
9
|
+
flattenElement,
|
|
10
|
+
generateIndex,
|
|
11
|
+
generateTreeTable
|
|
12
|
+
} from './nested'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { setContext } from 'svelte'
|
|
3
|
+
// import { writable } from 'svelte/store'
|
|
4
|
+
import Wrapper from '..//Wrapper.svelte'
|
|
5
|
+
import Item from '../Item.svelte'
|
|
6
|
+
import Tabs from '../Tabs.svelte'
|
|
7
|
+
const registry = $state({})
|
|
8
|
+
setContext('registry', registry)
|
|
9
|
+
|
|
10
|
+
let { Template, using, properties } = $props()
|
|
11
|
+
|
|
12
|
+
using = {
|
|
13
|
+
editors: {},
|
|
14
|
+
components: {},
|
|
15
|
+
wrappers: {},
|
|
16
|
+
navigators: {},
|
|
17
|
+
...using
|
|
18
|
+
}
|
|
19
|
+
registry.editors = { ...using.editors }
|
|
20
|
+
registry.components = { default: Item, ...using.components }
|
|
21
|
+
registry.wrappers = { default: Wrapper, ...using.wrappers }
|
|
22
|
+
registry.navigators = { default: Tabs, ...using.navigators }
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<Template {...properties} />
|
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FormBuilder } from './lib/builder.svelte.js'
|
|
2
|
+
// Enhanced Input Components
|
|
3
|
+
export { default as FormRenderer } from './FormRenderer.svelte'
|
|
4
|
+
export { default as Input } from './Input.svelte'
|
|
5
|
+
export { default as InputField } from './InputField.svelte'
|
|
6
|
+
|
|
7
|
+
export * from './input'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte'
|
|
3
|
+
import { types } from './types'
|
|
4
|
+
|
|
5
|
+
const registry = getContext('registry')
|
|
6
|
+
|
|
7
|
+
let { value, type = 'text', using = {}, ...restProps } = $props()
|
|
8
|
+
|
|
9
|
+
using = { ...types, ...using, ...registry?.editors }
|
|
10
|
+
let Template = using[type]
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if type in using}
|
|
14
|
+
<Template bind:value {...restProps} on:change on:focus on:blur />
|
|
15
|
+
{:else}
|
|
16
|
+
<error>Type "{type}" is not supported by Input</error>
|
|
17
|
+
{/if}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte'
|
|
3
|
+
import { pick, omit } from 'ramda'
|
|
4
|
+
import Icon from '../Icon.svelte'
|
|
5
|
+
import Input from './Input.svelte'
|
|
6
|
+
import { types } from './types'
|
|
7
|
+
|
|
8
|
+
const registry = getContext('registry')
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
class: className,
|
|
12
|
+
name,
|
|
13
|
+
value,
|
|
14
|
+
type,
|
|
15
|
+
required,
|
|
16
|
+
status,
|
|
17
|
+
disabled,
|
|
18
|
+
message,
|
|
19
|
+
using,
|
|
20
|
+
nolabel,
|
|
21
|
+
icon,
|
|
22
|
+
label,
|
|
23
|
+
description,
|
|
24
|
+
...restProps
|
|
25
|
+
} = $props()
|
|
26
|
+
|
|
27
|
+
using = { ...types, ...registry, ...using }
|
|
28
|
+
let pass = status === 'pass'
|
|
29
|
+
let fail = status === 'fail'
|
|
30
|
+
let warn = status === 'warn'
|
|
31
|
+
let rootProps = pick(['id'], restProps)
|
|
32
|
+
let properties = {
|
|
33
|
+
required,
|
|
34
|
+
readOnly: disabled,
|
|
35
|
+
...omit(['id'], restProps),
|
|
36
|
+
name
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<input-field
|
|
41
|
+
{...rootProps}
|
|
42
|
+
class="flex flex-col input-{type} {className} "
|
|
43
|
+
class:disabled
|
|
44
|
+
class:pass
|
|
45
|
+
class:fail
|
|
46
|
+
class:warn
|
|
47
|
+
class:empty={!value}
|
|
48
|
+
>
|
|
49
|
+
{#if label && !nolabel && !['switch', 'checkbox'].includes(type)}
|
|
50
|
+
<label for={name} class:required>
|
|
51
|
+
{label}
|
|
52
|
+
</label>
|
|
53
|
+
{/if}
|
|
54
|
+
<field class="flex w-full flex-row items-center" aria-label={description ?? label ?? name}>
|
|
55
|
+
{#if icon}
|
|
56
|
+
<Icon name={icon} />
|
|
57
|
+
{/if}
|
|
58
|
+
{#if type === 'switch'}
|
|
59
|
+
<label for={name} class:required>{label}</label>
|
|
60
|
+
{/if}
|
|
61
|
+
<Input id={name} bind:value {type} {...properties} {using} on:change />
|
|
62
|
+
{#if type === 'checkbox'}
|
|
63
|
+
<label for={name} class:required>{label}</label>
|
|
64
|
+
{/if}
|
|
65
|
+
</field>
|
|
66
|
+
{#if message}
|
|
67
|
+
<message class={status}>{message}</message>
|
|
68
|
+
{/if}
|
|
69
|
+
</input-field>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getValue, defaultFields } from '@rokkit/core'
|
|
3
|
+
import Select from '../Select.svelte'
|
|
4
|
+
|
|
5
|
+
let { name, value, options = [], fields, onchange, ...restProps } = $props()
|
|
6
|
+
|
|
7
|
+
let selected = $state()
|
|
8
|
+
let configFields = $derived({ ...defaultFields, ...fields })
|
|
9
|
+
|
|
10
|
+
function handle(data) {
|
|
11
|
+
value = getValue(data.value, configFields)
|
|
12
|
+
onchange?.(data)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
$effect(() => {
|
|
16
|
+
if (value !== getValue(selected, configFields)) {
|
|
17
|
+
selected = options.find((option) => getValue(option, configFields) === value)
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<input {name} type="hidden" bind:value />
|
|
23
|
+
<Select name="" value={selected} {options} {fields} {...restProps} onchange={handle} />
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getValue, defaultFields } from '@rokkit/core'
|
|
3
|
+
import Switch from '../Switch.svelte'
|
|
4
|
+
|
|
5
|
+
let { name, value, options, fields, ...restProps } = $props()
|
|
6
|
+
// let selected = $state(null)
|
|
7
|
+
let configFields = $derived({ ...defaultFields, ...fields })
|
|
8
|
+
function handle(data) {
|
|
9
|
+
value = getValue(data.value, configFields)
|
|
10
|
+
dispatch('change', data.value)
|
|
11
|
+
}
|
|
12
|
+
let selected = $derived(options.find((option) => getValue(option, configFields) === value))
|
|
13
|
+
// $effect(() => {
|
|
14
|
+
// selected = options.find((option) => getValue(option, configFields) === value)
|
|
15
|
+
// })
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<input {name} type="hidden" bind:value />
|
|
19
|
+
<Switch bind:value={selected} {options} {fields} {...restProps} onchange={handle} />
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Icon } from '@rokkit/ui'
|
|
3
|
+
import { defaultStateIcons } from '@rokkit/core'
|
|
4
|
+
import { isNil } from 'ramda'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {ObjectIcon} StateIcons
|
|
8
|
+
* @property {string} checked
|
|
9
|
+
* @property {string} unchecked
|
|
10
|
+
* @property {string} unknown
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} InputCheckboxProps
|
|
15
|
+
* @property {null|Boolean} value
|
|
16
|
+
* @property {'default'|'custom'} variant -
|
|
17
|
+
* @property {StateIcons} icons
|
|
18
|
+
* @property {Function} onchange
|
|
19
|
+
* @property {Function} onfocus
|
|
20
|
+
* @property {Function} onblur
|
|
21
|
+
* @property {boolean} required
|
|
22
|
+
* @property {boolean} disabled
|
|
23
|
+
* @property {string} name
|
|
24
|
+
* @property {string} id
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @type {InputCheckboxProps & { [key: string]: any }} */
|
|
28
|
+
let {
|
|
29
|
+
value = $bindable(),
|
|
30
|
+
variant = 'default',
|
|
31
|
+
icons,
|
|
32
|
+
onchange,
|
|
33
|
+
onfocus,
|
|
34
|
+
onblur,
|
|
35
|
+
required,
|
|
36
|
+
disabled,
|
|
37
|
+
name,
|
|
38
|
+
id,
|
|
39
|
+
...rest
|
|
40
|
+
} = $props()
|
|
41
|
+
|
|
42
|
+
function handleChange(event) {
|
|
43
|
+
value = Boolean(event.target.checked)
|
|
44
|
+
onchange?.(value)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function toggle() {
|
|
48
|
+
value = !Boolean(value)
|
|
49
|
+
onchange?.(value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let checked = $derived(Boolean(value))
|
|
53
|
+
let stateIcons = $derived({ ...defaultStateIcons.checkbox, ...icons })
|
|
54
|
+
let icon = $derived(stateIcons[isNil(value) ? 'unknown' : value ? 'checked' : 'unchecked'])
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div data-checkbox-root data-variant={variant}>
|
|
58
|
+
<input
|
|
59
|
+
type="checkbox"
|
|
60
|
+
hidden={variant !== 'default'}
|
|
61
|
+
{required}
|
|
62
|
+
{disabled}
|
|
63
|
+
{name}
|
|
64
|
+
{id}
|
|
65
|
+
{checked}
|
|
66
|
+
onchange={handleChange}
|
|
67
|
+
{onfocus}
|
|
68
|
+
{onblur}
|
|
69
|
+
{...rest}
|
|
70
|
+
/>
|
|
71
|
+
{#if variant !== 'default'}
|
|
72
|
+
<Icon name={icon} data-checkbox-icon role="button" onclick={toggle} />
|
|
73
|
+
{/if}
|
|
74
|
+
</div>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {Object} InputColorProps
|
|
4
|
+
* @property {string} value
|
|
5
|
+
* @property {Function} onchange
|
|
6
|
+
* @property {Function} onfocus
|
|
7
|
+
* @property {Function} onblur
|
|
8
|
+
* @property {boolean} required
|
|
9
|
+
* @property {boolean} disabled
|
|
10
|
+
* @property {string} name
|
|
11
|
+
* @property {string} id
|
|
12
|
+
* @property {string} autocomplete
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** @type {InputColorProps & { [key: string]: any }} */
|
|
16
|
+
let {
|
|
17
|
+
value = $bindable(),
|
|
18
|
+
onchange,
|
|
19
|
+
onfocus,
|
|
20
|
+
onblur,
|
|
21
|
+
required,
|
|
22
|
+
disabled,
|
|
23
|
+
name,
|
|
24
|
+
id,
|
|
25
|
+
autocomplete,
|
|
26
|
+
...rest
|
|
27
|
+
} = $props()
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<input
|
|
31
|
+
bind:value
|
|
32
|
+
type="color"
|
|
33
|
+
{required}
|
|
34
|
+
{disabled}
|
|
35
|
+
{name}
|
|
36
|
+
{id}
|
|
37
|
+
{autocomplete}
|
|
38
|
+
{onchange}
|
|
39
|
+
{onfocus}
|
|
40
|
+
{onblur}
|
|
41
|
+
{...rest}
|
|
42
|
+
/>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {Object} InputDateProps
|
|
4
|
+
* @property {string} value
|
|
5
|
+
* @property {Function} onchange
|
|
6
|
+
* @property {Function} onfocus
|
|
7
|
+
* @property {Function} onblur
|
|
8
|
+
* @property {string} min
|
|
9
|
+
* @property {string} max
|
|
10
|
+
* @property {number} step
|
|
11
|
+
* @property {boolean} required
|
|
12
|
+
* @property {boolean} disabled
|
|
13
|
+
* @property {boolean} readonly
|
|
14
|
+
* @property {string} name
|
|
15
|
+
* @property {string} id
|
|
16
|
+
* @property {string} autocomplete
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** @type {InputDateProps & { [key: string]: any }} */
|
|
20
|
+
let {
|
|
21
|
+
value = $bindable(),
|
|
22
|
+
onchange,
|
|
23
|
+
onfocus,
|
|
24
|
+
onblur,
|
|
25
|
+
min,
|
|
26
|
+
max,
|
|
27
|
+
step,
|
|
28
|
+
required,
|
|
29
|
+
disabled,
|
|
30
|
+
readonly,
|
|
31
|
+
name,
|
|
32
|
+
id,
|
|
33
|
+
autocomplete,
|
|
34
|
+
...rest
|
|
35
|
+
} = $props()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<input
|
|
39
|
+
bind:value
|
|
40
|
+
type="date"
|
|
41
|
+
{min}
|
|
42
|
+
{max}
|
|
43
|
+
{step}
|
|
44
|
+
{required}
|
|
45
|
+
{disabled}
|
|
46
|
+
{readonly}
|
|
47
|
+
{name}
|
|
48
|
+
{id}
|
|
49
|
+
{autocomplete}
|
|
50
|
+
{onchange}
|
|
51
|
+
{onfocus}
|
|
52
|
+
{onblur}
|
|
53
|
+
{...rest}
|
|
54
|
+
/>
|