diff --git a/docs/src/routes/components/field.svelte b/docs/src/routes/components/field.svelte index 8b1a6e8..2a630c3 100644 --- a/docs/src/routes/components/field.svelte +++ b/docs/src/routes/components/field.svelte @@ -8,7 +8,7 @@ + + + +

+ +

+
+ + + +

+ +

+
+ +
+ + +
+
+
+
+
+
+ +
+ + +
+
+
`}> +
+ + +

+ +

+
+ + + +

+ +

+
+ +
+ + +
+
+
+
+
+
+ +
+ + +
+
+
+
+ + +
+ +

Groups

+ +Use the grouped property to group controls together. Use the expanded property to make a control take up remaining space. + + + import { Button, Field, Input } from 'svelma' + + + + +

+ +

+
+ + + +

+ +

+
`}> +
+ + +

+ +

+
+ + + +

+ +

+
+
+
+ +
+ +

Nested Groups

+ +You can nest fields inside fields. You have to use the expanded property on the Field to fill up the remaining space. + + + import { Button, Field, Input } from 'svelma' + + + + + + + + + + + + + + +`}> +
+ + + + + + + + + + + + + +
+
+ +
+ +

Responsive Groups

+ +Add groupMultiline property to allow controls to fill up multiple lines. + + + import { Button, Field, Input } from 'svelma' + + + + + {#each Array(30).fill().map((x, i) => i+1) as num} +
+ +
+ {/each} +
`}> +
+ + + {#each Array(30).fill().map((x, i) => i+1) as num} +
+ +
+ {/each} +
+
+
+ +
+ +

Positions

+ +Use position property to align Field horizontally. + + + import { Button, Field, Input } from 'svelma' + + + + +
+
+ + + +
+
`}> +
+ + +
+
+ + + +
+
+
+
+ \ No newline at end of file diff --git a/docs/src/routes/components/jsdocs.json b/docs/src/routes/components/jsdocs.json index 0609f5c..f5ab19a 100644 --- a/docs/src/routes/components/jsdocs.json +++ b/docs/src/routes/components/jsdocs.json @@ -661,6 +661,36 @@ "columnno": 2, "path": "src/components" }, + "description": "Type (color) of the field and help message. Also adds a matching icon.", + "type": [ + "String" + ], + "optional": true, + "name": "type", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "String" + ] + }, + "optional": true, + "name": "type" + }, + "kind": "prop", + "values": "is-white, is-black, is-light, is-dark, is-primary, is-info, is-success, is-warning, is-danger", + "longname": "module:Field~type", + "scope": "inner", + "memberof": "module:Field", + "___s": true + }, + { + "meta": { + "filename": "Field.svelte", + "lineno": 12, + "columnno": 2, + "path": "src/components" + }, "description": "Label for input", "type": [ "String" @@ -687,16 +717,16 @@ { "meta": { "filename": "Field.svelte", - "lineno": 11, + "lineno": 17, "columnno": 2, "path": "src/components" }, - "description": "Type (color of control)", + "description": "Same as native for on label", "type": [ "String" ], "optional": true, - "name": "type", + "name": "labelFor", "_isSvelteDoc": true, "_svelteProps": { "type": { @@ -705,19 +735,19 @@ ] }, "optional": true, - "name": "type" + "name": "labelFor" }, "kind": "prop", - "values": "is-white, is-black, is-light, is-dark, is-primary, is-info, is-success, is-warning, is-danger", - "longname": "module:Field~type", + "longname": "module:Field~labelFor", "scope": "inner", "memberof": "module:Field", - "___s": true + "___s": true, + "values": "" }, { "meta": { "filename": "Field.svelte", - "lineno": 17, + "lineno": 22, "columnno": 2, "path": "src/components" }, @@ -743,6 +773,126 @@ "memberof": "module:Field", "___s": true, "values": "" + }, + { + "meta": { + "filename": "Field.svelte", + "lineno": 27, + "columnno": 2, + "path": "src/components" + }, + "description": "Direct child components/elements of Field will be grouped horizontally", + "type": [ + "Boolean" + ], + "defaultvalue": false, + "name": "grouped", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "Boolean" + ] + }, + "defaultvalue": false, + "name": "grouped" + }, + "kind": "prop", + "longname": "module:Field~grouped", + "scope": "inner", + "memberof": "module:Field", + "___s": true, + "values": "" + }, + { + "meta": { + "filename": "Field.svelte", + "lineno": 32, + "columnno": 2, + "path": "src/components" + }, + "description": "Allow grouped controls to cover multiple lines", + "type": [ + "Boolean" + ], + "defaultvalue": false, + "name": "groupMultiline", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "Boolean" + ] + }, + "defaultvalue": false, + "name": "groupMultiline" + }, + "kind": "prop", + "longname": "module:Field~groupMultiline", + "scope": "inner", + "memberof": "module:Field", + "___s": true, + "values": "" + }, + { + "meta": { + "filename": "Field.svelte", + "lineno": 37, + "columnno": 2, + "path": "src/components" + }, + "description": "Alter the alignment of the field", + "type": [ + "String" + ], + "optional": true, + "name": "position", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "String" + ] + }, + "optional": true, + "name": "position" + }, + "kind": "prop", + "values": "is-centered, is-right", + "longname": "module:Field~position", + "scope": "inner", + "memberof": "module:Field", + "___s": true + }, + { + "meta": { + "filename": "Field.svelte", + "lineno": 43, + "columnno": 2, + "path": "src/components" + }, + "description": "Automatically attach child controls together", + "type": [ + "Boolean" + ], + "defaultvalue": true, + "name": "addons", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "Boolean" + ] + }, + "defaultvalue": true, + "name": "addons" + }, + "kind": "prop", + "longname": "module:Field~addons", + "scope": "inner", + "memberof": "module:Field", + "___s": true, + "values": "" } ], "Icon": [], @@ -848,11 +998,41 @@ "columnno": 2, "path": "src/components" }, + "description": "Makes input full-width when inside a grouped or addon field", + "type": [ + "boolean" + ], + "defaultvalue": false, + "name": "expanded", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "boolean" + ] + }, + "defaultvalue": false, + "name": "expanded" + }, + "kind": "prop", + "longname": "module:Input~expanded", + "scope": "inner", + "memberof": "module:Input", + "___s": true, + "values": "" + }, + { + "meta": { + "filename": "Input.svelte", + "lineno": 29, + "columnno": 2, + "path": "src/components" + }, "description": "Show the password reveal toggle button", "type": [ "boolean" ], - "optional": true, + "defaultvalue": false, "name": "passwordReveal", "_isSvelteDoc": true, "_svelteProps": { @@ -861,7 +1041,7 @@ "boolean" ] }, - "optional": true, + "defaultvalue": false, "name": "passwordReveal" }, "kind": "prop", @@ -874,7 +1054,7 @@ { "meta": { "filename": "Input.svelte", - "lineno": 29, + "lineno": 34, "columnno": 2, "path": "src/components" }, @@ -904,7 +1084,7 @@ { "meta": { "filename": "Input.svelte", - "lineno": 34, + "lineno": 39, "columnno": 2, "path": "src/components" }, @@ -936,7 +1116,7 @@ { "meta": { "filename": "Input.svelte", - "lineno": 39, + "lineno": 44, "columnno": 2, "path": "src/components" }, @@ -968,7 +1148,67 @@ { "meta": { "filename": "Input.svelte", - "lineno": 44, + "lineno": 49, + "columnno": 2, + "path": "src/components" + }, + "description": "Show this icon on left side of input", + "type": [ + "String" + ], + "optional": true, + "name": "icon", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "String" + ] + }, + "optional": true, + "name": "icon" + }, + "kind": "prop", + "longname": "module:Input~icon", + "scope": "inner", + "memberof": "module:Input", + "___s": true, + "values": "" + }, + { + "meta": { + "filename": "Input.svelte", + "lineno": 54, + "columnno": 2, + "path": "src/components" + }, + "description": "Fontawesome icon pack to use. By default the Icon component uses fas", + "type": [ + "String" + ], + "optional": true, + "name": "iconPack", + "_isSvelteDoc": true, + "_svelteProps": { + "type": { + "names": [ + "String" + ] + }, + "optional": true, + "name": "iconPack" + }, + "kind": "prop", + "values": "fas, fab, etc...", + "longname": "module:Input~iconPack", + "scope": "inner", + "memberof": "module:Input", + "___s": true + }, + { + "meta": { + "filename": "Input.svelte", + "lineno": 60, "columnno": 2, "path": "src/components" }, diff --git a/src/components/Field.svelte b/src/components/Field.svelte index ee84074..84bb0fb 100644 --- a/src/components/Field.svelte +++ b/src/components/Field.svelte @@ -2,45 +2,121 @@ import { onMount, setContext } from 'svelte' import { omit } from '../utils' + /** Type (color) of the field and help message. Also adds a matching icon. + * @svelte-prop {String} [type] + * @values $$colors$$ + * */ + export let type = '' + /** Label for input * @svelte-prop {String} [label] * */ export let label = null - /** Type (color of control) - * @svelte-prop {String} [type] - * @values $$colors$$ + /** Same as native for on label + * @svelte-prop {String} [labelFor] * */ - export let type = '' + export let labelFor = '' /** Message to show beneath input * @svelte-prop {String} [message] * */ export let message = '' - export let labelFor = '' + /** Direct child components/elements of Field will be grouped horizontally + * @svelte-prop {Boolean} grouped=false + * */ + export let grouped = false + + /** Allow grouped controls to cover multiple lines + * @svelte-prop {Boolean} groupMultiline=false + * */ + export let groupMultiline = false + + /** Alter the alignment of the field + * @svelte-prop {String} [position] + * @values is-centered, is-right + * */ + export let position = '' + + /** Automatically attach child controls together + * @svelte-prop {Boolean} addons=true + * */ + export let addons = true + + export let expanded = false setContext('type', () => type) + let el + let labelEl + let messageEl + let fieldType = '' let hasIcons = false let iconType = '' + let mounted = false + let newPosition = '' + // Determine the icon type $: { if (['is-danger', 'is-success'].includes(type)) { - hasIcons = true iconType = type } } - $: props = { ...omit($$props, 'class') } + $: { + if (grouped) fieldType = 'is-grouped' + else if (mounted) { + const childNodes = Array.prototype.filter.call(el.children, c => !([labelEl, messageEl].includes(c))) + if (childNodes.length > 1 && addons) { + fieldType = 'has-addons' + } + } + } + + // Update has-addons-* or is-grouped-* classes based on position prop + $: { + if (position) { + const pos = position.split('-') + if (pos.length >= 1) { + const prefix = grouped ? 'is-grouped-' : 'has-addons-' + newPosition = prefix + pos[1] + } + } + } + + $: props = { ...omit($$props, 'addons', 'class', 'expanded', 'grouped', 'label', 'labelFor', 'position', 'type') } + + onMount(() => { + mounted = true + }) -
+ + +
{#if label} - + {/if} {#if message} -

{message}

+

{message}

{/if}
diff --git a/src/components/Icon.svelte b/src/components/Icon.svelte index 8c6b6f4..9ec925f 100644 --- a/src/components/Icon.svelte +++ b/src/components/Icon.svelte @@ -6,6 +6,7 @@ export let customClass = '' export let customSize = '' export let isClickable = false + export let isLeft = false export let isRight = false let newCustomSize = '' @@ -49,6 +50,6 @@ } - + diff --git a/src/components/Input.svelte b/src/components/Input.svelte index f1c889b..8a24f65 100644 --- a/src/components/Input.svelte +++ b/src/components/Input.svelte @@ -20,8 +20,13 @@ * */ export let size = '' + /** Makes input full-width when inside a grouped or addon field + * @svelte-prop {boolean} expanded=false + * */ + export let expanded = false + /** Show the password reveal toggle button - * @svelte-prop {boolean} [passwordReveal] + * @svelte-prop {boolean} passwordReveal=false * */ export let passwordReveal = false @@ -40,6 +45,17 @@ * */ export let loading = false + /** Show this icon on left side of input + * @svelte-prop {String} [icon] + * */ + export let icon = '' + + /** Fontawesome icon pack to use. By default the Icon component uses fas + * @svelte-prop {String} [iconPack] + * @values fas, fab, etc... + * */ + export let iconPack = '' + /** Input is disabled * @svelte-prop {boolean} [disabled=false] * */ @@ -59,6 +75,7 @@ $: props = { ...omit($$props, 'class', 'value', 'type', 'size', 'passwordReveal', 'hasCounter', 'loading', 'disabled'), } + $: hasIconLeft = !!icon $: hasIconRight = passwordReveal || loading || statusType $: passwordVisibleIcon = isPasswordVisible ? 'eye-slash' : 'eye' $: { @@ -113,16 +130,14 @@ } -
+
{#if type !== 'textarea'} {/if} + {#if icon} + + {/if} + {#if !loading && (passwordReveal || statusType)}